Die Oberfläche ist lokalisiert; Skill-Beschreibungen und -Dokumente werden per KI automatisch in Ihre Sprache übersetzt. Code, Befehle, Pfade und Fachbegriffe bleiben im Original, maßgeblich ist das Dokument des Autors.
Skills entdecken
Daten und Forschung · SKILL.md

cobol-developer

cobol-developer

Use when reading, writing, debugging, or modernizing COBOL programs — divisions and sections, data types (PIC clauses, COMP/COMP-3/DISPLAY), file handling (QSAM/VSAM/KSDS/RRDS), PERFORM and paragraph structure, COPY/REPLACE, embedded SQL (EXEC SQL), CICS programming (EXEC CICS), batch JCL integration, debugging (CEDF/Xpediter), and COBOL modernization patte…

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill-Dokumentation

GitHub

name: cobol-developer description: Use when reading, writing, debugging, or modernizing COBOL programs — divisions and sections, data types (PIC clauses, COMP/COMP-3/DISPLAY), file handling (QSAM/VSAM/KSDS/RRDS), PERFORM and paragraph structure, COPY/REPLACE, embedded SQL (EXEC SQL), CICS programming (EXEC CICS), batch JCL integration, debugging (CEDF/Xpediter), and COBOL modernization patterns. Part of the ibm-mainframe skill family.

COBOL Developer Reference

Companion to ibm-mainframe (JCL/VSAM/utilities) and db2-mainframe (DB2 z/OS DBA). For Python mainframe connectivity see python-enterprise-connectors.


1. Program Structure

       IDENTIFICATION DIVISION.
       PROGRAM-ID. ORDPROC.
       AUTHOR. MAINTENANCE TEAM.
       DATE-WRITTEN. 2026-03-31.
      *================================================================*
      * ORDER PROCESSING - BATCH PROGRAM                               *
      *================================================================*

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SPECIAL-NAMES.
           DECIMAL-POINT IS COMMA.

       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT ORDER-FILE
               ASSIGN TO ORDIN
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-ORDER-FS.

           SELECT REPORT-FILE
               ASSIGN TO RPTOUT
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-REPORT-FS.

           SELECT CUSTOMER-FILE
               ASSIGN TO CUSTDB
               ORGANIZATION IS INDEXED
               ACCESS MODE IS RANDOM
               RECORD KEY IS CUST-KEY
               FILE STATUS IS WS-CUST-FS.

       DATA DIVISION.
       FILE SECTION.
       FD  ORDER-FILE
           RECORDING MODE IS F
           RECORD CONTAINS 200 CHARACTERS.
       01  ORDER-RECORD.
           05  ORD-ID              PIC 9(10).
           05  ORD-CUST-ID         PIC 9(8).
           05  ORD-DATE            PIC X(10).
           05  ORD-AMOUNT          PIC S9(11)V99 COMP-3.
           05  ORD-STATUS          PIC X(1).
               88  ORD-PENDING     VALUE 'P'.
               88  ORD-SHIPPED     VALUE 'S'.
               88  ORD-CANCELLED   VALUE 'C'.
           05  FILLER              PIC X(163).

       FD  REPORT-FILE
           RECORDING MODE IS F
           RECORD CONTAINS 132 CHARACTERS.
       01  REPORT-RECORD           PIC X(132).

       WORKING-STORAGE SECTION.
       01  WS-FILE-STATUS.
           05  WS-ORDER-FS        PIC XX VALUE SPACES.
           05  WS-REPORT-FS       PIC XX VALUE SPACES.
           05  WS-CUST-FS         PIC XX VALUE SPACES.

       01  WS-FLAGS.
           05  WS-EOF-FLAG        PIC X(1) VALUE 'N'.
               88  END-OF-FILE    VALUE 'Y'.
               88  NOT-END-OF-FILE VALUE 'N'.

       01  WS-COUNTERS.
           05  WS-READ-COUNT      PIC 9(9) COMP VALUE 0.
           05  WS-PROC-COUNT      PIC 9(9) COMP VALUE 0.
           05  WS-ERROR-COUNT     PIC 9(9) COMP VALUE 0.

       01  WS-TOTALS.
           05  WS-TOTAL-AMOUNT    PIC S9(15)V99 COMP-3
                                  VALUE ZERO.

       PROCEDURE DIVISION.
       0000-MAIN.
           PERFORM 1000-INITIALIZE
           PERFORM 2000-PROCESS UNTIL END-OF-FILE
           PERFORM 9000-TERMINATE
           GOBACK
           .

       1000-INITIALIZE.
           OPEN INPUT ORDER-FILE
           OPEN OUTPUT REPORT-FILE
           PERFORM 1100-READ-ORDER
           .

       1100-READ-ORDER.
           READ ORDER-FILE
               AT END SET END-OF-FILE TO TRUE
               NOT AT END ADD 1 TO WS-READ-COUNT
           END-READ
           .

       2000-PROCESS.
           EVALUATE TRUE
               WHEN ORD-PENDING
                   PERFORM 2100-PROCESS-PENDING
               WHEN ORD-SHIPPED
                   PERFORM 2200-PROCESS-SHIPPED
               WHEN OTHER
                   ADD 1 TO WS-ERROR-COUNT
           END-EVALUATE
           PERFORM 1100-READ-ORDER
           .

       9000-TERMINATE.
           CLOSE ORDER-FILE REPORT-FILE
           DISPLAY 'RECORDS READ:      ' WS-READ-COUNT
           DISPLAY 'RECORDS PROCESSED: ' WS-PROC-COUNT
           DISPLAY 'ERRORS:            ' WS-ERROR-COUNT
           .

2. Data Division Deep Dive

PIC Clauses

PICMeaningExample Value
PIC X(20)Alphanumeric, 20 chars"JOHN DOE "
PIC 9(5)Numeric display, 5 digits00123
PIC S9(7)V99Signed, 7 integer + 2 decimal+1234567.89
PIC S9(7)V99 COMP-3Packed decimal (BCD)4 bytes
PIC S9(9) COMPBinary (fullword)4 bytes
PIC S9(18) COMPBinary (doubleword)8 bytes
PIC S9(7)V99 COMP-1Single-precision float4 bytes
PIC S9(18)V99 COMP-2Double-precision float8 bytes
PIC Z(5)9Edited numeric (leading zeros suppressed) 123
PIC $ZZ,ZZ9.99Edited with currency/commas $1,234.56

Storage Formats

UsageStorageWhen to Use
DISPLAY1 byte/digitExternal files, reports
COMP-3 (packed)(n+1)/2 bytesAll calculations and DB2 columns
COMP (binary)2/4/8 bytesSubscripts, counters, indexes
COMP-1 (float)4 bytesScientific calculations (rare)
COMP-2 (double)8 bytesScientific calculations (rare)

REDEFINES

       01  WS-DATE-FIELD.
           05  WS-DATE-CCYYMMDD   PIC 9(8).
           05  WS-DATE-PARTS REDEFINES WS-DATE-CCYYMMDD.
               10  WS-DATE-CC     PIC 99.
               10  WS-DATE-YY     PIC 99.
               10  WS-DATE-MM     PIC 99.
               10  WS-DATE-DD     PIC 99.

OCCURS (Arrays)

       01  WS-MONTHLY-TOTALS.
           05  WS-MONTH-ENTRY OCCURS 12 TIMES
               INDEXED BY WS-MONTH-IDX.
               10  WS-MONTH-NAME  PIC X(10).
               10  WS-MONTH-AMT   PIC S9(11)V99 COMP-3.

      * Variable-length array
       01  WS-ORDER-LINES.
           05  WS-LINE-COUNT      PIC 99 COMP.
           05  WS-LINE-ITEM OCCURS 1 TO 50 TIMES
               DEPENDING ON WS-LINE-COUNT.
               10  WS-ITEM-SKU    PIC X(10).
               10  WS-ITEM-QTY    PIC 9(5) COMP-3.
               10  WS-ITEM-PRICE  PIC S9(7)V99 COMP-3.

88-Level Condition Names

       01  WS-TRANSACTION-TYPE    PIC X(2).
           88  TXN-SALE           VALUE 'SA'.
           88  TXN-RETURN         VALUE 'RT'.
           88  TXN-EXCHANGE       VALUE 'EX'.
           88  TXN-VALID          VALUE 'SA' 'RT' 'EX'.

      * Usage:
           IF TXN-VALID
               PERFORM 2000-PROCESS-TXN
           END-IF

           SET TXN-SALE TO TRUE    *> Sets WS-TRANSACTION-TYPE to 'SA'

3. File Handling

File Status Codes

CodeMeaning
00Success
10End of file (AT END)
22Duplicate key on WRITE
23Record not found (READ/START/DELETE)
35File not found (OPEN)
39File attribute conflict
41File already open
42File already closed
46Sequential READ with no valid next
47READ on file not opened INPUT/I-O
48WRITE on file not opened OUTPUT/I-O/EXTEND

VSAM KSDS (Indexed)

       FILE-CONTROL.
           SELECT CUSTOMER-FILE
               ASSIGN TO CUSTFILE
               ORGANIZATION IS INDEXED
               ACCESS MODE IS DYNAMIC
               RECORD KEY IS CUST-ID
               ALTERNATE RECORD KEY IS CUST-NAME
                   WITH DUPLICATES
               FILE STATUS IS WS-CUST-FS.

      * Random read
           MOVE '00012345' TO CUST-ID
           READ CUSTOMER-FILE
               INVALID KEY
                   DISPLAY 'CUSTOMER NOT FOUND: ' CUST-ID
               NOT INVALID KEY
                   PERFORM 3000-PROCESS-CUSTOMER
           END-READ

      * Sequential browse (START + READ NEXT)
           MOVE '00010000' TO CUST-ID
           START CUSTOMER-FILE KEY >= CUST-ID
               INVALID KEY DISPLAY 'START FAILED'
           END-START
           PERFORM UNTIL WS-CUST-FS NOT = '00'
               READ CUSTOMER-FILE NEXT
                   AT END SET END-OF-FILE TO TRUE
               END-READ
               IF NOT END-OF-FILE
                   PERFORM 3000-PROCESS-CUSTOMER
               END-IF
           END-PERFORM

      * Update
           READ CUSTOMER-FILE
               INVALID KEY DISPLAY 'NOT FOUND'
           END-READ
           MOVE 'ACTIVE' TO CUST-STATUS
           REWRITE CUSTOMER-RECORD
               INVALID KEY DISPLAY 'REWRITE FAILED'
           END-REWRITE

SORT/MERGE

       SD  SORT-FILE.
       01  SORT-RECORD.
           05  SORT-KEY           PIC 9(10).
           05  SORT-DATA          PIC X(190).

       PROCEDURE DIVISION.
      * Simple sort
           SORT SORT-FILE
               ON ASCENDING KEY SORT-KEY
               USING INPUT-FILE
               GIVING OUTPUT-FILE

      * Sort with INPUT/OUTPUT PROCEDURE
           SORT SORT-FILE
               ON ASCENDING KEY SORT-KEY
               INPUT PROCEDURE IS 5000-SELECT-RECORDS
               OUTPUT PROCEDURE IS 6000-FORMAT-OUTPUT

       5000-SELECT-RECORDS.
           OPEN INPUT RAW-FILE
           PERFORM UNTIL END-OF-RAW
               READ RAW-FILE AT END SET END-OF-RAW TO TRUE
               NOT AT END
                   IF RAW-STATUS = 'A'
                       MOVE RAW-RECORD TO SORT-RECORD
                       RELEASE SORT-RECORD
                   END-IF
               END-READ
           END-PERFORM
           CLOSE RAW-FILE
           .

       6000-FORMAT-OUTPUT.
           OPEN OUTPUT FINAL-FILE
           PERFORM UNTIL END-OF-SORT
               RETURN SORT-FILE
                   AT END SET END-OF-SORT TO TRUE
                   NOT AT END
                       PERFORM 6100-WRITE-FORMATTED
               END-RETURN
           END-PERFORM
           CLOSE FINAL-FILE
           .

4. Procedure Division Patterns

STRING / UNSTRING

      * STRING — concatenate
           STRING WS-LAST-NAME DELIMITED BY SPACES
                  ', '           DELIMITED BY SIZE
                  WS-FIRST-NAME DELIMITED BY SPACES
             INTO WS-FULL-NAME
             WITH POINTER WS-STR-PTR
             ON OVERFLOW DISPLAY 'NAME TOO LONG'
           END-STRING

      * UNSTRING — split
           UNSTRING WS-CSV-LINE DELIMITED BY ','
             INTO WS-FIELD1
                  WS-FIELD2
                  WS-FIELD3
             WITH POINTER WS-UNS-PTR
             TALLYING IN WS-FIELD-COUNT
             ON OVERFLOW DISPLAY 'TOO MANY FIELDS'
           END-UNSTRING

INSPECT

      * Count occurrences
           INSPECT WS-INPUT-STRING
               TALLYING WS-COUNT FOR ALL 'A'

      * Replace characters
           INSPECT WS-INPUT-STRING
               REPLACING ALL LOW-VALUES BY SPACES

      * Convert (translate)
           INSPECT WS-INPUT-STRING
               CONVERTING 'abcdefghijklmnopqrstuvwxyz'
               TO         'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

Reference Modification

      * Extract substring: identifier(start:length)
           MOVE WS-FULL-DATE(1:4) TO WS-YEAR    *> First 4 chars
           MOVE WS-FULL-DATE(5:2) TO WS-MONTH   *> Chars 5-6
           MOVE WS-FULL-DATE(7:2) TO WS-DAY     *> Chars 7-8

CALL (Subprogram)

      * Static call (link-edited together)
           CALL 'DATECONV' USING WS-INPUT-DATE
                                 WS-OUTPUT-DATE
                                 WS-RETURN-CODE

      * Dynamic call (loaded at runtime — can CANCEL to free)
           MOVE 'DATECONV' TO WS-PGM-NAME
           CALL WS-PGM-NAME USING WS-INPUT-DATE
                                   WS-OUTPUT-DATE
                                   WS-RETURN-CODE
           ON EXCEPTION
               DISPLAY 'PROGRAM NOT FOUND: ' WS-PGM-NAME
               MOVE 16 TO RETURN-CODE
           END-CALL

      * CANCEL (free dynamic program from memory)
           CANCEL WS-PGM-NAME

5. Embedded SQL (DB2)

Basic Patterns

       WORKING-STORAGE SECTION.
           EXEC SQL INCLUDE SQLCA END-EXEC.
           EXEC SQL INCLUDE DCLORDER END-EXEC.

       01  WS-SQLCODE             PIC S9(9) COMP.
       01  HV-CUST-ID            PIC S9(8) COMP.
       01  HV-ORDER-DATE         PIC X(10).
       01  HV-AMOUNT             PIC S9(11)V99 COMP-3.
       01  HV-AMOUNT-IND         PIC S9(4) COMP.

       PROCEDURE DIVISION.

      * Singleton SELECT
           EXEC SQL
               SELECT CUST_NAME, CUST_BALANCE
               INTO :HV-CUST-NAME, :HV-CUST-BALANCE
               FROM CUSTOMER
               WHERE CUST_ID = :HV-CUST-ID
           END-EXEC
           EVALUATE SQLCODE
               WHEN 0     CONTINUE
               WHEN +100  DISPLAY 'CUSTOMER NOT FOUND'
               WHEN OTHER PERFORM 9100-SQL-ERROR
           END-EVALUATE

      * INSERT
           EXEC SQL
               INSERT INTO ORDERS
               (ORDER_ID, CUST_ID, ORDER_DATE, AMOUNT)
               VALUES
               (:HV-ORDER-ID, :HV-CUST-ID,
                :HV-ORDER-DATE, :HV-AMOUNT)
           END-EXEC

      * NULL indicator handling
           EXEC SQL
               SELECT AMOUNT
               INTO :HV-AMOUNT :HV-AMOUNT-IND
               FROM ORDERS
               WHERE ORDER_ID = :HV-ORDER-ID
           END-EXEC
           IF HV-AMOUNT-IND < 0
               DISPLAY 'AMOUNT IS NULL'
           END-IF

Cursor Processing

      * Declare cursor
           EXEC SQL
               DECLARE CSR-ORDERS CURSOR FOR
               SELECT ORDER_ID, ORDER_DATE, AMOUNT
               FROM ORDERS
               WHERE CUST_ID = :HV-CUST-ID
               AND ORDER_DATE >= :HV-START-DATE
               ORDER BY ORDER_DATE DESC
           END-EXEC

      * Open cursor
           EXEC SQL OPEN CSR-ORDERS END-EXEC
           IF SQLCODE NOT = 0
               PERFORM 9100-SQL-ERROR
           END-IF

      * Fetch loop
           PERFORM UNTIL SQLCODE NOT = 0
               EXEC SQL
                   FETCH CSR-ORDERS
                   INTO :HV-ORDER-ID,
                        :HV-ORDER-DATE,
                        :HV-AMOUNT
               END-EXEC
               IF SQLCODE = 0
                   PERFORM 3100-PROCESS-ORDER
               END-IF
           END-PERFORM

           IF SQLCODE NOT = +100
               PERFORM 9100-SQL-ERROR
           END-IF

      * Close cursor
           EXEC SQL CLOSE CSR-ORDERS END-EXEC

      * Error handler
       9100-SQL-ERROR.
           DISPLAY 'SQL ERROR: SQLCODE=' SQLCODE
           DISPLAY 'SQLERRMC=' SQLERRMC
           MOVE 16 TO RETURN-CODE
           EXEC SQL ROLLBACK END-EXEC
           GOBACK
           .

Common SQLCODEs

SQLCODEMeaningAction
0SuccessContinue
+100Not found / end of cursorHandle as business logic
-803Duplicate key on INSERTCheck for existing record
-805Package/plan not foundRebind needed
-811Multiple rows from SELECT INTOAdd predicate or use cursor
-818Timestamp mismatchRebind with current DBRM
-904Unavailable resourceRetry or fail gracefully
-911Deadlock/timeout rollbackRetry transaction
-913Deadlock victimRetry transaction

6. CICS Programming

Pseudo-Conversational Pattern

      * Main entry — pseudo-conversational
       0000-MAIN.
           EVALUATE EIBCALEN
               WHEN 0
                   PERFORM 1000-FIRST-TIME
               WHEN OTHER
                   PERFORM 2000-PROCESS-INPUT
           END-EVALUATE
           .

       1000-FIRST-TIME.
           INITIALIZE WS-COMMAREA
           PERFORM 3000-SEND-MAP
           EXEC CICS RETURN
               TRANSID('ORDQ')
               COMMAREA(WS-COMMAREA)
               LENGTH(LENGTH OF WS-COMMAREA)
           END-EXEC
           .

       2000-PROCESS-INPUT.
           MOVE DFHCOMMAREA TO WS-COMMAREA
           EXEC CICS RECEIVE MAP('ORDMAP')
               MAPSET('ORDMAPS')
               INTO(ORDMAPI)
           END-EXEC

           EVALUATE EIBAID
               WHEN DFHENTER
                   PERFORM 2100-PROCESS-ORDER
               WHEN DFHPF3
                   EXEC CICS RETURN END-EXEC
               WHEN DFHPF12
                   EXEC CICS RETURN END-EXEC
               WHEN OTHER
                   MOVE 'INVALID KEY' TO MSGO
                   PERFORM 3000-SEND-MAP
           END-EVALUATE
           .

       3000-SEND-MAP.
           EXEC CICS SEND MAP('ORDMAP')
               MAPSET('ORDMAPS')
               FROM(ORDMAPO)
               ERASE
               CURSOR
           END-EXEC
           EXEC CICS RETURN
               TRANSID('ORDQ')
               COMMAREA(WS-COMMAREA)
               LENGTH(LENGTH OF WS-COMMAREA)
           END-EXEC
           .

CICS Commands Reference

CommandPurpose
SEND MAP / RECEIVE MAPBMS screen I/O
LINK PROGRAMCall subprogram (returns)
XCTL PROGRAMTransfer control (no return)
RETURN TRANSIDPseudo-conversational return
READ / WRITE / REWRITE / DELETEVSAM file operations
READQ TS / WRITEQ TS / DELETEQ TSTemporary Storage queue
READQ TD / WRITEQ TDTransient Data queue
START TRANSIDSchedule async transaction
RETRIEVEGet START data
GETMAIN / FREEMAINMemory allocation
ASKTIME / FORMATTIMEDate/time operations

Error Handling

      * RESP-based (recommended — replaces HANDLE CONDITION)
           EXEC CICS READ
               DATASET('CUSTFILE')
               INTO(CUST-RECORD)
               RIDFLD(CUST-KEY)
               RESP(WS-RESP)
               RESP2(WS-RESP2)
           END-EXEC

           EVALUATE WS-RESP
               WHEN DFHRESP(NORMAL)
                   PERFORM 3100-DISPLAY-CUSTOMER
               WHEN DFHRESP(NOTFND)
                   MOVE 'CUSTOMER NOT FOUND' TO MSGO
               WHEN DFHRESP(DISABLED)
                   MOVE 'FILE DISABLED' TO MSGO
               WHEN OTHER
                   PERFORM 9200-CICS-ERROR
           END-EVALUATE

7. Batch Processing

JCL Integration

//ORDPROC  JOB (ACCT),'ORDER PROCESSING',
//         CLASS=A,MSGCLASS=X,MSGLEVEL=(1,1)
//STEP010  EXEC PGM=ORDPROC
//STEPLIB  DD DSN=PROD.LOAD.LIBRARY,DISP=SHR
//ORDIN    DD DSN=PROD.ORDERS.DAILY,DISP=SHR
//CUSTDB   DD DSN=PROD.CUSTOMER.VSAM,DISP=SHR
//RPTOUT   DD DSN=PROD.REPORTS.DAILY(+1),
//         DISP=(NEW,CATLG),
//         SPACE=(TRK,(50,10),RLSE),
//         DCB=(RECFM=FB,LRECL=132,BLKSIZE=0)
//SYSOUT   DD SYSOUT=*

PARM Passing

       LINKAGE SECTION.
       01  LS-PARM.
           05  LS-PARM-LENGTH    PIC S9(4) COMP.
           05  LS-PARM-DATA      PIC X(100).

       PROCEDURE DIVISION USING LS-PARM.
           IF LS-PARM-LENGTH > 0
               EVALUATE LS-PARM-DATA(1:1)
                   WHEN 'D' SET DAILY-RUN TO TRUE
                   WHEN 'M' SET MONTHLY-RUN TO TRUE
               END-EVALUATE
           END-IF

Return Codes

      * Set return code for JCL COND checking
           MOVE 0 TO RETURN-CODE     *> Success
           MOVE 4 TO RETURN-CODE     *> Warning
           MOVE 8 TO RETURN-CODE     *> Error
           MOVE 16 TO RETURN-CODE    *> Severe error

      * In JCL:
      * //STEP020 EXEC PGM=NEXTSTEP,COND=(8,LT,STEP010)
      *   (skip if STEP010 RC < 8, i.e., run only if RC >= 8)

8. Copybook Patterns

      * In WORKING-STORAGE:
           COPY ORDCOPY.                      *> Include copybook as-is

           COPY CUSTCOPY REPLACING
               ==:TAG:== BY ==WS-==.          *> Replace tag prefix

      * Copybook CUSTCOPY.cpy:
      * 01  :TAG:-CUSTOMER-RECORD.
      *     05  :TAG:-CUST-ID    PIC 9(8).
      *     05  :TAG:-CUST-NAME  PIC X(40).
      * Becomes:
      * 01  WS-CUSTOMER-RECORD.
      *     05  WS-CUST-ID       PIC 9(8).
      *     05  WS-CUST-NAME     PIC X(40).

      * DCLGEN (DB2 table declarations)
           EXEC SQL INCLUDE DCLORDER END-EXEC
      * Generates host variable declarations matching DB2 columns

9. Debugging

Common ABEND Codes

CodeMeaningCommon Cause
S0C7Data exceptionNon-numeric data in numeric field, uninitialized COMP-3
S0C4Protection exceptionBad pointer, subscript out of range, bad LINKAGE
S0C1Operation exceptionBranching to non-executable area, bad CALL
S222Operator cancelled jobJob exceeded time limit
S322CPU time exceededInfinite loop, bad PERFORM UNTIL
S0B37Dataset out of spaceIncrease SPACE in JCL
S913RACF authorization failureMissing permissions

Debugging Techniques

      * DISPLAY debugging (simplest — goes to SYSOUT)
           DISPLAY 'DEBUG: CUST-ID=' WS-CUST-ID
                   ' AMOUNT=' WS-AMOUNT
                   ' AT PARAGRAPH 2100'

      * Compile with SSRANGE to catch subscript errors
      * CBL SSRANGE
      * Or: PARM='SSRANGE' on IGYWCL compile step

      * Compile with TEST for symbolic debugging
      * PARM='TEST(ALL,SYM,SEPARATE)'

CEDF (CICS Execution Diagnostic Facility)

CEDF ON     — Enable CEDF for your terminal
              Steps through each EXEC CICS command
              Shows EIBRESP, EIBRESP2, before/after data
CEDF OFF    — Disable

10. Modernization

GnuCOBOL (Local Development)

# Install on RHEL/Ubuntu
sudo dnf install gnucobol     # RHEL
sudo apt install gnucobol     # Ubuntu

# Compile and run
cobc -x -o ordproc ordproc.cbl
./ordproc

# Compile with DB2 (via ODBC)
cobc -x ordproc.cbl -ldb2

JSON Support (Enterprise COBOL 6.x+)

      * JSON GENERATE
           JSON GENERATE WS-JSON-OUTPUT
               FROM WS-ORDER-RECORD
               COUNT IN WS-JSON-LENGTH
               ON EXCEPTION
                   DISPLAY 'JSON GENERATE FAILED'
               NOT ON EXCEPTION
                   DISPLAY WS-JSON-OUTPUT(1:WS-JSON-LENGTH)
           END-JSON

      * JSON PARSE
           JSON PARSE WS-JSON-INPUT
               INTO WS-ORDER-RECORD
               WITH DETAIL
               ON EXCEPTION
                   DISPLAY 'JSON PARSE FAILED'
           END-JSON

COBOL-to-Service Patterns

PatternApproachEffort
CICS Web ServiceExpose CICS program as WSDL/REST via CICS TSLow
MQ BridgeCOBOL reads/writes MQ queues, external consumerMedium
Zowe APIAccess z/OS resources via REST (Zowe CLI/SDK)Medium
Strangler FigGradually replace COBOL with microservicesHigh
Side-by-SideRun new service alongside COBOL, sync dataHigh

11. Reading & Understanding Unfamiliar COBOL

The rest of this reference is authoring-focused. This section is for the opposite task: being dropped into a large, undocumented COBOL program you did not write and having to understand it — the comprehension payload for a maintenance or migration pass. Companion comprehension references in this family: pick-developer (Pick/MultiValue) and datastage-developer (DataStage ETL).

Orient top-down: the four divisions are a fixed reading order

COBOL's rigid structure is an advantage when reading — the divisions always appear in the same order and each answers a specific question:

  1. IDENTIFICATION DIVISION — PROGRAM-ID (the program's callable name), author, date. One line of real signal: the name other programs CALL.
  2. ENVIRONMENT DIVISION — CONFIGURATION SECTION (SPECIAL-NAMES, e.g. DECIMAL-POINT IS COMMA, CURRENCY SIGN) and INPUT-OUTPUT SECTION → FILE-CONTROL with the SELECT … ASSIGN TO … clauses. This is where logical file names bind to physical DD names / datasets — read it first to learn what the program touches.
  3. DATA DIVISION — the data shapes: FILE SECTION (record layouts under each FD), WORKING-STORAGE SECTION (the program's variables, flags, counters, tables), and LINKAGE SECTION (parameters passed in from the caller / JCL PARM).
  4. PROCEDURE DIVISION — the executable logic, organized into paragraphs and sections. The first paragraph runs first; follow the PERFORMs from there.

A fast first pass: read PROGRAM-ID → the SELECT list (what files) → the FD/01 record layouts (what the data looks like) → the first PROCEDURE paragraph (the driver), then follow control flow from the top.

Follow control flow: PERFORM / PERFORM THRU / CALL / GO TO

COBOL control flow is mostly PERFORM (an in-program "call and return"):

       0000-MAIN.
           PERFORM 1000-INITIALIZE          *> run that paragraph, then return here
           PERFORM 2000-PROCESS
               UNTIL END-OF-FILE            *> loop: repeat until the condition
           PERFORM 9000-TERMINATE
           GOBACK                           *> return to caller (or STOP RUN)
  • PERFORM <para> — execute the named paragraph, then return to the line after the PERFORM. The primary call-graph edge.
  • PERFORM <a> THRU <b> (a.k.a. PERFORM <a> THROUGH <b>) — execute paragraphs a through b in source order, then return. You must read every paragraph in the range to know what runs — control falls from one into the next (see fall-through below). A common convention is an empty <b>-EXIT. paragraph holding just EXIT. as the range terminator.
  • PERFORM … UNTIL … / PERFORM … VARYING … FROM … BY … UNTIL … — the loop forms; VARYING is the COBOL for loop (note: UNTIL is tested before each iteration by default — it is a pre-test loop unless WITH TEST AFTER).
  • PERFORM n TIMES — fixed iteration count.
  • CALL '<PROG>' USING … — invoke a separate program (the inter-program edge); arguments are matched positionally to the callee's LINKAGE SECTION. CALL <data-name> is a dynamic call — the target is only known at run time (treat as unresolved when reading statically).
  • GO TO — an unconditional jump that does not return. In legacy code it is common; trace it as a hard branch. GO TO … DEPENDING ON n is a computed branch (jump to the nth label).

Decode the data: PIC, COMP-3, REDEFINES, OCCURS DEPENDING ON, 88-levels

The DATA DIVISION is where meaning lives. Key things to decode when reading a layout:

  • PIC (picture) clause — the shape of a field. 9 = a digit, X = any character, S = a sign, V = an implied decimal point (no byte stored), A = alphabetic. PIC S9(7)V99 = a signed number, 7 integer digits + 2 decimal places. The V is virtual — 1234567 89 is stored as 9 digits with the decimal point only implied.
  • USAGE (the storage form) — DISPLAY (default; one byte per digit, human-readable), COMP/COMP-4/BINARY (binary integer, 2/4/8 bytes), COMP-3/PACKED-DECIMAL (packed BCD, (n+1)/2 bytes, two digits per byte + a sign nibble — not printable; a COMP-3 field dumped as text is garbage), COMP-1/COMP-2 (float/double). When a numeric field looks like binary noise in a file, check its USAGE.
  • REDEFINES — a second name and layout over the same bytes (COBOL's union). The bytes are interpreted one way under the first name and another way under the REDEFINES name; only one interpretation is valid at a time. Watch for a record read as raw bytes then re-interpreted via a REDEFINES based on a record-type flag.
  • OCCURS n TIMES — a fixed array (a table); INDEXED BY names its index.
  • OCCURS 1 TO n TIMES DEPENDING ON <counter> (ODO) — a variable-length array whose live length is the value of <counter> at run time. The record's length changes with the counter — critical when reading file layouts (everything after an ODO field shifts). Find the DEPENDING ON field to know how many entries are real.
  • 88-level condition names — a named boolean over a parent field's value(s):
         05  WS-STATUS        PIC X.
             88  ORD-PENDING  VALUE 'P'.
             88  ORD-SHIPPED  VALUE 'S'.
    
    IF ORD-PENDING means IF WS-STATUS = 'P'; SET ORD-SHIPPED TO TRUE means MOVE 'S' TO WS-STATUS. 88-levels make the code read like business rules — map each back to its parent field and value.
  • Level numbers — 01 = a record/group; 05/10/… = nested subordinate fields (the numbers show nesting depth, not fixed steps); 77 = a standalone elementary item; 66 = a RENAMES regrouping (rare).

Connect files: FD ↔ SELECT ↔ ASSIGN (and the JCL DD)

Tracing a file end to end crosses three places:

  1. SELECT logical-name ASSIGN TO DDNAME … FILE STATUS IS WS-xx. (ENVIRONMENT) — binds the program's logical file name to a system DD name and a status field.
  2. FD logical-name … 01 record-layout. (DATA / FILE SECTION) — the record structure read or written.
  3. In batch, the JCL //DDNAME DD DSN=… maps that DD name to the actual dataset (see §7).

So a READ ORDER-FILE reaches the FD ORDER-FILE, whose SELECT says ASSIGN TO ORDIN, which the JCL maps to a physical dataset. Always check the FILE STATUS field after I/O — a paragraph that reads a file and then tests WS-ORDER-FS is doing its error handling there (file status 00 = OK, 10 = end of file, 23 = not found, 35 = file missing; see §3).

Gotchas that mislead a reader

  • Fall-through between paragraphs. Paragraphs are not subroutines with hard boundaries — when a paragraph ends, control falls into the next paragraph in source order unless a PERFORM returns, a GO TO jumps, or the program stops. A paragraph reached by PERFORM A THRU B runs A, then everything between A and B. Never assume a paragraph runs in isolation; check what physically follows it.
  • ALTER + GO TO (obsolete but present in old code) — ALTER X TO PROCEED TO Y rewrites the target of a GO TO at run time, so the same GO TO can branch to different places on different executions. It makes static reading treacherous; flag any ALTER and trace every place that alters the same GO TO.
  • Implicit MOVE / group moves — a MOVE between fields of different PIC does silent conversion/truncation (alphanumeric-to-numeric, decimal alignment, space-padding). A MOVE of a group item copies bytes positionally regardless of the subordinate fields' types. The data can change shape without an obvious cast.
  • MOVE CORRESPONDING — moves only the subordinate fields whose names match between two groups; what actually moves depends on the names, not the order.
  • REDEFINES aliasing — the same bytes seen under two names (above). A value "changing" may just be the other view of the same storage.
  • OCCURS DEPENDING ON — record length is not constant; offsets after the ODO field move with the counter.
  • PERFORM range edits — adding a paragraph inside an existing PERFORM A THRU B range silently makes it run as part of that range. When reading a THRU, enumerate every paragraph in the span.

A reading checklist

  1. PROGRAM-ID — the name; grep the codebase for who CALLs it.
  2. SELECT … ASSIGN list — what files/datasets it touches (+ the FILE STATUS fields).
  3. FD / 01 record layouts — decode PIC/USAGE/REDEFINES/OCCURS … DEPENDING ON.
  4. WORKING-STORAGE flags and 88-levels — the state machine and its named conditions.
  5. LINKAGE SECTION + PROCEDURE DIVISION USING — the parameters from the caller/JCL.
  6. The first PROCEDURE paragraph — the driver; follow PERFORM/PERFORM THRU/GO TO.
  7. Each CALL — an external program (dynamic CALL <data-name> is unresolved statically).
  8. COPY members — shared layouts/code pulled in (COPY … REPLACING renames at compile time; the post-replace names are not in the source you see).
  9. Watch the gotchas: fall-through, ALTER/GO TO, implicit/group MOVE, ODO lengths.

Anti-Patterns

Anti-PatternWhy It FailsCorrect Approach
Using COMP-3 (packed decimal) for fields that need display outputCOMP-3 is not human-readable and causes garbled output in reports and logsUse DISPLAY for fields that appear in reports; reserve COMP-3 for calculations and storage optimization
Hardcoding file record lengths instead of using COPY membersChanges to record layouts require hunting through every program; missed updates cause S0C7 abendsDefine record layouts in COPY members; use REPLACE for program-specific field names
GO TO spaghetti instead of PERFORM-based structured programmingUnreadable control flow, impossible to debug, and maintenance nightmaresUse PERFORM THRU with well-named paragraphs; eliminate GO TO except for error exit patterns
Ignoring SQLCODE after every EXEC SQL statementSilent failures — a failed SELECT returns stale data, a failed INSERT loses records without alerting anyoneCheck SQLCODE after every SQL call; handle -803 (duplicate), -811 (multiple rows), +100 (not found) explicitly
Big-bang COBOL-to-microservice rewritesMulti-year rewrites fail 60%+ of the time; business logic is often undocumented in the COBOL itselfUse Strangler Fig pattern: wrap existing programs with APIs, migrate incrementally, validate at each step

Related Skills

SkillWhen to Use
ibm-mainframez/OS JCL, VSAM, IDCAMS, DFSORT, ISPF, REXX
db2-mainframeDB2 for z/OS (BIND, REORG, RUNSTATS, utilities)
python-enterprise-connectorsPython → z/OS via Zowe SDK, DB2 Connect
datastage-developerDataStage ETL reading from mainframe sources
cognos-adminCognos reporting against DB2 z/OS data
mainframe-lineage-parsersLineage-grade reading: deterministic COBOL+JCL+embedded-EXEC SQL → OpenLineage data lineage (DD-join + host-var→column edges). When you need where the data flows, not just what the code does.
structure-recoveryLineage-grade reading: reverse-engineer COBOL record layouts (PIC/USAGE/COMP-3 byte offsets, REDEFINES, OCCURS) and inferred DDL from copybooks/programs.
legacy-code-intelQueryable SCIP-style symbol graph over COBOL (paragraph/section call graph, copybook impact).
Gespeicherte Skills