COBOLMainframe

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

TT
TopicTrick
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:

cobol
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:

cobol
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:

cobol
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-FLAG

SET ... TO FALSE is also supported when a FALSE VALUE is defined:

cobol
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:

cobol
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-IF

Compared 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:

cobol
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:

cobol
MOVE 20260120 TO WS-DATE-PACKED

And read it back as components:

cobol
DISPLAY 'YEAR: '  WSD-YEAR   *> 2026
DISPLAY 'MONTH: ' WSD-MONTH  *> 01
DISPLAY 'DAY: '   WSD-DAY    *> 20

Union Types for Polymorphic Records

When a record can contain different payload types identified by a type code:

cobol
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:

cobol
EVALUATE TR-TYPE-CODE
    WHEN 'PY'
        PERFORM PROCESS-PAYMENT-USING-PP-PAYLOAD
    WHEN 'IQ'
        PERFORM PROCESS-INQUIRY-USING-IP-PAYLOAD
END-EVALUATE

REDEFINES Rules to Remember

  1. The redefining item must immediately follow the redefined item at the same level number
  2. The redefining item cannot be larger than the redefined item
  3. VALUE clauses (except on 88-level subordinates) are not permitted on a redefining item
  4. You can have multiple items redefining the same original item — they all share the same storage
cobol
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:

cobol
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:

cobol
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:

cobol
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:

cobol
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:

cobol
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:

cobol
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:

cobol
INITIALIZE WS-COUNTERS           *> all COMP fields → 0
INITIALIZE WS-REPORT-FIELDS      *> all X fields → spaces
INITIALIZE WS-COMMAREA           *> mixed — each field gets its type default

You can also initialize to specific values:

cobol
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.