COBOL copybook · EBCDIC cp037 · 72-byte fixed record

The sign is in the last byte

A mainframe extract is bytes, not a file format. Nothing inside it says where one field ends and the next begins, whether a number is negative, or where its decimal point belongs. All of that lives in a separate document — and when the two disagree, the load still succeeds and the numbers are still wrong.

Open the inspector →   to run this against a copybook of your own.

Layout UTLBILL.cpy (synthetic) Records 100,000 Proposals by Adjudicated by the bytes

Watch it refuse

Eighty seconds, no sound. The same copybook against two files — one it does not describe, and one it does. Every frame is the tool running, not a mock-up.

Who has this problem

Anyone moving decades of mainframe data into a warehouse, a lake, or a new system — which right now is most large banks, insurers, utilities and government agencies in Europe.

What you are given

Two files and no schema

A flat file of fixed-length records in EBCDIC, and a COBOL copybook describing the layout. The file has no header, no delimiters and no types. The copybook is the only thing that makes it readable — and it was last edited by someone who has retired.

What people do

Write a loader in an afternoon

Slice each record at fixed offsets, strip anything that isn't a digit, cast to a number, load it. It runs. It produces a table. Row counts match the source exactly, which is the check most teams stop at.

What goes wrong

Nothing raises an error

Credits arrive as charges. Amounts arrive a hundred times too large. A code column silently falls through every branch. There is no exception, no rejected row, no red mark — just a column of plausible numbers that are wrong, sitting in a warehouse being reported on.

The two files you are handed

Click any field in the copybook to select it in the inspector below. The raw bytes are the same 60 records, shown as they actually sit on disk.

UTLBILL.cpy the layout — 22 lines of COBOL
UTLBILL.dat the data — 72 bytes per record

Press As text to see what happens when this file is opened in an ordinary editor. The bytes are unchanged; only the assumed character set differs. EBCDIC is not ASCII, and nothing in the file announces which one it is.

Three ways to read the same column

Not three settings. Three real loaders, of which two are common and both are wrong.

Correct

Recover the digit hiding under the sign, apply the sign, then shift the implied decimal point that the copybook declares and the file does not store.

# PIC S9(08)V99, EBCDIC, trailing overpunch
digits, sign = split_overpunch(text)
value = Decimal(digits) * sign
value = value.scaleb(-2)   # the V99

What overpunch does.

Sign ignored

The last byte of a negative value is } or J–R, not a digit. Strip non-digits and it disappears — along with the digit sharing that byte. Every credit silently becomes a charge.

value = int(re.sub(r"\D", "", text)) / 100

The most common mistake, because it looks defensive.

Digits only

The same, plus forgetting that V99 means two decimal places that are never written down. Cents are read as whole units and every figure is a hundred times too large.

value = int(re.sub(r"\D", "", text))

Usually spotted — but only when someone already knows the true total.

What the difference costs

BIL-ADJUSTMENT-AMT totalled across all 100,000 records by the tool. Same bytes each time.

Look at a record yourself

60 verbatim records are embedded in this page and decoded here in your browser — these figures are computed live, not quoted. Click a byte to select its field.

Read as
selected field sign byte — not a digit alternating field bands

What the scan measured

No model involved. Every line carries the number of records it was observed in, and where the consequence is arithmetic, the arithmetic.

What the model proposed, and what the bytes said back

Nemotron may only propose from a closed vocabulary the prober knows how to test. A hallucination cannot become a finding here — only a refuted hypothesis.

When the copybook is a photograph

Plenty of copybooks are not files. They are printouts, or images inside a PDF nobody can select text out of, and the person who could retype them left in 2009.

A scanned printout of a COBOL copybook listing, on fanfold paper
Fed to — no text layer, no selectable characters. Just paper.
Two real reads of this page

        

Same model, same image, two attempts. One is right. The other names a field DALYTRANS-ID, truncates another to DALY, and parses as perfectly valid COBOL — nothing about its shape gives it away.

What settles it is that a copybook makes a falsifiable prediction. The field widths must sum to the record length printed on the page, and the real 105,000-byte data file must divide by it. A model read the paper; the arithmetic decided whether it read it right. An unreliable reader plus a decisive check is a reliable pipeline — so the tool simply re-reads until a layout is proved, and tells you how many attempts it took.

From copybook to a database

A copybook describes bytes. A schema needs answers the bytes do not carry. So nothing is generated from the copybook — a plan is, and the plan is what a person reviews and edits. Everything below is real output of the tool.

Layout

      

Try it on your own files

Point it at a copybook of your own, with or without a data file.

stays local

Nothing is uploaded. The parser and the rules run in this page, in your browser — there is no server to send anything to. That is not a convenience; the data this tool is for is exactly the data nobody is allowed to put on a website, so the analysis has to come to the bytes instead. You can disconnect your network and this section still works.

Change it if text reads as gibberish.
Set this when the copybook is only a view of a longer record.

Vocabulary

Six terms that carry all the trouble.

Copybook
A fragment of COBOL declaring a record's fields in order. It is the schema, kept in a separate file from the data, with nothing enforcing that the two agree.
EBCDIC
IBM's character set, older than ASCII and incompatible with it. Several variants exist — cp037, cp500, cp1047 — differing on characters people actually use.
PIC S9(08)V99
Eight digits, then two more after an implied decimal point. S means signed. Ten bytes on disk, no point, no sign character.
Overpunch
The sign, encoded into the upper half of the last byte, leaving the digit in the lower half. A term inherited from punched cards, where it was an extra hole in the same column.
COMP-3
Packed decimal: two digits per byte, sign in the final nibble. Read as text it is unprintable garbage; read as a string it is silently truncated.
88-level
A named condition on a field's value. Two of them can claim the same value, which no tool can resolve — and one that guesses is worse than one that stops.

Every figure on this page is real output of overpunch run against demo/UTLBILL.dat. The record layout, its domain and every byte of its data are invented for the demo — no copybook or dataset belonging to any organisation appears here. Full-file totals come from the tool's own 100,000-record pass; the inspector's figures are computed in your browser from the 60 records embedded in this page, by a second decoder written independently of the first. Comparing the two across 660 field reads is how a digit-dropping bug in the original was found.