Appendix A: Enterprise COBOL Quick Reference

This appendix is a working reference, not a tutorial. It assumes you already know COBOL and need to look something up quickly — a PIC pattern you use twice a year, the exact syntax for UNSTRING, or which compiler option controls bounds checking. Keep it bookmarked.

All examples target IBM Enterprise COBOL for z/OS (V6.x). Where GnuCOBOL diverges, the difference is noted.


The Four Divisions

IDENTIFICATION DIVISION

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PRGNAME.
       AUTHOR. Your Name.
       DATE-WRITTEN. 2026-03-17.
       DATE-COMPILED.

PROGRAM-ID is the only required paragraph. The name must match (or at least align with) your load module name. AUTHOR and DATE-WRITTEN are documentation only — the compiler ignores them. DATE-COMPILED is replaced by the actual compile date/time in the listing.

For nested programs or called subprograms:

       PROGRAM-ID. SUBPGM IS INITIAL.

IS INITIAL resets all Working-Storage to its initial value each time the program is called. Without it, Working-Storage persists across calls — which is sometimes what you want (counters, cached data) and sometimes a source of subtle bugs.

ENVIRONMENT DIVISION

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.
       SOURCE-COMPUTER. IBM-370.
       OBJECT-COMPUTER. IBM-370.
       SPECIAL-NAMES.
           DECIMAL-POINT IS COMMA.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT INFILE  ASSIGN TO INPUTDD
               ORGANIZATION IS SEQUENTIAL
               ACCESS MODE IS SEQUENTIAL
               FILE STATUS IS WS-INFILE-STATUS.
           SELECT IDXFILE ASSIGN TO IDXDD
               ORGANIZATION IS INDEXED
               ACCESS MODE IS DYNAMIC
               RECORD KEY IS IDX-PRIMARY-KEY
               ALTERNATE RECORD KEY IS IDX-ALT-KEY
                   WITH DUPLICATES
               FILE STATUS IS WS-IDXFILE-STATUS.
           SELECT SORTFILE ASSIGN TO SORTWORK.

File organizations:

Organization Access Modes Typical DD
SEQUENTIAL SEQUENTIAL QSAM, tape
INDEXED SEQUENTIAL, RANDOM, DYNAMIC VSAM KSDS
RELATIVE SEQUENTIAL, RANDOM, DYNAMIC VSAM RRDS
LINE SEQUENTIAL SEQUENTIAL GnuCOBOL only

Always code FILE STATUS. Always check it. Programs that skip file status checking account for a disproportionate share of midnight production calls.

DATA DIVISION

       DATA DIVISION.
       FILE SECTION.
       FD  INFILE
           RECORDING MODE IS F
           BLOCK CONTAINS 0 RECORDS
           RECORD CONTAINS 80 CHARACTERS.
       01  INFILE-RECORD              PIC X(80).

       WORKING-STORAGE SECTION.
       01  WS-FIELDS.
           05  WS-COUNTER             PIC 9(07) COMP-3.
           05  WS-FLAG                PIC X(01).
               88  WS-EOF             VALUE 'Y'.
               88  WS-NOT-EOF         VALUE 'N'.

       LOCAL-STORAGE SECTION.
       01  LS-WORK-AREA               PIC X(100).

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

Working-Storage vs. Local-Storage: Working-Storage is allocated once and persists for the life of the run unit. Local-Storage is allocated fresh on each invocation — crucial for reentrant CICS programs and recursive calls.

BLOCK CONTAINS 0 RECORDS tells the system to use the blocksize from the DCB or data set label. Always code this rather than hard-coding a block size.

PROCEDURE DIVISION

       PROCEDURE DIVISION.
       PROCEDURE DIVISION USING LS-PARM-AREA.
       PROCEDURE DIVISION USING LS-PARM-AREA
           RETURNING WS-RESULT.

PIC Clause Patterns

Numeric

Pattern Meaning Storage (Display) Example Value
PIC 9(5) 5-digit unsigned 5 bytes 00123
PIC S9(5) 5-digit signed 5 bytes + sign -00123
PIC S9(7)V99 7.2 digits signed 10 bytes display -0001234.56
PIC 9(7)V99 COMP-3 7.2 packed 5 bytes 1234567.89
PIC S9(8) COMP Binary fullword 4 bytes -12345678
PIC S9(4) COMP Binary halfword 2 bytes -1234
PIC S9(18) COMP Binary doubleword 8 bytes large integer

Alphanumeric

Pattern Meaning Storage
PIC X(10) 10-char alphanumeric 10 bytes
PIC A(10) 10-char alphabetic 10 bytes
PIC X(1) Single character 1 byte

Edited (for reports)

Pattern Example Input Example Output
PIC Z(5)9 000123 123
PIC ZZ,ZZ9 01234 1,234
PIC $ZZ,ZZ9.99` | 0012345.67 | ` $12,345.67
PIC -(5)9.99 -001234.56 -1234.56
PIC 99/99/9999 03172026 03/17/2026
PIC X(5)BX(5) HELLOWORLD HELLO WORLD

COMP Types Summary

Type Also Called Storage Use Case
COMP (COMP-4) BINARY 2/4/8 bytes Subscripts, counters, binary interfaces
COMP-1 4 bytes Single-precision float (rare in business)
COMP-2 8 bytes Double-precision float (rare in business)
COMP-3 PACKED-DECIMAL (n+1)/2 bytes Money, business arithmetic — the default choice
COMP-5 NATIVE BINARY 2/4/8 bytes Full binary range, C/Java interop

The rule of thumb: Use COMP-3 for business data, COMP/COMP-4 for subscripts and counters, COMP-5 for calling non-COBOL APIs. Avoid COMP-1 and COMP-2 unless interfacing with scientific code.


Key Statements

PERFORM

      * Inline PERFORM
           PERFORM VARYING WS-IDX FROM 1 BY 1
               UNTIL WS-IDX > WS-MAX
               MOVE SPACES TO WS-LINE(WS-IDX)
           END-PERFORM

      * Out-of-line PERFORM
           PERFORM 1000-PROCESS-RECORD
               THRU 1000-EXIT

      * PERFORM TIMES
           PERFORM 2000-RETRY 3 TIMES

      * PERFORM UNTIL
           PERFORM 3000-READ-NEXT
               UNTIL WS-EOF

THRU (or THROUGH) is a shop-standards issue. Some shops mandate it for every paragraph; others ban it. When using THRU, ensure the exit paragraph exists and contains only EXIT or CONTINUE.

EVALUATE (Structured CASE)

           EVALUATE TRUE
               WHEN WS-TRANS-TYPE = 'A'
                   PERFORM 2100-ADD-RECORD
               WHEN WS-TRANS-TYPE = 'C'
                   PERFORM 2200-CHANGE-RECORD
               WHEN WS-TRANS-TYPE = 'D'
                   PERFORM 2300-DELETE-RECORD
               WHEN OTHER
                   PERFORM 2900-INVALID-TRANS
           END-EVALUATE

      * Multi-subject EVALUATE
           EVALUATE WS-REGION ALSO WS-PRODUCT
               WHEN 'EAST' ALSO 'WIDGET'
                   MOVE 0.10 TO WS-DISCOUNT
               WHEN 'EAST' ALSO ANY
                   MOVE 0.05 TO WS-DISCOUNT
               WHEN ANY    ALSO 'WIDGET'
                   MOVE 0.07 TO WS-DISCOUNT
               WHEN OTHER
                   MOVE 0.00 TO WS-DISCOUNT
           END-EVALUATE

STRING

           STRING WS-LAST-NAME DELIMITED BY SPACES
                  ', '          DELIMITED BY SIZE
                  WS-FIRST-NAME DELIMITED BY SPACES
               INTO WS-FULL-NAME
               WITH POINTER WS-PTR
               ON OVERFLOW
                   MOVE 'Y' TO WS-OVERFLOW-FLAG
           END-STRING

Initialize WS-PTR to 1 before the first STRING. If building a string in multiple STRING statements, do not reset the pointer between them — that is the whole point of the POINTER phrase.

UNSTRING

           UNSTRING WS-CSV-RECORD
               DELIMITED BY ',' OR ALL SPACES
               INTO WS-FIELD-1
                    WS-FIELD-2
                    WS-FIELD-3
               WITH POINTER WS-PTR
               TALLYING IN WS-FIELD-COUNT
               ON OVERFLOW
                   PERFORM 9100-PARSE-ERROR
           END-UNSTRING

TALLYING gives you the number of receiving fields that were populated. ON OVERFLOW fires when there are more delimited fields than receiving fields.

INSPECT

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

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

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

COMPUTE

           COMPUTE WS-RESULT ROUNDED
               = (WS-PRINCIPAL * WS-RATE ** WS-YEARS)
               ON SIZE ERROR
                   PERFORM 9200-OVERFLOW-ERROR
           END-COMPUTE

COMPUTE is the only statement that supports exponentiation (**), parenthetical grouping, and mixed arithmetic in a single expression. For anything beyond simple ADD/SUBTRACT/MULTIPLY/DIVIDE, prefer COMPUTE.

ROUNDED rounds the final result. Without it, truncation occurs. For financial calculations, always code ROUNDED.

ON SIZE ERROR fires on overflow or division by zero. Always code it for production arithmetic.

CALL

      * Static call
           CALL 'SUBPGM01' USING WS-REQUEST-AREA
                                  WS-RESPONSE-AREA

      * Dynamic call
           MOVE 'SUBPGM01' TO WS-PGM-NAME
           CALL WS-PGM-NAME USING WS-REQUEST-AREA
                                   WS-RESPONSE-AREA
               ON EXCEPTION
                   PERFORM 9300-PGM-NOT-FOUND
           END-CALL

      * CALL with BY REFERENCE / BY CONTENT / BY VALUE
           CALL 'SUBPGM02' USING BY REFERENCE WS-AREA-1
                                  BY CONTENT   WS-AREA-2
                                  BY VALUE     WS-LENGTH

BY REFERENCE (default): callee sees and can modify the caller's storage. BY CONTENT: callee gets a copy; changes do not affect the caller. BY VALUE: passes the actual value (not a pointer); required for calling C functions.

Static calls are resolved at link-edit — the subprogram is bound into the load module. Dynamic calls are resolved at runtime via the CALL literal or identifier — the subprogram is a separate load module. Dynamic calls cost more at first invocation (fetch from STEPLIB) but allow individual subprogram replacement without relinking.

EXEC SQL (Embedded DB2)

           EXEC SQL
               SELECT FIRST_NAME, LAST_NAME, SALARY
                 INTO :WS-FIRST-NAME,
                      :WS-LAST-NAME,
                      :WS-SALARY :WS-SALARY-NULL
                 FROM EMPLOYEE
                WHERE EMPLOYEE_ID = :WS-EMP-ID
           END-EXEC

           EVALUATE SQLCODE
               WHEN 0
                   CONTINUE
               WHEN +100
                   MOVE 'Y' TO WS-NOT-FOUND
               WHEN OTHER
                   PERFORM 9500-DB2-ERROR
           END-EVALUATE

Every EXEC SQL must be followed by an SQLCODE check. No exceptions. Not even for COMMIT.

EXEC CICS

           EXEC CICS READ
               FILE('CUSTMAST')
               INTO(WS-CUST-RECORD)
               LENGTH(WS-CUST-LENGTH)
               RIDFLD(WS-CUST-KEY)
               RESP(WS-CICS-RESP)
               RESP2(WS-CICS-RESP2)
           END-EXEC

           EVALUATE WS-CICS-RESP
               WHEN DFHRESP(NORMAL)
                   CONTINUE
               WHEN DFHRESP(NOTFND)
                   PERFORM 8100-CUSTOMER-NOT-FOUND
               WHEN OTHER
                   PERFORM 9600-CICS-ERROR
           END-EVALUATE

Always use RESP/RESP2 instead of HANDLE CONDITION. HANDLE CONDITION is a GOTO in disguise and makes programs nearly impossible to debug.


COPY and REPLACE

      * Basic COPY
           COPY CUSTCOPY.

      * COPY with REPLACING
           COPY CUSTCOPY REPLACING ==:PREFIX:== BY ==WS-CUST==.

      * REPLACE (independent of COPY)
           REPLACE ==:TAG:== BY ==PROD==.
           01  :TAG:-RECORD.
               05  :TAG:-ID            PIC X(10).
           REPLACE OFF.

COPY pulls in a copybook from the SYSLIB concatenation. REPLACING modifies text during the copy. REPLACE is a standalone directive that modifies source text — useful for generating multiple similar structures from a single template.

The == pseudo-text delimiters are required. The replacement is purely textual — the compiler does a literal string substitution before parsing.

Common Copybook Conventions

Copybook Contents
SQLCA DB2 SQL Communication Area (COPY SQLCA)
DFHAID CICS attention identifier definitions
DFHBMSCA CICS BMS attribute characters
DFHEIBLK CICS EIB (Execute Interface Block)

Compiler Options That Matter

These are the options you will actually adjust in production. The full list runs to hundreds; these are the ones that affect your daily work.

Optimization and Performance

Option Default Recommendation Effect
OPT(0) OPT(0) OPT(2) for production Optimization level. OPT(2) yields 10-30% throughput improvement.
FASTSRT NOFASTSRT FASTSRT always Lets DFSORT handle SORT/MERGE I/O directly, bypassing COBOL file handling. Major performance gain.
NUMPROC(PFD) NUMPROC(NOPFD) NUMPROC(PFD) if data is clean Assumes valid packed decimal signs. Faster, but S0C7 on bad data.
TRUNC(OPT) TRUNC(STD) TRUNC(OPT) for new code Lets compiler choose optimal truncation. TRUNC(BIN) for C interop.
HGPR(PRESERVE) HGPR(PRESERVE) Default is fine Controls use of high halves of 64-bit GPRs.
AFP(VOLATILE) AFP(VOLATILE) Default is fine Controls additional floating-point registers.

Debugging and Safety

Option Default Recommendation Effect
TEST NOTEST TEST(NOEJPD,SOURCE) in dev Enables Debug Tool. Remove for production (except TEST(NOEJPD,NOSOURCE) for post-mortem).
SSRANGE NOSSRANGE SSRANGE in dev Bounds-checks subscripts and reference modifications. Catches S0C4 causes before they happen. 5-15% runtime cost.
CHECK(ON) CHECK(OFF) CHECK(ON) in dev Numeric validation on MOVE. Catches S0C7 sources.
LIST NOLIST LIST for tuning Generates assembler listing. Essential for performance tuning.
OFFSET NOOFFSET OFFSET for production Generates condensed offset listing. Needed to map abend offsets to COBOL statements.

Arithmetic and Data

Option Default Recommendation Effect
ARITH(COMPAT) ARITH(COMPAT) ARITH(EXTEND) for new code COMPAT: max 18 digits. EXTEND: max 31 digits. EXTEND required for large financial calculations.
INTDATE(ANSI) INTDATE(ANSI) Check your installation Affects date intrinsic functions. ANSI: day 1 = Jan 1, 1601. LILIAN: day 1 = Oct 15, 1582.
NSYMBOL(NATIONAL) NSYMBOL(DBCS) NSYMBOL(NATIONAL) for Unicode Controls interpretation of N literals.
CODEPAGE(1140) Installation default Match your data EBCDIC code page. 1140 = US English with Euro sign.

Compilation Control

Option Default Recommendation Effect
RENT RENT RENT always for CICS Generates reentrant code. Required for CICS, recommended everywhere.
DYNAM NODYNAM Depends on design Dynamic call resolution. NODYNAM for static calls, DYNAM for dynamic.
LIB LIB LIB always Enables COPY/REPLACE processing.
SQL NOSQL SQL when using DB2 Enables DB2 coprocessor.
CICS NOCICS CICS when using CICS Enables CICS coprocessor.
THREAD NOTHREAD THREAD for DB2 stored procs Enables thread-safe code.

Development:

OPT(0),SSRANGE,TEST(NOEJPD,SOURCE),CHECK(ON),LIST,OFFSET,
FASTSRT,RENT,LIB,ARITH(EXTEND),NUMPROC(NOPFD)

Production:

OPT(2),NOSSRANGE,NOTEST,NOCHECK,NOLIST,OFFSET,
FASTSRT,RENT,LIB,ARITH(EXTEND),NUMPROC(PFD),TRUNC(OPT)

Common Abbreviations and Acronyms

Abbreviation Meaning
BMS Basic Mapping Support (CICS screen maps)
CICS Customer Information Control System
COMP Computational (binary)
COMP-3 Packed decimal
COPY Source library inclusion
CSECT Control Section
DB2 Database 2 (IBM relational DBMS)
DCB Data Control Block
DISP Disposition (JCL)
DFSORT Data Facility Sort
DSN Data Set Name
DSORG Data Set Organization
EIB Execute Interface Block (CICS)
FD File Description
GDG Generation Data Group
IEBGENER Utility: copy sequential data sets
IDCAMS Utility: VSAM catalog services
ISPF Interactive System Productivity Facility
JCL Job Control Language
JES Job Entry Subsystem
KSDS Key-Sequenced Data Set (VSAM)
LRECL Logical Record Length
MRO Multi-Region Operation (CICS)
MVS Multiple Virtual Storage
PDS Partitioned Data Set
PDSE Partitioned Data Set Extended
QSAM Queued Sequential Access Method
RECFM Record Format
SD Sort-file Description
SQLCA SQL Communication Area
SYSOUT System output (JES spool)
TSO Time Sharing Option
VSAM Virtual Storage Access Method
WLM Workload Manager
WTO Write To Operator
z/OS IBM's flagship mainframe operating system

Intrinsic Functions Quick List

Numeric

Function Example Result
FUNCTION LENGTH(x) FUNCTION LENGTH(WS-NAME) Length in bytes
FUNCTION MAX(a b c) FUNCTION MAX(10 20 5) 20
FUNCTION MIN(a b c) FUNCTION MIN(10 20 5) 5
FUNCTION MOD(a b) FUNCTION MOD(17 5) 2
FUNCTION INTEGER-PART(x) FUNCTION INTEGER-PART(3.7) 3
FUNCTION NUMVAL(x) FUNCTION NUMVAL(' 123.45') 123.45
FUNCTION NUMVAL-C(x) FUNCTION NUMVAL-C('$1,234.56') 1234.56
FUNCTION ORD(x) FUNCTION ORD('A') 194 (EBCDIC)

String

Function Example Result
FUNCTION UPPER-CASE(x) FUNCTION UPPER-CASE('hello') 'HELLO'
FUNCTION LOWER-CASE(x) FUNCTION LOWER-CASE('HELLO') 'hello'
FUNCTION REVERSE(x) FUNCTION REVERSE('ABC') 'CBA'
FUNCTION TRIM(x) FUNCTION TRIM(WS-NAME) Leading/trailing spaces removed
FUNCTION TRIM(x LEADING) FUNCTION TRIM(WS-NAME LEADING) Leading spaces removed

Date/Time

Function Example Notes
FUNCTION CURRENT-DATE 21-byte alphanumeric YYYYMMDDHHMMSShhZ+HHMM
FUNCTION INTEGER-OF-DATE(d) FUNCTION INTEGER-OF-DATE(20260317) Integer date
FUNCTION DATE-OF-INTEGER(n) FUNCTION DATE-OF-INTEGER(155457) YYYYMMDD
FUNCTION WHEN-COMPILED 21-byte alphanumeric Compile date/time

Date arithmetic example:

           COMPUTE WS-DAYS-BETWEEN =
               FUNCTION INTEGER-OF-DATE(WS-END-DATE) -
               FUNCTION INTEGER-OF-DATE(WS-START-DATE)

Reference Modification

      * identifier(start:length)
           MOVE WS-FULL-NAME(1:10) TO WS-SHORT-NAME
           MOVE WS-RECORD(WS-OFFSET:WS-LEN) TO WS-FIELD

Start position is 1-based. If length is omitted, it extends to the end of the field. With SSRANGE active, out-of-bounds references generate a runtime error instead of silently corrupting memory.


Condition Names (88-levels)

       01  WS-STATUS            PIC X(02).
           88  WS-ACTIVE        VALUE 'AC'.
           88  WS-INACTIVE      VALUE 'IN'.
           88  WS-SUSPENDED     VALUE 'SU'.
           88  WS-VALID-STATUS  VALUE 'AC' 'IN' 'SU'.

Use SET WS-ACTIVE TO TRUE to assign the value 'AC' to WS-STATUS. This is cleaner than MOVE 'AC' TO WS-STATUS and self-documenting.

88-levels with multiple values are ideal for validation:

           IF NOT WS-VALID-STATUS
               PERFORM 9100-INVALID-STATUS
           END-IF

File Status Codes

Code Meaning
00 Successful
02 Successful, duplicate key (VSAM alternate index)
04 Record length mismatch (not serious)
10 End of file (AT END)
22 Duplicate key on WRITE (VSAM KSDS)
23 Record not found (VSAM RANDOM READ)
30 Permanent I/O error
34 Out of space on WRITE
35 File not found (OPEN)
37 File attribute conflict (OPEN)
39 File attribute mismatch
41 File already open
42 File already closed
46 Sequential read without position
47 File not open for READ
48 File not open for WRITE
49 File not open for REWRITE/DELETE
92 Logic error
93 Resource not available
95 Incomplete/wrong length record
96 No DD statement found

SORT and MERGE

           SORT SORT-FILE
               ON ASCENDING KEY SORT-CUST-ID
               ON DESCENDING KEY SORT-AMOUNT
               INPUT PROCEDURE IS 4000-SELECT-RECORDS
               OUTPUT PROCEDURE IS 5000-PROCESS-SORTED

      * Simple SORT with USING/GIVING
           SORT SORT-FILE
               ON ASCENDING KEY SORT-KEY
               USING INPUT-FILE
               GIVING OUTPUT-FILE

With FASTSRT, USING/GIVING bypasses COBOL I/O entirely — DFSORT reads and writes the files directly. This is significantly faster but means COBOL OPEN/CLOSE/READ/WRITE processing does not apply to those files.


Scope Terminators

Always use explicit scope terminators. Every shop's code review should enforce this.

Statement Terminator
IF END-IF
EVALUATE END-EVALUATE
PERFORM END-PERFORM
READ END-READ
WRITE END-WRITE
REWRITE END-REWRITE
DELETE END-DELETE
START END-START
STRING END-STRING
UNSTRING END-UNSTRING
COMPUTE END-COMPUTE
ADD END-ADD
SUBTRACT END-SUBTRACT
MULTIPLY END-MULTIPLY
DIVIDE END-DIVIDE
CALL END-CALL
SEARCH END-SEARCH
EXEC SQL END-EXEC
EXEC CICS END-EXEC

Table Handling

       01  WS-STATE-TABLE.
           05  WS-STATE-ENTRY OCCURS 50 TIMES
               INDEXED BY WS-STATE-IDX.
               10  WS-STATE-CODE     PIC X(02).
               10  WS-STATE-NAME     PIC X(20).
               10  WS-TAX-RATE       PIC V9(04) COMP-3.

      * SEARCH (serial)
           SET WS-STATE-IDX TO 1
           SEARCH WS-STATE-ENTRY
               AT END
                   PERFORM 9100-STATE-NOT-FOUND
               WHEN WS-STATE-CODE(WS-STATE-IDX) =
                   WS-INPUT-STATE
                   MOVE WS-TAX-RATE(WS-STATE-IDX)
                       TO WS-OUTPUT-RATE
           END-SEARCH

      * SEARCH ALL (binary — table must be sorted)
       01  WS-STATE-TABLE-SORTED.
           05  WS-STATE-ENTRY OCCURS 50 TIMES
               ASCENDING KEY IS WS-STATE-CODE
               INDEXED BY WS-STATE-IDX.
               10  WS-STATE-CODE     PIC X(02).
               10  WS-STATE-NAME     PIC X(20).
               10  WS-TAX-RATE       PIC V9(04) COMP-3.

           SEARCH ALL WS-STATE-ENTRY
               AT END
                   PERFORM 9100-STATE-NOT-FOUND
               WHEN WS-STATE-CODE(WS-STATE-IDX) =
                   WS-INPUT-STATE
                   MOVE WS-TAX-RATE(WS-STATE-IDX)
                       TO WS-OUTPUT-RATE
           END-SEARCH

SEARCH ALL requires the table to be defined with ASCENDING KEY (or DESCENDING KEY) and the table data must actually be in that order. The compiler generates a binary search — O(log n) vs. O(n) for serial SEARCH.


Variable-Length Records and OCCURS DEPENDING ON

       FD  VARFILE
           RECORDING MODE IS V
           RECORD IS VARYING IN SIZE
               FROM 50 TO 500 CHARACTERS
               DEPENDING ON WS-RECORD-LENGTH.

       01  WS-VAR-TABLE.
           05  WS-NUM-ENTRIES     PIC S9(04) COMP.
           05  WS-TABLE-ENTRY OCCURS 1 TO 100 TIMES
               DEPENDING ON WS-NUM-ENTRIES.
               10  WS-ENTRY-DATA  PIC X(20).

Set WS-NUM-ENTRIES before any reference to the table. The compiler uses it to calculate the actual length of WS-VAR-TABLE. Getting this wrong causes S0C4 or data corruption.


This reference is deliberately terse. For full syntax diagrams and edge-case behavior, consult the Enterprise COBOL for z/OS Language Reference (SC27-1408) — the definitive authority. For compiler option details, see the Programming Guide (SC27-1412). Both are available on the IBM Documentation website at no cost.