Tables with OCCURS

COBOL-85 allowed up to 7 dimensions; later standards raised the minimum limit.

17.1 One-dimensional tables

Subscripts start at 1. WS-SALES(0) or WS-SALES(13) is out of bounds — undetected unless you compile with SSRANGE (IBM) or -debug / -fec=bound-subscript (GnuCOBOL). OCCURS cannot be used at the 01, 66, 77, or 88 level.

01  WS-MONTHLY-SALES.
           05  WS-SALES         PIC 9(7)V99 OCCURS 12 TIMES.
      * ...
           MOVE 1500.00 TO WS-SALES(1)
           PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 12
               ADD WS-SALES(WS-I) TO WS-YEAR-TOTAL
           END-PERFORM

17.2 Tables of groups and multi-dimensional tables

COBOL-85 allowed up to 7 dimensions; later standards raised the minimum limit. GnuCOBOL and IBM Enterprise COBOL support at least 7 — check your compiler's documented limits before going deeper (and ask whether you really need to).

01  WS-EMPLOYEE-TABLE.
           05  WS-EMP OCCURS 100 TIMES.
               10  WS-EMP-ID       PIC 9(5).
               10  WS-EMP-NAME     PIC X(20).
               10  WS-EMP-HOURS    PIC 99V9 OCCURS 7 TIMES.
      * ...
           MOVE "SMITH" TO WS-EMP-NAME(3)
           MOVE 8.5     TO WS-EMP-HOURS(3, 2)     *> employee 3, day 2

17.3 Initializing a table with literals (REDEFINES idiom)

DISPLAY WS-DAY-NAME(WS-DAY-OF-WEEK) now prints the day name (pairs nicely with ACCEPT ... FROM DAY-OF-WEEK). (COBOL 2002 also allows VALUE directly on OCCURS items in some compilers, but the REDEFINES idiom is portable.)

01  WS-DAY-NAMES-DATA.
           05  FILLER    PIC X(9) VALUE "MONDAY".
           05  FILLER    PIC X(9) VALUE "TUESDAY".
           05  FILLER    PIC X(9) VALUE "WEDNESDAY".
           05  FILLER    PIC X(9) VALUE "THURSDAY".
           05  FILLER    PIC X(9) VALUE "FRIDAY".
           05  FILLER    PIC X(9) VALUE "SATURDAY".
           05  FILLER    PIC X(9) VALUE "SUNDAY".
       01  WS-DAY-TABLE REDEFINES WS-DAY-NAMES-DATA.
           05  WS-DAY-NAME    PIC X(9) OCCURS 7 TIMES.

17.4 Subscripts vs indexes

Any integer item (PIC S9(4) COMP recommended) INDEXED BY name on the OCCURS clause Occurrence number (1, 2, 3…)

Byte displacement (implementation detail) MOVE, ADD, COMPUTE

SET idx TO n, SET idx UP BY 1, PERFORM VARYING idx Must be converted to a displacement each use Faster (already a displacement) SEARCH, SEARCH ALL

Relative indexing (WS-RATE-CODE(RATE-IDX + 1)) is allowed.

01  WS-RATE-TABLE.
           05  WS-RATE-ENTRY OCCURS 50 TIMES INDEXED BY RATE-IDX.
               10  WS-RATE-CODE    PIC X(3).
               10  WS-RATE-PCT     PIC 9V999.
       01  WS-SAVED-IDX            USAGE INDEX.
      * ...
           SET RATE-IDX TO 1
           SET RATE-IDX UP BY 1
           SET WS-SAVED-IDX TO RATE-IDX
           PERFORM VARYING RATE-IDX FROM 1 BY 1 UNTIL RATE-IDX > 50
               MOVE SPACES TO WS-RATE-CODE(RATE-IDX)
           END-PERFORM

17.5 Variable-length tables: OCCURS DEPENDING ON

Storage is allocated for the maximum (200) in WORKING-STORAGE, but the group's length and SEARCH limits follow WS-ITEM-COUNT.

Set the DEPENDING ON object before moving or writing the group. In file records, ODO gives true variable-length records.

COBOL 2014 also defines dynamic-capacity tables (OCCURS DYNAMIC) that grow at run time; support varies (check GnuCOBOL/IBM documentation).

01  WS-ORDER.
           05  WS-ITEM-COUNT       PIC S9(4) COMP.
           05  WS-ITEM OCCURS 1 TO 200 TIMES
                       DEPENDING ON WS-ITEM-COUNT
                       INDEXED BY ITEM-IDX.
               10  WS-ITEM-SKU     PIC X(10).
               10  WS-ITEM-QTY     PIC 9(5).