L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Explorer les Skills
Données et recherche · 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

Documentation de la Skill

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).
Skills enregistrées