This approach requires more care than usual. In a top-level program, you can abort pretty much whenever you want. When one paragraph PERFORMs another, it won't even regain control if the second paragraph aborts. In a subprogram, however, the first paragraph may need to check whether the second one encountered a fatal error. The error may have to percolate through several layers of code before it reaches the calling program.
If a subprogram reports a fatal error to the calling program, the calling program should abort. But maybe it won't. Maybe it will call the subprogram again.
The subprogram must protect itself from such improper calls. When it detects a fatal error it should set a switch so that it can remember that a fatal error has occurred. In any subsequent call, the subprogram should check the switch, notice the previous error, and return immediately without doing anything.
There are exceptions. If there is a routine for returning an error message, an error obviously should not disable it. It may also make sense to honor a request to shut down the module (close files, release memory, and so forth).
However, this approach limits the subprogram to a specific way of issuing messages. Techniques designed for batch programs may not work for IMS transactions or CICS programs. Different applications follow different conventions.
In order to be reusable in other contexts, a subprogram should not issue error messages on its own. It should pass information about the error back up to the calling program, and let it be responsible for issuing the message.
This approach calls for some extra machinery to pass the information upward. It can be awkward when the information must pass up through several layers of software. If a module is inherently restricted to a particular application and a particular environment, it might as well avoid these problems by issuing its own messages.
For issuing error messages this technique is not enough, because it requires the calling program to have detailed knowledge of the meaning of each error code. In addition, a meaningful message may need to incorporate information which is not available to the calling program.
Many JOCKEY subprograms provide a separate entry point to return fifty characters of text describing the most recent error. In most cases the calling program can use this text to build an error message without knowing anything further about specific status codes.
For example: the JK015 routines manage a collection of named variables. One entry point, JKGETENV, fetches the value of a variable whose name is specified by the calling program. It obtains the value of such variables by loading a small file into a WORKING-STORAGE table.
There may be a table overflow in loading the variables. In one possible design, JKGETENV would return a status code meaning "table overflow" or "variable not found."
Instead, JKGETENV merely reports that the variable has a value of blank spaces. There is no status code to test. As a result, JKGETENV is simpler to use than it would be if the calling program had to check a status code after every call. If a program needs to be paranoid about possible errors, it can use certain other entry points to detect them.