Declaring OCCURS 500 on a twenty-byte field is not a naming exercise—it is a memory contract. Easytrieve allocates contiguous storage for every occurrence whether you touch one element or all five hundred. Batch jobs run inside a REGION ceiling; report programs copy W working storage to spool work files at PRINT; FILE record buffers expand when repeating groups sit on input layouts. Beginners who copy COBOL copybooks without byte math abend with storage violations or compile against FLDMAX limits their site set years ago. Array memory is element length times occurrence count, plus the INDEX subscript field, plus every other large structure in the same program—TABLE rows, VIRTUAL work files, static S pools, and multi-file buffers. This page teaches how to calculate bytes, compare W versus S behavior for arrays in reports, plan FILE LRECL with OCCURS, size INDEX safely, relate arrays to TABLE memory models, and document REGION estimates operations can approve before production night.
DEFINE LINE-ITEM W 40 A OCCURS 25 allocates twenty-five forty-byte alphanumeric elements—one thousand bytes for the array body. Packed fields use storage length, not picture digit count: DEFINE AMT W 5 P 2 is five bytes per element. One-byte OCCURS 80 for character walks uses eighty bytes total. Before coding, write element-bytes × OCCURS on paper; compare to FLDMAX documented for your release. Nested OCCURS multiplies: a group OCCURS 10 containing a field OCCURS 5 yields fifty leaf elements at the inner field's length when both index together.
12345DEFINE WS-TOTAL W 7 P 2 DEFINE WS-IDX W 3 N 0 DEFINE WS-AMTS W 5 P 2 OCCURS 200 INDEX WS-IDX * Array body ≈ 200 × 5 = 1000 bytes * INDEX field = 3 bytes (separate)
FLDMAX is an Easytrieve installation option capping maximum field allocation. A single DEFINE whose total OCCURS span exceeds FLDMAX fails compile or generation. Operations owns the value; developers must read site standards before declaring scratch tables rivaling small databases. When FLDMAX blocks your design, split data across passes, use external TABLE files with max-table-entries, or move large reference to SQL ACCESS—not silent truncation.
| Location | Allocation | Report impact |
|---|---|---|
| W (non-static) | Per working storage pool | Copied to report work file at PRINT |
| S (static) | Static pool for run | Stays in static storage during formatting |
Large W arrays inside hot PRINT paths increase spool work file width—every printed record may carry copied bytes you only needed for one column. Prefer S for accumulators that must survive across report lines when documentation supports it, or shrink what PRINT references. Do not duplicate a thousand-byte W array on every detail line unintentionally.
12345FILE INVOICE FB(200) INV-NO 1 8 A LINE-DESC 20 30 A OCCURS 5 INDEX LINE-IX * Five × 30 = 150 bytes for lines starting at 20 * Verify positions 20–169 fit inside 200-byte record
OCCURS on FILE fields lives in the record buffer loaded by GET. Total defined record length must match JCL DCB LRECL. Variable-length records with repeating groups need explicit length discipline—VB layouts may not tolerate naive OCCURS without understanding RDW and maximum record size. Misaligned offsets read garbage into array slots and corrupt INDEX walks.
INDEX is its own DEFINE numeric field—typically W 3 N 0 or wider for OCCURS above 999. INDEX does not consume occurrence slots but must hold values 1 through OCCURS maximum. Undersized INDEX causes subscript wrap in logic while storage still allocated full array—debugging nightmare. Size INDEX with one digit of headroom beyond current OCCURS for maintenance growth.
| Aspect | OCCURS array | FILE TABLE |
|---|---|---|
| Access | Set INDEX, use element name | SEARCH WITH GIVING |
| Load | Program logic fills slots | INSTREAM or external read at initiation |
| Key order | Your responsibility if binary search needed | ARG must be ascending at load |
| Typical size | Scratch tables built per run | Hundreds to low thousands of rows |
DEFINE CHARS W 1 A OCCURS 80 INDEX CH-IX overlays a string buffer for parsing. Memory is eighty bytes whether you scan three characters or eighty. Parent field may alias same storage—changing CHARS element 5 updates the parent byte. Overlay arrays do not allocate twice; they reinterpret contiguous bytes already reserved for the parent DEFINE.
When PRINT references W array elements, work file copies may include those bytes per report field selection. Wide scratch arrays referenced on LINE increase spool record size and sort cost when SEQUENCE runs. Keep report-facing arrays narrow; build large scratch in S or in VIRTUAL intermediate files when REPORT does not need every element on every line.
An array is a row of same-sized boxes. If each box holds forty toy cars and you have twenty-five boxes, you need space for one thousand cars on the shelf—even if you only play with box three today. INDEX is the number on the box you open. FLDMAX is the rule saying your shelf cannot be wider than the wall allows. W boxes get photocopied when you show them on the report poster; S boxes stay on the main shelf. FILE arrays are boxes glued inside each incoming shipping crate—the crate must be big enough for all boxes or the lid will not close.
1. Total bytes for DEFINE AMOUNT W 5 P 2 OCCURS 100 is approximately:
2. FLDMAX in Easytrieve options affects:
3. W array fields at PRINT time:
4. OCCURS on a FILE field allocates storage:
5. INDEX field for OCCURS 200 should be sized to hold: