GOBACK, STOP RUN and RETURN-CODE
Three ways to finish
GOBACKreturns to whoever called this program. In a subprogram it resumes the caller after theCALL; in a main program it returns to the operating system, ending the job step.STOP RUNends the whole run unit: the main program and every subprogram it called. Control never goes back to the caller.EXIT PROGRAMreturns from a called program likeGOBACK, but in a main program it does nothing at all and execution carries on with the next statement.
IDENTIFICATION DIVISION.
PROGRAM-ID. ENDINGS.
PROCEDURE DIVISION.
DISPLAY "BEFORE"
CALL "QUITTER"
DISPLAY "AFTER QUITTER"
CALL "EXITER"
DISPLAY "AFTER EXITER"
CALL "STOPPER"
DISPLAY "AFTER STOPPER"
GOBACK.
IDENTIFICATION DIVISION.
PROGRAM-ID. QUITTER.
PROCEDURE DIVISION.
DISPLAY "IN QUITTER"
GOBACK.
END PROGRAM QUITTER.
IDENTIFICATION DIVISION.
PROGRAM-ID. EXITER.
PROCEDURE DIVISION.
DISPLAY "IN EXITER"
EXIT PROGRAM.
END PROGRAM EXITER.
IDENTIFICATION DIVISION.
PROGRAM-ID. STOPPER.
PROCEDURE DIVISION.
DISPLAY "IN STOPPER"
MOVE 8 TO RETURN-CODE
STOP RUN.
END PROGRAM STOPPER.
END PROGRAM ENDINGS.
BEFORE
IN QUITTER
AFTER QUITTER
IN EXITER
AFTER EXITER
IN STOPPER
AFTER STOPPER never appears, and the job step ends with return code 8.
The practical rule: end every program with GOBACK. It does the right
thing whether the program runs as a main program or is called, so the same
code can be reused either way. A STOP RUN buried in a shared routine is a
bug waiting for the day someone calls it from a batch driver.
RETURN-CODE
RETURN-CODE is a special register, a numeric field you don't declare.
Subprograms use it to report an outcome, and the conventional values are
the same as JCL condition codes:
| RC | Meaning |
|---|---|
| 0 | All good |
| 4 | Warning: processed, but look at it |
| 8 | Error: this item was rejected |
| 12, 16 | Severe: something is badly wrong |
The subprogram does MOVE 8 TO RETURN-CODE before GOBACK; the caller
reads RETURN-CODE after the CALL. There is only one RETURN-CODE, so
save it in your own field straight away:
CALL "CHKACCT" USING WS-ACCT-REC
MOVE RETURN-CODE TO WS-RC
When the main program finishes, whatever is in RETURN-CODE becomes the
job step's condition code, the RC you see in the job log and that later
steps test with COND. That is how a batch program tells operations "I ran,
but with warnings".
Two traps follow from there being only one register:
- A subprogram that doesn't set
RETURN-CODEpasses back whatever was already there. In GnuCOBOL, if the previous call left 8, a routine that never touchesRETURN-CODEalso appears to return 8. Set it on every path, includingMOVE 0 TO RETURN-CODEfor success. - A main program that calls such routines can accidentally end with the
last call's code. Set the step's final RC deliberately before
GOBACKorSTOP RUN.
On the job
Many shops pass a status field in the parameter list instead of, or as
well as, RETURN-CODE: a two-character code plus a message, defined
in the routine's interface copybook. Whatever the convention, check
it after every CALL. Ignoring a routine's error return is one of the
most common findings in code review.
Your task
ACCTVAL (the starter; don't change it) checks account records before the
nightly update. For each record it calls CHKACCT, reads
RETURN-CODE, prints OK, WARNING or ERROR, and finally sets the job
step's return code to the worst result it saw.
Write CHKACCT as a nested program. It receives the whole record:
01 LS-ACCT-REC.
05 LS-ACCT-NO PIC X(8).
05 LS-STATUS PIC X.
05 LS-BALANCE PIC 9(7)V99.
and sets RETURN-CODE by the first rule that matches:
| Rule | RC |
|---|---|
| account number is not all digits | 8 |
status is neither A (active) nor C (closed) |
8 |
status C and balance above zero |
4 |
| balance above 50000.00 | 4 |
| anything else | 0 |
For the input
05
10000001A000125000
1000X002A000010000
10000003C000000000
10000004C000000150
10000005A006000000
the output is below, and the program must end with return code 8:
10000001 OK
1000X002 ERROR
10000003 OK
10000004 WARNING
10000005 WARNING
OK 002 WARNING 002 ERROR 001