Abend
You wrote a program, punched it, and handed the deck over a counter. What came back the next day was either your report or a listing with a message on it. That is the whole feedback loop, once every twenty-four hours, and it is the reason the language you were writing in wrapped a loop of its own around your code so that you had less to get wrong.
New to batch computing? Start here
There was no screen. You wrote a program on paper, had it punched onto cards, and handed the deck across a counter. Some hours later you were given back a printout, and that printout was the entire conversation: no stepping through, no trying again, no seeing what a value was at the time.
So a mistake did not cost you a minute. It cost you until tomorrow, and machine time was billed. That is the pressure everything on this page was designed under, and it is why the diagnostics look the way they do: a code and a dump were all you were going to get, so they had to be enough.
A computer only has numbers
There are no letters in a computer, no colours and no sound. There are numbers, and an agreement about what a given number means. The letter A is a particular number because a committee said so, and for no other reason.
That agreement is an encoding, and the interesting part is never the table. It is what the table costs: how many bits each symbol takes, which symbols were favoured, what happens to the ones nobody thought of, and whether you can start reading in the middle. Every machine in this topic is an argument about that cost, settled differently.
The machine for this idea on its own is ASCII, if you would rather press it than read about it.
The loop you did not write
RPG generates a program around your specifications. Its manual numbers the items of that cycle from 1 to 15. Three of them are yours. Step through a deck and watch which is which, and watch the indicators the cycle sets on your behalf.
- item
- 1
- whose
- the compiler's
- what it did
- wrote the page heading before any record was read
- indicators
- none on
The fifteen items
- 1 Before the first record is read, the program prepares and writes any heading information to be put out on the first page.
- 2 After the first record has been read, the program prepares and writes heading and detail information which is not conditioned on overflow.
- 3 The generated program tests for any halt indicators. If any halt indicators are on, the program branches to item 12.
- 4 The generated program tests for the end-of-file conditions. If the end-of-file condition has occurred, the program branches to item 13.
- 5 The generated program then reads an input record. All control level indicators and all resulting indicators are turned off, the record identification code identifies the record, and when a control-field break occurs the appropriate control-level indicators are turned on.
- 6 Next, all total calculations are performed. This step is bypassed for the initial control break caused by reading the first input record.
- 7 Next, all total output records which are not conditioned on overflow are prepared and put out. This step is also bypassed for the first control break.
- 8 The generated program tests for the last record indicator (LR). If it is on, the program branches to item 14.
- 9 The object module tests for an overflow condition. If an overflow condition has occurred, the program branches to item 15.
- 10 The data fields contained in the input record just read are moved into storage.
- 11 Any detail calculations are performed, and processing continues with item 1.
- 12 Program execution is terminated.
- 13 The Last-Record indicator (LR) is set ON and all control-level indicators L1-L9 are set ON. Then the program branches to item 6.
- 14 Program execution is terminated.
- 15 If overflow has occurred, total lines, heading lines and detail lines (in that order) conditioned by overflow are printed. The program then branches to item 10.
What has come off the printer
HEADING
What you actually wrote
You did not type a program. You wrote it on a pre-printed form, one line per card, and the compiler read each field out of its own columns. A name beginning one column too far left was a different field, or no field at all. Fill the boxes and watch the card underneath: that line of eighty characters is the whole of what the machine received.
the card, as the compiler reads it
010C AMONT ADD TOTAL TOTAL
column 1
Where these column numbers come from
- Control Levelcolumns 7 to 8. “Control Level (columns 7 and 8) of the specification must have a cont,rol level specification”
- Indicatorscolumns 9 to 17. “Indicators 9-17 Entelr one to three indicators”
- Factor 1columns 18 to 27. “Enter either the name or the literal that is Factor 1 or Factor 2 in columns 18-27 or 33-42”
- Factor 2columns 33 to 42. “Enter either the name or the literal that is Factor 1 or Factor 2 in columns 18-27 or 33-42”
- Result Fieldcolumns 43 to 48. “writing the name FLDD in Result Field (columns 43-48)”
What the compiler would say
- 4 AMONT in Factor 1 is not defined anywhere, so it is assumed to be zero
And the sheet that says where a field is
The sheet above works on names: ADD AMOUNT TO TOTAL. The names come from the Input specifications sheet, which says which columns of the card each field occupies. The manual is explicit about what that buys you: “Once the card columns of the field have been specified and the appropriate field name has been defined for the field, other references to this field are made by using its field name rather than writing down the specific card columns each time.”
You say it once. Everything afterwards trusts the name. So move the field one column and watch what the compiler says about it.
| card, columns 21 to 30 | what AMOUNT reads | value | should be |
|---|---|---|---|
| ··012500·· | 012500 | 125.00 | 125.00 |
| ··003750·· | 003750 | 37.50 | 37.50 |
| ··088000·· | 088000 | 880.00 | 880.00 |
Total 1,042.50, which is the right answer. The columns describe where the money actually is.
And what it cost to get wrong
One submission a day. The compiler graded every diagnostic it found and returned the worst one: nothing, a warning it carried on past, or an error and no program. Faults of the same severity come back together, because one pass finds them all, so what costs you days is having faults of different kinds.
These are the faults in the line you wrote above, nothing else. Change it and this changes.
| day | return code | what came back |
|---|---|---|
| 1 | 4 warning | a listing, a program, and a diagnostic saying it assumed something for you |
| 2 | 0 no diagnostics | a listing and a program |
2 days, one submission each, and the last one is the day it finally worked.
And what an abend is
Everything above is a fault the job survives. A return code of 4, or a field read one column out and no diagnostic at all. An abend is the other kind: the machine stops in the middle, having already done some of the work.
A packed field holds two digits per byte with a sign in the last half-byte. “In the packed format, two decimal digits normally are placed adjacent in a byte, except for the rightmost byte of the field.” The digits are 0 to 9. The sign is one of six other codes. Pick a field and watch the hardware read it half-byte at a time.
Written by a program that declared the field packed, which on an RPG Input sheet is a P in the packed column and is what every sheet on this page assumes.
| half-byte | holds | has to be | reads as |
|---|---|---|---|
| 1 | X'0' | a digit: 0 to 9 | 0 |
| 2 | X'1' | a digit: 0 to 9 | 1 |
| 3 | X'0' | a digit: 0 to 9 | 0 |
| 4 | X'4' | a digit: 0 to 9 | 4 |
| 5 | X'2' | a digit: 0 to 9 | 2 |
| 6 | X'5' | a digit: 0 to 9 | 5 |
| 7 | X'0' | a digit: 0 to 9 | 0 |
| 8 | X'C' | a sign: A, C, E, F for plus, B or D for minus | plus |
Every half-byte is what it has to be, so the field is 1042.50 and the program carries on.
Why the final total appears at all
Nothing in an RPG program tells it to print the grand total. Look for the instruction and it is not there. What happens is that item 4 notices end of file and branches to item 13; item 13 sets the Last Record indicator and every control-level indicator on, and then branches back to item 6, which is total time. Your total calculations and your total output run one more time, on a cycle that re-entered itself from its own end, and that is the final total.
Step the deck above to the end and watch it happen. Item 4, then 13, then 6. Miss that path and RPG looks like magic; see it once and the language stops being mysterious.
Three items out of fifteen
The manual's own words bound the cycle: A program cycle begins with item 1 and continues through item 11.
And it names the parts you write into: Steps 6 and 7 are referred to as total time. Steps 1 and 11 are referred to as detail time.
Item 1 is the compiler's heading, so of the four named steps, three carry your code: total calculations, total output, and detail calculations. The other twelve read the file, identify the record, notice the control break, set the indicators, test for overflow, and decide when your three run. That is not a library you called. It is a loop wrapped around you, and on a machine you saw once a day it was the difference between a report and a wasted week.
Which is what the name is about
Abnormal end. The job stopped and the reason came back on paper. A modern editor tells you about a mistake while you are still making it; this told you tomorrow, and only about the first kind of mistake it found. The cycle above exists because the fewer decisions you had to encode by hand, the fewer of those days you spent.
What is real here, and what is not
What the dates on this page are dating
1964 to the 1990s is not the life of the language. RPG is older than both documents here, having started on IBM machines before the System/360, and this page does not date it. 1964 is the Principles of Operation, where the packed decimal format, the digit and sign codes and the data exception itself come from: the architecture this fault is a fault of. The cycle drawn above is from the 1968 RPG manual. The 1990s end is the cycle outliving both, through the System/3, the /34, the /38 and the AS/400 of 1988, still running code written against the 1968 description.
The abend here is a data exception, which is one kind out of many
A job could end abnormally for a dozen reasons: no space on the volume, a file not allocated, a divide by zero, an operator cancelling it. This page shows the one that turns on the bytes themselves, because that is the one where the data looks fine and the arithmetic does not. The codes are from the System/360 Principles of Operation, and the sign table is checked against the System/370 manual as well, twelve years later, because a table typed from memory needs a witness that is not this page.
The instruction is not named, and the completion code is not printed
On System/360 and its descendants a data exception on a decimal instruction came back as a system completion code of 0C7, and everyone who worked on that hardware knows the number. It is not on this page. What the operator saw depended on the operating system, the release and the language: a 0C7 under OS/360 and MVS, a different message entirely under the System/38 and AS/400 that came later, and RPG's own halt indicators before either. The mechanism below the message is the same everywhere, so the mechanism is what this shows.
Which half-byte the hardware notices first is not stated here
The manual says operands are fetched right to left, which would make the sign the first thing examined, but it does not promise an order in which faults are reported and a real machine may check a whole field at once. So the table marks every half-byte that is wrong rather than claiming to know which one stopped the program.
The fifteen items are transcribed, and the test checks every one
They are not a paraphrase. Each item's description is taken from the November 1968 RPG language manual, form C24-3337-3, which has a real text layer, so no OCR is involved. The test suite requires a distinctive clause from every one of the fifteen to appear in the archived copy, so a step reworded to read better would turn it red. Figure 31 in the manual is the flowchart these numbers refer to; this page does not reproduce the figure, only the numbered text beside it.
Two control levels, where RPG had nine
RPG supports control levels L1 through L9, nested, so a report can break on branch inside region inside division. This page drives two, L1 and L2, because one level never shows why they are numbered: it takes a second to see a group total print inside a division total, and to see that breaking at L2 turns L1 on with it. The engine carries all nine indicators and sets them all on at end of file, which is what the manual says happens; levels three to nine are simply never reached by this deck.
The calculations are fixed; the sheet is a sheet, not a compiler
The calculations the cycle runs at items 6, 7 and 11 are a fixed toy: accumulate a value, print a group total on a control break, print a final total at the end. The specification sheet lower down is a real sheet with the manual's real column numbers, and it is checked the way the compiler checked one, but it does not compile: editing it does not change what the cycle above computes. It changes how many days the deck took to come back, which is the other half of the subject.
The day count is a model, not a log
Real turnaround was not reliably a day. It was a day at a well-run shop with an overnight batch window, and it was two hours if you had the machine to yourself, and it was three days if the operator dropped your deck or the tape you needed was mounted on another job. The model here says one submission a day and that faults of one severity class come back together. The second half is a fact about how a compiler pass works; the first is a round number standing in for a range.
A return code of 4 is the interesting one
The compiler graded diagnostics and returned the worst severity it found, and what its table grades is the outlook rather than the output: 4 is minor errors with successful execution probable, 8 is errors with unsuccessful execution possible, 12 is serious errors with it probable, 16 is critical errors and normal execution impossible. Whether a later step in the job ran on a given code was the job’s own COND parameter, not the compiler’s decision. This page used to say 8 and above meant a listing and no program, which is neither what the table says nor how a job worked. At 4 you got a program, because the compiler had assumed something on your behalf and carried on, and its diagnostics say so in as many words. That is the failure this page would put first if it could only keep one: not the day you lost to an error, but the day you did not lose, because you got output back and it was the wrong output.
The diagnostics are graded from the manual; their wording is ours
Which faults are errors and which are warnings comes from the compiler's own return-code scale, and the column ranges every check works from are quoted on the sheet itself, out of the manual's prose. The sentences the page prints are not. The manual's diagnostic message text is in its Appendix G, and the scan's text layer is too damaged there to quote, so each message here is described in this page's own words. Nine checks, where a real compiler had hundreds: this one can see a missing operation, an operation code it does not know, a missing factor or result, a length or decimal position that is not a number, more decimals than the field has positions, a control level that is not one, a result field defined twice or not at all, and a name nothing defines. It cannot see anything about the other specification sheets, because they are not here.
What is not modelled
JCL, which was its own language and its own class of overnight failure. Matching and secondary files. Table lookup. Exception output. Halt indicators are here only as a switch to show the branch to item 12. And nothing about the machine underneath: no storage estimates, no core, no operator. The subject is one loop.
How this machine was built, and why a cycle defined in 1968 outlived the manual: the engineering notebook.
Sources
- IBM, IBM System/360 Operating System: Report Program Generator Language, form C24-3337-3, fourth edition, November 1968, via bitsavers. The primary document: the fifteen items of the cycle, the numbering, total time and detail time, and the compiler return codes are all from here, and the copy has a text layer so the transcription is not an OCR guess.
- IBM, IBM System/360 Principles of Operation, A22-6821-0, 1964. The packed decimal format, the digit and sign codes, and what a data exception is.
- IBM, IBM System/370 Principles of Operation, GA22-7000-4, 1975. The second witness for the sign table, which is memorised here and so needs one.
- Logical Art, the studio this belongs to.