Mastering COBOL UNSTRING: Pointers, Counts, and Safe Parsing
Learn how to use COBOL’s UNSTRING safely—control pointers, capture token lengths, guard against overflow, and avoid CSV pitfalls.
29 Jul 2025, 02:05 UTC

Problem: Why COBOL’s UNSTRING Can Surprise You
When a mainframe application needs to split a text field—say a comma‑separated list from a VSAM record—many developers reach for the UNSTRING statement. It looks simple: give it a string, tell it where the delimiters are, and it hands you pieces. In practice, a few subtle rules can cause silent truncation, missing data, or overflow errors that slip past unit tests.
Key surprises:
- UNSTRING moves data as an alphanumeric operation; numeric targets need explicit conversion.
- The
COUNT INclause records how many characters were examined, not the length of the extracted token. - Pointer values are 1‑based and must be reset before each call.
- Adjacent delimiters always produce an empty field that appears as spaces.
- It does not understand CSV quoting or escaped delimiters.
Understanding these quirks lets you write robust parsers that guard against data loss.
Thesis: Use UNSTRING as a low‑level splitter, not a CSV engine
UNSTRING is best for simple, well‑defined delimiters. When you need quoted fields, embedded delimiters, or robust error handling, pre‑process the data or switch to a dedicated parser. Below, we show how to control UNSTRING’s behavior, capture token lengths, and detect overflow.
Section 1 – Alphanumeric Moves and COUNT IN
All receiving fields in an UNSTRING must be declared PIC X or a subtype of it. If you place a numeric field (e.g., PIC 9(3)) directly in the INTO list, COBOL applies numeric move rules, which can shift sign or decimal point unintentionally. Keep the fields alphanumeric and convert afterward with NUMVAL or an intrinsic if arithmetic is required.
The COUNT IN phrase stores the number of characters from the sending field that were examined to produce each token. This count excludes the delimiter itself, so it tells you how many source characters were consumed, not the token size. It is especially useful when the downstream logic depends on token length (e.g., distinguishing a three‑character code from a longer name).
Section 2 – Pointer Management and Delimiter Semantics
When you need to resume parsing after having consumed part of the string, use WITH POINTER. The pointer is a 1‑based index into the sending field. It must be set before each UNSTRING call; otherwise the statement uses whatever value happened to be in the variable, leading to unpredictable results. A common mistake is reusing a pointer value from a previous parse, which can skip data or produce all‑space fields if the pointer exceeds the string length.
Delimiter choice matters. DELIMITED BY SPACE splits on every individual space character, so two consecutive spaces create an empty field. DELIMITED BY ALL SPACES treats a run of spaces as a single delimiter, collapsing the gap. Both forms still produce an empty field when delimiters are adjacent; the field will contain spaces, not nulls. Always test for spaces after the move if a missing value is significant.
Section 3 – CSV Limitations and ON OVERFLOW
UNSTRING has no concept of quoted fields or escaped delimiters. A comma inside a quoted CSV field will be treated as a delimiter, breaking the record. If you must handle true CSV, preprocess the data or use a dedicated CSV library.
When the sending field contains more delimited segments than the number of receiving fields, the ON OVERFLOW clause fires. Without it, the extra segments are silently discarded. Use ON OVERFLOW to log the event, route the record to an error file, or raise an exception.
Section 4 – Worked Example and Practical Checklist
The following skeleton shows a complete UNSTRING operation that:
- Splits a comma‑delimited string into four tokens.
- Captures how many characters were examined for each token.
- Resets the pointer before parsing.
- Handles overflow safely.
IDENTIFICATION DIVISION.
PROGRAM-ID. UNSTRING-EXAMPLE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-RECORD PIC X(50).
01 WS-TOKEN-1 PIC X(10).
01 WS-TOKEN-2 PIC X(10).
01 WS-TOKEN-3 PIC X(10).
01 WS-TOKEN-4 PIC X(10).
01 WS-LEN-1 PIC 9(4).
01 WS-LEN-2 PIC 9(4).
01 WS-LEN-3 PIC 9(4).
01 WS-LEN-4 PIC 9(4).
01 WS-POINTER PIC 9(4).
PROCEDURE DIVISION.
MOVE 'ALPHA,BETA,,GAMMA' TO WS-RECORD
MOVE 1 TO WS-POINTER
UNSTRING WS-RECORD
DELIMITED BY ','
INTO WS-TOKEN-1 COUNT IN WS-LEN-1
WS-TOKEN-2 COUNT IN WS-LEN-2
WS-TOKEN-3 COUNT IN WS-LEN-3
WS-TOKEN-4 COUNT IN WS-LEN-4
WITH POINTER WS-POINTER
ON OVERFLOW
DISPLAY 'ON OVERFLOW: too many segments'
END-UNSTRING
DISPLAY 'TOKEN1: ' WS-TOKEN-1 ' LEN: ' WS-LEN-1
DISPLAY 'TOKEN2: ' WS-TOKEN-2 ' LEN: ' WS-LEN-2
DISPLAY 'TOKEN3: ' WS-TOKEN-3 ' LEN: ' WS-LEN-3
DISPLAY 'TOKEN4: ' WS-TOKEN-4 ' LEN: ' WS-LEN-4
STOP RUN.
Verification steps:
- Set
WS-POINTERto 6 before theUNSTRINGand observe that parsing starts at the sixth character, skipping the first token. - Replace the comma with a double space and run the program with
DELIMITED BY SPACEversusDELIMITED BY ALL SPACESto see how adjacent delimiters affect field counts. - Append a fifth comma‑delimited value to
WS-RECORDand confirm that theON OVERFLOWbranch executes.
Limitations & Actionable Checklist
• Truncation: Receiving fields that are too short silently truncate data. Size each PIC X field to the maximum expected token length.
• Pointer misuse: Reusing a pointer value can skip data or produce blanks. Reset the pointer to 1 (or the desired offset) on every parse.
• Adjacent delimiters: Empty fields appear as spaces. If a missing value is significant, test for spaces after the move.
• CSV quoting: UNSTRING cannot handle quoted fields or escaped delimiters. Pre‑process or switch to a CSV parser if needed.
Before deploying UNSTRING in production:
- Verify that
COUNT INmatches expected token lengths. - Force an
ON OVERFLOWby feeding a record with more segments than receiving fields. - Reset
WITH POINTERto 1 for each new record. - Check for spaces in empty fields if missing data is meaningful.
By treating UNSTRING as a low‑level splitter and applying these guardrails, you can avoid silent data loss and build reliable text‑processing routines on the mainframe.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.