COBOL Module 6 – Tables: OCCURS, SEARCH and SORT
Tables, subscripts and indexes
Define one- and two-dimensional COBOL tables with OCCURS, load them from literals or a file, use subscripts and indexes, and catch out-of-range entries.
What you will learn
- Define one- and two-dimensional tables with OCCURS and load them from literals or files
- Choose between subscripts and indexes and move indexes with SET
- Detect out-of-range subscripts with runtime checks and explain what happens without them
- Check a table's capacity before loading data that could exceed it
Before you start
What you’ll learn · Before you start
What you will learn
- Define one- and two-dimensional tables with OCCURS and load them from literals or files
- Choose between subscripts and indexes and move indexes with SET
- Detect out-of-range subscripts with runtime checks and explain what happens without them
- Check a table's capacity before loading data that could exceed it
Before you start
On this page
Writing entry 6 of a five-entry branch table changed the field stored after the table from UNTOUCHED to MUMBAIHED, and the program ended normally. A COBOL table is a run of entries in storage with nothing around it, and only the program, or a check it was built with, keeps a subscript: A number in brackets after a table item that picks one entry, counting from 1, as in BR-CODE(3). It is a literal or a whole-number data item, optionally plus or minus a constant. inside it.
Below you will define tables with OCCURS in one and two dimensions, load them from literals and from a file without overfilling them, choose between subscripts and indexes, and watch what an out-of-range subscript does with and without run-time checks.
OCCURS repeats an entry, and a subscript picks one, counting from 1
The OCCURS clause: The clause that makes an item a table: ITEM OCCURS n TIMES describes n entries of the same layout, one after another, numbered from 1. It is not allowed at levels 01, 66, 77 or 88., in IBM’s words, “specifies tables whose elements can be referred to by indexing or subscripting”. BR-ENTRY OCCURS 5 TIMES describes five entries of the same layout, one after the other, and BR-CODE(3) names the code of the third. IBM’s guide says “the lowest possible subscript value is 1, which references the first occurrence”, and the subscript may be a literal or a numeric data item. OCCURS is not allowed at level 01, 66, 77 or 88, so a table is always part of a group. This program lays out the values of five branches as literals and describes the table over them with REDEFINES:
IDENTIFICATION DIVISION.
PROGRAM-ID. BRANCHES.
* A table of five branches, its values laid out as literals
* and the table described over them with REDEFINES. A
* subscript picks an entry, counting from 1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 BRANCH-VALUES.
05 FILLER PIC X(12) VALUE "BR01PUNE ".
05 FILLER PIC X(12) VALUE "BR02CHENNAI ".
05 FILLER PIC X(12) VALUE "BR03KOLKATA ".
05 FILLER PIC X(12) VALUE "BR04JAIPUR ".
05 FILLER PIC X(12) VALUE "BR05INDORE ".
01 BRANCH-TABLE REDEFINES BRANCH-VALUES.
05 BR-ENTRY OCCURS 5 TIMES.
10 BR-CODE PIC X(4).
10 BR-CITY PIC X(8).
01 SUB PIC 99.
PROCEDURE DIVISION.
DISPLAY "table bytes: " FUNCTION LENGTH(BRANCH-TABLE)
DISPLAY "entry bytes: " FUNCTION LENGTH(BR-ENTRY(1))
PERFORM VARYING SUB FROM 1 BY 1 UNTIL SUB > 5
DISPLAY "entry " SUB ": " BR-CODE(SUB) " " BR-CITY(SUB)
END-PERFORM
MOVE 3 TO SUB
DISPLAY "BR-CITY(SUB) with SUB = 3: " BR-CITY(SUB)
STOP RUN. The session also runs the next section’s two programs:
from session import files, run
# A one-dimensional table loaded from literals, a two-dimensional table filled by a loop, and the ALL subscript,
# which GnuCOBOL 3.2 does not accept.
files("branches.cob", "sales.cob", "sumall.cob")
run("""
cobc -x branches.cob && ./branches
cobc -x sales.cob && ./sales
!cobc -x sumall.cob
""") Output
$ cobc -x branches.cob && ./branches
table bytes: 60
entry bytes: 12
entry 01: BR01 PUNE
entry 02: BR02 CHENNAI
entry 03: BR03 KOLKATA
entry 04: BR04 JAIPUR
entry 05: BR05 INDORE
BR-CITY(SUB) with SUB = 3: KOLKATA
$ cobc -x sales.cob && ./sales
table bytes: 42
branch 1 total: 3750.00
branch 2 total: 6750.00
MONTH-AMT(2, 3): 2375.00
MONTH-AMT(1, 4), a month too far: 2125.00
$ cobc -x sumall.cob
sumall.cob:11: error: syntax error, unexpected ALL
9 | 01 TOTAL PIC 9(7)V99.
10 | PROCEDURE DIVISION.
11 > COMPUTE TOTAL = FUNCTION SUM(AMT(ALL))
12 | DISPLAY TOTAL
13 | STOP RUN.
[exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 tables_session.py
The table is 60 bytes, five entries of 12, and the loop read them with SUB from 1 to 5. The entries have no separator and no length of their own: entry n simply starts 12 bytes after entry n - 1, which is all a subscript works out.
The REDEFINES pattern is common in old programs because the values sit next to the layout. IBM’s guide suggests VALUE clauses when a table holds stable values “such as days and months”, and reading the values into the table before the program refers to it when they change from one run to the next, which a section below does.
A table inside a table takes two subscripts
An entry can itself contain a table. In sales.cob, BRANCH-ROW OCCURS 2 TIMES and each row holds MONTH-AMT OCCURS 3 TIMES, so MONTH-AMT takes two subscripts, the branch first and then the month: MONTH-AMT(2, 3) is the third month of the second branch. A nested VARYING loop stored B x 1000 + M x 125 in each entry, which gives the amounts below; the session printed the two row totals and MONTH-AMT(2, 3), 2375.00:
| MONTH-AMT | Month 1 | Month 2 | Month 3 | Row total |
|---|---|---|---|---|
| Branch 1 | 1125.00 | 1250.00 | 1375.00 | 3750.00 |
| Branch 2 | 2125.00 | 2250.00 | 2375.00 | 6750.00 |
The table is 42 bytes: 2 rows of 3 amounts of 7 bytes each, the rows one after the other. The month varies fastest in storage, as MONTH-NO varied fastest in the VARYING … AFTER loop of the loops lesson. That is why the last line of the program, MONTH-AMT(1, 4), printed 2125.00: there is no fourth month in row 1, so the address fell on the first month of row 2, and no error came.
IBM’s guide offers a shorter way to total a table: for intrinsic functions with several arguments, “you can use the
subscript ALL to reference all the items in the table”, as in FUNCTION SUM(AMT(ALL)). GnuCOBOL 3.2 does not accept
it: sumall.cob stopped with syntax error, unexpected ALL. A loop with an accumulator, as in sales.cob, works with
both compilers.
ALL subscripts and GnuCOBOL
Code copied from a z/OS program that totals a table with FUNCTION SUM(TABLE-NAME(ALL)) will not compile with GnuCOBOL 3.2. Replace the call with a PERFORM VARYING loop that adds each entry.
Checkpoint
Check: OCCURS and subscripts from 1 · Two-dimensional tables
Load a table from a file, and check that it fits
Values that change, such as the list of branches, belong in a file that the program reads into the table when it starts: a new branch is then a new line of data, not a change to the program. The loop has one duty besides storing, which is to refuse a file with more lines than the table has entries. This program loads the five-entry table from branches.txt, first a file of three branches, then one of six:
IDENTIFICATION DIVISION.
PROGRAM-ID. LOADFILE.
* Loads the branch table from a file at start-up and refuses
* a file with more branches than the table holds. The file
* statements are the subject of a later lesson.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT BRANCH-FILE ASSIGN TO "branches.txt"
ORGANIZATION LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD BRANCH-FILE.
01 BRANCH-REC PIC X(12).
WORKING-STORAGE SECTION.
01 BRANCH-TABLE.
05 BR-ENTRY OCCURS 5 TIMES.
10 BR-CODE PIC X(4).
10 BR-CITY PIC X(8).
01 BR-COUNT PIC 99 VALUE 0.
01 BR-MAX PIC 99 VALUE 5.
01 EOF-FLAG PIC X VALUE "N".
88 END-OF-FILE VALUE "Y".
01 FULL-FLAG PIC X VALUE "N".
88 TABLE-FULL VALUE "Y".
01 REFUSED-CODE PIC X(4).
01 SUB PIC 99.
PROCEDURE DIVISION.
OPEN INPUT BRANCH-FILE
PERFORM UNTIL END-OF-FILE
READ BRANCH-FILE
AT END SET END-OF-FILE TO TRUE
NOT AT END PERFORM STORE-BRANCH
END-READ
END-PERFORM
CLOSE BRANCH-FILE
IF TABLE-FULL
DISPLAY "too many branches: " REFUSED-CODE
" does not fit a table of " BR-MAX
MOVE 8 TO RETURN-CODE
STOP RUN
END-IF
DISPLAY BR-COUNT " branches loaded"
PERFORM VARYING SUB FROM 1 BY 1 UNTIL SUB > BR-COUNT
DISPLAY " " BR-CODE(SUB) " " BR-CITY(SUB)
END-PERFORM
STOP RUN.
STORE-BRANCH.
IF BR-COUNT = BR-MAX
MOVE BRANCH-REC(1:4) TO REFUSED-CODE
SET TABLE-FULL TO TRUE
SET END-OF-FILE TO TRUE
ELSE
ADD 1 TO BR-COUNT
MOVE BRANCH-REC TO BR-ENTRY(BR-COUNT)
END-IF. from session import files, run, write
# The branch table loaded from a file of three branches, then from a file of six, one more than the table holds.
files("loadfile.cob")
write("three.txt", "BR01PUNE\nBR02CHENNAI\nBR03KOLKATA\n")
write("six.txt", "BR01PUNE\nBR02CHENNAI\nBR03KOLKATA\nBR04JAIPUR\nBR05INDORE\nBR06NASHIK\n")
run("""
cobc -x loadfile.cob
cp three.txt branches.txt && ./loadfile
!cp six.txt branches.txt && ./loadfile
""") Output
$ cobc -x loadfile.cob $ cp three.txt branches.txt && ./loadfile 03 branches loaded BR01 PUNE BR02 CHENNAI BR03 KOLKATA $ cp six.txt branches.txt && ./loadfile too many branches: BR06 does not fit a table of 05 [exit status 8]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 loadfile_session.py
Three branches loaded and printed. The file of six stopped with
too many branches: BR06 does not fit a table of 05 and status 8, after five branches had been stored and before the
sixth could touch anything. Step through the second
run:
The drawing shows the whole scene; its 4 steps are listed below.
Every step as text
- The first line. READ gives BR01PUNE. BR-COUNT is 0, which is not BR-MAX, so the branch is stored as entry 1 and BR-COUNT becomes 1.
- Up to five. The next four lines are stored the same way, BR02 to BR05, and BR-COUNT reaches 5, the size of the table.
- The sixth line. READ gives BR06NASHIK. Now BR-COUNT = BR-MAX is true, so STORE-BRANCH does not touch the table. It keeps BR06 in REFUSED-CODE, sets TABLE-FULL and ends the loop.
- The report. After CLOSE, the program prints
too many branches: BR06 does not fit a table of 05and ends with RETURN-CODE 8, so the job sees the failure. Not one byte was written past the table.
The check costs one comparison per line, and it turns a file that has outgrown the program into a failed job with a reason, instead of data written past the end of the table, which the last section of this lesson shows.
Key idea
Read changing values into a table from a file at start-up, count the entries as they are stored, and stop with an error before an entry beyond the OCCURS limit is written.
An index is set with SET and stands for a position
A subscript is an ordinary numeric item, which you MOVE and ADD to like any other. An index: A name declared with INDEXED BY on a table and changed with SET, PERFORM VARYING or SEARCH. On IBM's compiler it holds a displacement, (entry number - 1) times the entry length. is declared with the table, BR-ENTRY OCCURS 5 TIMES INDEXED BY BR-IDX, and IBM’s guide says to change it with “a PERFORM, SEARCH, or SET statement”. It also says what an index holds on IBM’s compiler: not the entry number but a displacement, “the occurrence number (subscript) minus 1”, multiplied by the entry’s length. This program works with an index:
IDENTIFICATION DIVISION.
PROGRAM-ID. INDEXES.
* The branch table with an index. SET gives the index a value
* and moves it; SET into a numeric item turns it back into an
* entry number for DISPLAY. GnuCOBOL can also DISPLAY the index
* itself, which shows how it holds the index.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 BRANCH-VALUES.
05 FILLER PIC X(12) VALUE "BR01PUNE ".
05 FILLER PIC X(12) VALUE "BR02CHENNAI ".
05 FILLER PIC X(12) VALUE "BR03KOLKATA ".
05 FILLER PIC X(12) VALUE "BR04JAIPUR ".
05 FILLER PIC X(12) VALUE "BR05INDORE ".
01 BRANCH-TABLE REDEFINES BRANCH-VALUES.
05 BR-ENTRY OCCURS 5 TIMES INDEXED BY BR-IDX.
10 BR-CODE PIC X(4).
10 BR-CITY PIC X(8).
01 ENTRY-NO PIC 99.
PROCEDURE DIVISION.
SET BR-IDX TO 1
DISPLAY "SET BR-IDX TO 1: " BR-CODE(BR-IDX) " "
BR-CITY(BR-IDX)
SET BR-IDX UP BY 2
DISPLAY "SET BR-IDX UP BY 2: " BR-CODE(BR-IDX) " "
BR-CITY(BR-IDX)
DISPLAY "relative, BR-IDX + 1: " BR-CODE(BR-IDX + 1)
SET ENTRY-NO TO BR-IDX
DISPLAY "SET ENTRY-NO TO BR-IDX: " ENTRY-NO
DISPLAY "BR-IDX itself: " BR-IDX
PERFORM VARYING BR-IDX FROM 4 BY 1 UNTIL BR-IDX > 5
DISPLAY "VARYING BR-IDX: " BR-CODE(BR-IDX)
END-PERFORM
STOP RUN. from session import files, run
# An index set, moved, used with an offset, turned into a number, shown as GnuCOBOL holds it, and varied by PERFORM.
files("indexes.cob")
run("""
cobc -x indexes.cob && ./indexes
""") Output
$ cobc -x indexes.cob && ./indexes SET BR-IDX TO 1: BR01 PUNE SET BR-IDX UP BY 2: BR03 KOLKATA relative, BR-IDX + 1: BR04 SET ENTRY-NO TO BR-IDX: 03 BR-IDX itself: +000000003 VARYING BR-IDX: BR04 VARYING BR-IDX: BR05
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 indexes_session.py
SET BR-IDX TO 1 named BR01, and SET BR-IDX UP BY 2 moved it to BR03. BR-CODE(BR-IDX + 1) read the entry after it, BR04, without changing BR-IDX. SET ENTRY-NO TO BR-IDX converted the index back into an entry number, 3, for DISPLAY, and PERFORM VARYING moved the index through entries 4 and 5. GnuCOBOL also let the program display BR-IDX itself, and it printed +000000003: GnuCOBOL holds the entry number, where IBM’s formula gives (3 - 1) x 12 = 24 for the same entry.
| Subscript | Index | |
|---|---|---|
| Declared as | Any whole-number numeric item | INDEXED BY on the OCCURS |
| Changed with | MOVE, ADD, COMPUTE, VARYING | SET, VARYING, SEARCH |
| Holds, on IBM’s compiler | The entry number, from 1 | A displacement, (n - 1) x entry length |
| Needed by | Any table reference | SEARCH and SEARCH ALL, next lesson |
Displacements are IBM's way
GnuCOBOL keeps an index as the entry number, as BR-IDX showed, while IBM’s compiler keeps a displacement, so code that treats an index as a number can give different results on the two. Change indexes only with SET, VARYING and SEARCH, as IBM’s guide says, and use SET to turn one into a number.
Checkpoint
Check: Loading a table and checking that it fits · Indexes and SET
A subscript past the end writes over the next item unless checks are on
Nothing in the table itself stops a subscript of 6 in a five-entry table: the program computes where entry 6 would start and writes there. In bounds.cob the table of five 6-byte cities is followed in the same group by NEXT-FIELD:
IDENTIFICATION DIVISION.
PROGRAM-ID. BOUNDS.
* A table of five cities and the field stored right after it.
* The subscript 6 is one past the last entry.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 BRANCH-AREA.
05 BRANCH-TABLE.
10 BR-CITY PIC X(6) OCCURS 5 TIMES.
05 NEXT-FIELD PIC X(9) VALUE "UNTOUCHED".
01 SUB PIC 99.
PROCEDURE DIVISION.
MOVE SPACES TO BRANCH-TABLE
DISPLAY "before: NEXT-FIELD [" NEXT-FIELD "]"
MOVE 6 TO SUB
MOVE "MUMBAI" TO BR-CITY(SUB)
DISPLAY "after BR-CITY(6): NEXT-FIELD [" NEXT-FIELD "]"
STOP RUN. from session import files, run
# The same write to entry 6 of a 5-entry table, in a normal build and in a -debug build.
files("bounds.cob")
run("""
cobc -x bounds.cob && ./bounds
!cobc -x -debug -o bounds-debug bounds.cob && ./bounds-debug
""") Output
$ cobc -x bounds.cob && ./bounds before: NEXT-FIELD [UNTOUCHED] after BR-CITY(6): NEXT-FIELD [MUMBAIHED] $ cobc -x -debug -o bounds-debug bounds.cob && ./bounds-debug before: NEXT-FIELD [UNTOUCHED] libcob: bounds.cob:16: error: subscript of 'BR-CITY' out of bounds: 6 note: maximum subscript for 'BR-CITY': 5 Last statement of "BOUNDS" was MOVE at line 16 of bounds.cob ENTRY BOUNDS at bounds.cob:13 Started by ./bounds-debug [exit status 1]
Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 bounds_session.py
The normal build wrote MUMBAI into the first six bytes of NEXT-FIELD, which then read MUMBAIHED, and ended with status 0. Step through where entry 6 lands:
The drawing shows the whole scene; its 5 steps are listed below.
Every step as text
- Five entries. BR-CITY OCCURS 5 TIMES, 6 bytes each, so the table is bytes 1 to 30 of BRANCH-AREA. Entry n starts at byte 6 x (n - 1) + 1.
- The field after the table. NEXT-FIELD follows the table in the same group, at bytes 31 to 39, and holds UNTOUCHED.
- Entry 6. The same formula puts entry 6 at byte 31, which is NEXT-FIELD. Without checks, nothing compares the subscript with the 5 of OCCURS.
- The overwrite. MOVE "MUMBAI" TO BR-CITY(6) writes six bytes at byte 31, and NEXT-FIELD now reads MUMBAIHED. The normal build ended with status 0, so nothing showed the damage.
- With the checks. The -debug build stopped at the MOVE with
subscript of 'BR-CITY' out of bounds: 6and the note that the maximum is 5, so NEXT-FIELD was never touched.
The -debug build stopped at the MOVE with subscript of 'BR-CITY' out of bounds: 6 and the note that the maximum is 5,
because -debug switches on the subscript check that GnuCOBOL’s NEWS ties to -fec=bound-subscript. IBM’s compiler has
the SSRANGE option for the same purpose, which checks that subscripts and indexes do not “reference areas outside the
region of their associated tables”. Its documented default is NOSSRANGE, so a production build without it behaves
like the normal build here.
Trusting the data to fit
Wrong: MOVE BRANCH-REC TO BR-ENTRY(BR-COUNT) after ADD 1 TO BR-COUNT, with no test of BR-COUNT. Right: compare the count with the table’s size before every store, as loadfile.cob did, and run the tests with -debug.
Not every out-of-range write is so easy to see. A write past the end changes whatever follows the table, a counter, a total or a flag, and the program goes on with that wrong value; the failure often appears far from the bad subscript.
Key idea
A subscript outside the table is not an error unless a check is compiled in: test counts against the OCCURS limit in the code, and run tests with -debug, or SSRANGE on IBM’s compiler, so a missed case stops the run.
Checkpoint
Check: Out-of-range subscripts and run-time checks
Practise: tables and their limits
The questions below are about the tables, subscripts and indexes of this lesson’s programs. Work out the entry, the byte or the result first, then compare with the session that ran it:
Practice that adapts to you
Practise this lesson
15 questions about 5 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.
Then extend the loader where GnuCOBOL is installed:
A branch lookup with an error line
Extend loadfile.cob to read a second file of transactions, each with a branch code, and print each transaction’s
city by finding its branch in the table with a PERFORM VARYING loop. A code that is not in the table must print an
error line, and a branch file of 20 codes must load into a table of 20 entries without touching anything after it.
Build it with cobc -x -debug loadfile.cob while you test.
Interview questions
Warm-up (fresher to 2–5 years): how does a subscript differ from an index in COBOL?
A subscript is an ordinary whole-number data item or a literal that gives the entry number, from 1, and you change it with MOVE, ADD or COMPUTE. An index is declared with the table, OCCURS … INDEXED BY, and is changed only with SET, PERFORM VARYING or SEARCH. On IBM’s compiler an index holds a displacement, the entry number minus 1 times the entry’s length, while GnuCOBOL keeps the entry number, so code should rely on neither. SET converts between the two: SET BR-IDX TO 1 starts at the first entry, and SET ENTRY-NO TO BR-IDX gives the entry number for display. SEARCH and SEARCH ALL work only through an index.
Warm-up (fresher to 2–5 years): how many bytes does a two-dimensional table of 2 rows of 3 amounts PIC 9(5)V99 take?
42 bytes. Each amount is PIC 9(5)V99 in USAGE DISPLAY, seven digits and no byte for the implied decimal point, so 7 bytes. A row holds 3 amounts, 21 bytes, and the table holds 2 rows, 42 bytes, stored one row after the other with the inner subscript, the month, varying fastest. FUNCTION LENGTH printed 42 for the lesson’s SALES-TABLE. The same arithmetic gives every entry’s position: MONTH-AMT(B, M) starts at byte 21 x (B - 1) + 7 x (M - 1) + 1, so (2, 3) starts at byte 36.
Two harder questions follow: a table that started to corrupt a total, and whether to switch range checks on in production. Decide your first step before you open each one:
Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.
-
Mid to senior
A program keeps 20 branch codes in a table that it loads from a file. Since the file grew to 23 lines, the run's grand total is wrong, although the code that adds it has not changed and the job ends normally. What happened, how do you prove it, and what do you change?
-
Senior to staff
Production COBOL programs at your site are built without subscript range checks. After two incidents of overwritten storage, someone proposes switching on IBM's SSRANGE, or GnuCOBOL's checks, for every build. How do you decide, and what would you do as well?
Organisations named on this page
MySmartCoPilot is not linked with IBM or the GnuCOBOL project. OCCURS, subscripting, indexing and SSRANGE are cited from IBM’s manuals, the subscript check from GnuCOBOL’s NEWS, and the outputs come from GnuCOBOL 3.2 runs.
Flashcards · 8 cards
Recall it, then check
Say the answer to yourself before you look: recalling it is what makes it stick.
-
From which number does a COBOL subscript count?
From 1: BR-CODE(1) is the first entry. A subscript may be a literal or a numeric data item, and entry n starts n - 1 entry lengths after the table's first byte.
-
At which levels is OCCURS not allowed?
01, 66, 77 and 88, so a table is always part of a group.
-
In MONTH-AMT(2, 3), which subscript is which?
The outer table's comes first: branch 2, month 3. Rows are stored one after another, so the inner subscript varies fastest in storage.
-
Does GnuCOBOL 3.2 accept FUNCTION SUM(AMT(ALL))?
No, it stops with "syntax error, unexpected ALL", although IBM's compiler takes ALL subscripts. Total a table with a PERFORM VARYING loop and an accumulator.
-
What should a program check while it loads a table from a file?
The count of entries stored, against the OCCURS limit, before each store. A file that outgrows the table then fails the job with a reason instead of writing past the end.
-
How is an index declared, changed and turned into a number?
Declared with INDEXED BY on the OCCURS, changed only with SET, PERFORM VARYING or SEARCH, and turned into an entry number with SET ENTRY-NO TO BR-IDX.
-
What does an index hold on IBM's compiler, and on GnuCOBOL?
On IBM's compiler a displacement, the entry number minus 1 times the entry length; GnuCOBOL keeps the entry number. Code should rely on neither.
-
What happens when a program writes entry 6 of a five-entry table?
In a normal build it overwrites whatever follows the table, and the run ends normally. -debug stops it with the subscript out of bounds, and SSRANGE does the same on IBM's compiler, whose default is NOSSRANGE.
Key takeaways
- OCCURS describes a run of entries with the same layout, numbered from 1, and BR-CODE(3) is computed from the entry size: the five 12-byte branches made a 60-byte table.
- A table inside a table takes one subscript per level, outer first, MONTH-AMT(2, 3); GnuCOBOL 3.2 refuses IBM’s ALL subscript, so totals need a loop.
- Values that change belong in a file read at start-up, with a count checked against the OCCURS limit before every store, as the file of six branches showed.
- A subscript is a number you MOVE and ADD; an index is changed with SET, VARYING or SEARCH, holds a displacement on IBM’s compiler and is turned into a number with SET.
- Entry 6 of a five-entry table overwrote the next field without an error; -debug, or SSRANGE on IBM’s compiler, stops the run instead.
Terms in this lesson
- index
- A name declared with INDEXED BY on a table and changed with SET, PERFORM VARYING or SEARCH. On IBM's compiler it holds a displacement, (entry number - 1) times the entry length.
- OCCURS clause
- The clause that makes an item a table: ITEM OCCURS n TIMES describes n entries of the same layout, one after another, numbered from 1. It is not allowed at levels 01, 66, 77 or 88.
- subscript
- A number in brackets after a table item that picks one entry, counting from 1, as in BR-CODE(3). It is a literal or a whole-number data item, optionally plus or minus a constant.
References
- Enterprise COBOL for z/OS 6.5: OCCURS clause (IBM)
- Enterprise COBOL for z/OS 6.5: Handling tables (IBM)
- Enterprise COBOL for z/OS 6.5: Subscripting (IBM)
- Enterprise COBOL for z/OS 6.5: Indexing (IBM)
- Enterprise COBOL for z/OS 6.5: Putting values into a table (IBM)
- Enterprise COBOL for z/OS 6.5: Processing table items using intrinsic functions (IBM)
- Enterprise COBOL for z/OS 6.5: SSRANGE compiler option (IBM)
- GnuCOBOL 3.2 NEWS (GnuCOBOL project (GNU))
Report a problem with this lesson
Kept only in this browser. Your Learn progress