COBOL Working Storage: Layout, 88-Levels, REDEFINES, and VALUE

The WORKING-STORAGE SECTION is where COBOL programs live. Unlike file records (which are I/O buffers) or linkage items (which point to caller memory), working storage is owned entirely by the program — allocated at load time, initialized with VALUE clauses, and available throughout every paragraph and section. Designing it well makes programs readable, maintainable, and easier to debug.
Organizing Working Storage
Large COBOL programs may have thousands of working-storage fields. Structure matters. The conventional organization groups related fields under named 01-level records:
WORKING-STORAGE SECTION.
*===============================================================*
* PROGRAM FLAGS AND SWITCHES *
*===============================================================*
01 WS-FLAGS.
05 WS-EOF-FLAG PIC X VALUE 'N'.
88 WS-EOF VALUE 'Y'.
88 WS-NOT-EOF VALUE 'N'.
05 WS-ERROR-FLAG PIC X VALUE 'N'.
88 WS-ERROR-FOUND VALUE 'Y'.
88 WS-NO-ERROR VALUE 'N'.
05 WS-RECORD-VALID-FLAG PIC X VALUE 'N'.
88 WS-RECORD-VALID VALUE 'Y'.
88 WS-RECORD-INVALID VALUE 'N'.
*===============================================================*
* PROGRAM COUNTERS *
*===============================================================*
01 WS-COUNTERS.
05 WS-RECORDS-READ PIC 9(9) COMP VALUE ZERO.
05 WS-RECORDS-PROCESSED PIC 9(9) COMP VALUE ZERO.
05 WS-RECORDS-SKIPPED PIC 9(9) COMP VALUE ZERO.
05 WS-ERROR-COUNT PIC 9(5) COMP VALUE ZERO.
*===============================================================*
* FILE STATUS FIELDS *
*===============================================================*
01 WS-FILE-STATUSES.
05 WS-INPUT-STATUS PIC XX VALUE SPACES.
88 WS-INPUT-OK VALUE '00'.
88 WS-INPUT-EOF VALUE '10'.
88 WS-INPUT-NOT-FOUND VALUE '23'.
05 WS-OUTPUT-STATUS PIC XX VALUE SPACES.
88 WS-OUTPUT-OK VALUE '00'.
88 WS-OUTPUT-DUP-KEY VALUE '22'.
*===============================================================*
* WORK AREAS *
*===============================================================*
01 WS-WORK-AREAS.
05 WS-CURRENT-DATE PIC X(10).
05 WS-FORMATTED-AMOUNT PIC ZZZ,ZZZ,ZZ9.99-.
05 WS-TEMP-CALC PIC S9(13)V99 COMP-3.
05 WS-RETURN-CODE PIC S9(4) COMP VALUE ZERO.
*===============================================================*
* CONSTANTS *
*===============================================================*
01 WS-CONSTANTS.
05 WS-PROG-NAME PIC X(8) VALUE 'ACCTPROC'.
05 WS-MAX-ERRORS PIC 9(4) COMP VALUE 100.
05 WS-INTEREST-RATE PIC V9(6) COMP-3 VALUE .065000.
05 WS-ZERO-AMOUNT PIC S9(11)V99 COMP-3 VALUE ZERO.The asterisk-delimited comment blocks act as section dividers. This convention is universal in production mainframe code and makes large DATA DIVISIONs navigable.
88-Level Condition Names in Depth
88-level entries are one of COBOL's most powerful features. They transform arbitrary character or numeric values into named Boolean conditions that can be tested and set.
Multiple Values and Ranges
A single 88-level can test for multiple values or a range:
01 WS-TRANSACTION-CODE PIC X(2).
88 TC-DEPOSIT VALUE 'DP'.
88 TC-WITHDRAWAL VALUE 'WD'.
88 TC-TRANSFER VALUE 'TF'.
88 TC-INQUIRY VALUE 'IQ'.
88 TC-FINANCIAL VALUE 'DP' 'WD' 'TF'. *> multiple values
88 TC-VALID VALUE 'DP' 'WD' 'TF' 'IQ' 'CL' 'OP'.
01 WS-RESPONSE-CODE PIC 9(4) COMP.
88 RC-SUCCESS VALUE 0.
88 RC-WARNING VALUE 1 THRU 99. *> range
88 RC-ERROR VALUE 100 THRU 999.
88 RC-FATAL VALUE 1000 THRU 9999.The VALUE ... THRU ... syntax tests whether the field's value falls within an inclusive range. This replaces verbose IF X >= 100 AND X <= 999 conditions.
Setting Condition Names
Use SET ... TO TRUE to assign the corresponding value:
SET TC-DEPOSIT TO TRUE *> moves 'DP' to WS-TRANSACTION-CODE
SET WS-EOF TO TRUE *> moves 'Y' to WS-EOF-FLAG
SET WS-ERROR-FOUND TO TRUE *> moves 'Y' to WS-ERROR-FLAGSET ... TO FALSE is also supported when a FALSE VALUE is defined:
01 WS-PROCESSING-FLAG PIC X VALUE 'N'.
88 PROCESSING-ACTIVE VALUE 'Y'
WHEN SET TO FALSE VALUE 'N'.
*> Then in procedure:
SET PROCESSING-ACTIVE TO TRUE *> moves 'Y'
SET PROCESSING-ACTIVE TO FALSE *> moves 'N'Condition Names for File Status
88-levels on FILE STATUS fields make error handling far cleaner:
01 WS-VSAM-STATUS PIC XX.
88 VSAM-OK VALUE '00'.
88 VSAM-EOF VALUE '10'.
88 VSAM-NOT-FOUND VALUE '23'.
88 VSAM-DUP-KEY VALUE '22'.
88 VSAM-LOCKED VALUE '9D'.
88 VSAM-OPEN-ERROR VALUE '90' '91' '92' '93' '94' '95' '96' '97'.
*> Usage:
READ CUSTOMER-FILE
IF VSAM-OK
PERFORM PROCESS-RECORD
ELSE IF VSAM-NOT-FOUND
PERFORM HANDLE-NOT-FOUND
ELSE
PERFORM HANDLE-VSAM-ERROR
END-IFCompared to: IF WS-VSAM-STATUS = '00' ... — the condition-name version is unambiguous and self-documenting.
REDEFINES Patterns
REDEFINES lets two data names share the same storage. It is used for type-punning, union types, and multiple interpretations of the same bytes.
Date Fields: Packed vs Structured
The most common REDEFINES pattern splits an 8-digit packed date into its components:
01 WS-DATE-PACKED PIC 9(8) COMP VALUE ZERO.
01 WS-DATE-STRUCTURED REDEFINES WS-DATE-PACKED.
05 WSD-YEAR PIC 9(4).
05 WSD-MONTH PIC 9(2).
05 WSD-DAY PIC 9(2).Now you can assign a date as a single 8-digit number:
MOVE 20260120 TO WS-DATE-PACKEDAnd read it back as components:
DISPLAY 'YEAR: ' WSD-YEAR *> 2026
DISPLAY 'MONTH: ' WSD-MONTH *> 01
DISPLAY 'DAY: ' WSD-DAY *> 20Union Types for Polymorphic Records
When a record can contain different payload types identified by a type code:
01 WS-TRANSACTION-RECORD.
05 TR-TYPE-CODE PIC X(2).
05 TR-PAYLOAD PIC X(100).
01 TR-PAYMENT-PAYLOAD REDEFINES TR-PAYLOAD.
05 PP-ACCOUNT-ID PIC X(10).
05 PP-AMOUNT PIC S9(11)V99 COMP-3.
05 PP-CURRENCY PIC X(3).
05 FILLER PIC X(80).
01 TR-INQUIRY-PAYLOAD REDEFINES TR-PAYLOAD.
05 IP-ACCOUNT-ID PIC X(10).
05 IP-INQUIRY-TYPE PIC X(2).
05 FILLER PIC X(88).Usage:
EVALUATE TR-TYPE-CODE
WHEN 'PY'
PERFORM PROCESS-PAYMENT-USING-PP-PAYLOAD
WHEN 'IQ'
PERFORM PROCESS-INQUIRY-USING-IP-PAYLOAD
END-EVALUATEREDEFINES Rules to Remember
- The redefining item must immediately follow the redefined item at the same level number
- The redefining item cannot be larger than the redefined item
- VALUE clauses (except on 88-level subordinates) are not permitted on a redefining item
- You can have multiple items redefining the same original item — they all share the same storage
01 WS-BASE PIC X(10).
01 WS-AS-DIGITS REDEFINES WS-BASE PIC 9(10).
01 WS-SPLIT REDEFINES WS-BASE.
05 WS-FIRST-HALF PIC X(5).
05 WS-SECOND-HALF PIC X(5).VALUE Clause Patterns
Initializing Complex Records
VALUE can be applied at the group level using a hex literal or string:
01 WS-INITIALIZED-RECORD.
05 WS-FIELD-A PIC X(10) VALUE SPACES.
05 WS-FIELD-B PIC 9(5) COMP VALUE ZERO.
05 WS-FIELD-C PIC X(2) VALUE 'AC'.For an entire 01-level record, you can also use VALUE SPACES or VALUE LOW-VALUES to initialize all bytes at once:
01 WS-REPORT-LINE PIC X(132) VALUE SPACES.
01 WS-WORK-BUFFER.
05 FILLER PIC X(1000) VALUE LOW-VALUES.Constants Pattern
Centralize all program constants in a dedicated 01-level group:
01 WS-PROGRAM-CONSTANTS.
05 WS-PROG-ID PIC X(8) VALUE 'ACCTBAL '.
05 WS-VERSION PIC X(4) VALUE '1.02'.
05 WS-MAX-RETRY PIC 9(2) COMP VALUE 3.
05 WS-TIMEOUT-SECS PIC 9(4) COMP VALUE 30.
05 WS-ANNUAL-RATE PIC V9(8) COMP-3 VALUE .05250000.
05 WS-MONTHLY-RATE PIC V9(8) COMP-3 VALUE .00437500.Never scatter literals through the PROCEDURE DIVISION. When an interest rate changes from 5.25% to 5.50%, you want exactly one change in exactly one place.
SQL Communication Area (SQLCA)
Programs that use embedded SQL include the SQLCA in working storage. On z/OS this is typically brought in via COPY:
WORKING-STORAGE SECTION.
EXEC SQL INCLUDE SQLCA END-EXEC.The SQLCA provides SQLCODE (0 = success, negative = error, +100 = not found) and SQLERRM (error message text). You also declare host variables in working storage:
01 WS-DB2-FIELDS.
05 WS-ACCOUNT-ID PIC X(10).
05 WS-BALANCE PIC S9(11)V99 COMP-3.
05 WS-DB2-DATE PIC X(10).
01 WS-NULLIND.
05 WS-BALANCE-IND PIC S9(4) COMP.Indicator variables (WS-BALANCE-IND) detect DB2 NULL values — -1 means the column was NULL.
CICS COMMAREA in Working Storage
CICS pseudo-conversational programs define a working copy of the COMMAREA in WORKING-STORAGE and map the DFHCOMMAREA linkage section onto it:
WORKING-STORAGE SECTION.
01 WS-COMMAREA.
05 WCA-TRANSACTION-STATE PIC X(2).
88 WCA-INITIAL-ENTRY VALUE '00'.
88 WCA-AFTER-INQUIRY VALUE '01'.
88 WCA-AFTER-UPDATE VALUE '02'.
05 WCA-ACCOUNT-ID PIC X(10).
05 WCA-BALANCE PIC S9(11)V99 COMP-3.
05 WCA-MESSAGE PIC X(50).
LINKAGE SECTION.
01 DFHCOMMAREA PIC X(75).
PROCEDURE DIVISION.
IF EIBCALEN > ZERO
MOVE DFHCOMMAREA TO WS-COMMAREA
ELSE
INITIALIZE WS-COMMAREA
SET WCA-INITIAL-ENTRY TO TRUE
END-IF.This pattern copies the COMMAREA into working storage at the start of every task — providing structured access to the 88-level condition names and COMP-3 fields.
INITIALIZE Statement
INITIALIZE sets all subordinate elementary items in a group to their default values — numeric fields to zero, alphanumeric fields to spaces:
INITIALIZE WS-COUNTERS *> all COMP fields → 0
INITIALIZE WS-REPORT-FIELDS *> all X fields → spaces
INITIALIZE WS-COMMAREA *> mixed — each field gets its type defaultYou can also initialize to specific values:
INITIALIZE WS-ACCOUNT-RECORD
REPLACING ALPHANUMERIC BY SPACES
NUMERIC BY ZERO.INITIALIZE is cleaner than a block of MOVE ZERO TO ... and MOVE SPACES TO ... statements, but be careful with COMP-3 fields in groups that also contain DISPLAY fields — the initialization applies the correct default for each elementary item's type.
Conclusion
A well-organized WORKING-STORAGE SECTION makes the difference between a program that is easy to maintain for 30 years and one that becomes incomprehensible after 30 months. Use named group records for related fields, 88-levels for all flags and status codes, constants for magic values, and REDEFINES only when genuinely needed for multiple interpretations of the same data.
Continue to COBOL Arithmetic for ADD, SUBTRACT, COMPUTE, and the ROUNDED and SIZE ERROR options, or browse the full COBOL Mastery curriculum.
