Percolating GO TOs Upwards

Whenever you GO TO a paragraph which has only a single (unconditional) GO TO at the end, you can eliminate a GO TO. For example:
     GO TO 1130-LOAD-USOC-TABLE.
     ...
 1130-LOAD-USOC-TABLE.
*
* do some stuff here -- no GO TOs until the end:
*
     GO TO 1140-LOAD-CLS-SVC-TABLE.
Replace the first GO TO with a PERFORM, and move the second GO TO into the invoking code, following the PERFORM. Repeat this transformation for each such GO TO. The result looks like this:
     PERFORM 1130-LOAD-USOC-TABLE.     
     GO TO 1140-LOAD-CLS-SVC-TABLE.
     ...
 1130-LOAD-USOC-TABLE.
*
* do some stuff here -- no GO TOs
*
You have eliminated one GO TO, and removed a paragraph from the GO TO regime. In addition, you may have created an opportunity to collect common GO TOs.

For example, suppose your first GO TO appeared in the following context:

     IF USOCS-NOT-LOADED
        GO TO 1130-LOAD-USOC-TABLE
     ELSE
        GO TO 1140-LOAD-CLS-SVC-TABLE.
After percolating the GO TO, both branches will GO TO the same destination, and you can combine them into a simpler fragment:
     IF USOCS-NOT-LOADED
        PERFORM 1130-LOAD-USOC-TABLE.
*
     GO TO 1140-LOAD-CLS-SVC-TABLE.
At this point you may be able to repeat the transformation, letting this last GO TO percolate up to the next level. And so forth.

The Grand Plan

By now you can see where we're headed. The GO TOs rise to the top and collect like an oil slick, which you can skim off.

Suppose a paragraph always exits via a GO TO, but there are multiple destinations. If a PERFORM THRU is active, each path of execution will presumably reach the target of the THRU clause sooner or later. Let the GO TOs percolate up from the lower paragraphs. Eventually they will all meet each other where the GO TOs first diverged. Then you can collect them into a common GO TO, which can then percolate up another level.

If a PERFORM THRU is not active, then each path of execution will presumably reach a GOBACK, STOP RUN, or similar construct. Even if they don't reach the same GOBACK statement, you can create a separate paragraph with a single GOBACK statement, and replace each of the other GOBACKs with a GO TO -- which can then percolate as before.

Alternatively, you can let the GOBACKs percolate just like GO TOs, with much the same result.

Greaseballs in the Oil Slick

This tidy strategy offers a systematic approach for eliminating GO TOs. However, there are cases where it doesn't work.

Loops

If the program uses GO TO to implement a loop, you can't percolate a GO TO through it. You must reconstruct the loop into a PERFORM UNTIL.

Abend Paragraphs

Suppose a paragraph has two GO TOs. One of them eventually reaches a GOBACK or an EXIT paragraph, but the other always invokes an abend to report a fatal error.

These two destinations are fundamentally different. You can never merge them by collecting common GO TOs.

However, this situation is less of a problem than it may seem. Just give the abending paragraph a good clear name. If you make it clear from the name alone that the abending paragraph abends, then you can pretty much ignore the flow of control from the point where you invoke it. You can either GO TO it or PERFORM it -- the result is the same. Eventually you should probably PERFORM it, lest there be any GO TOs left, but there is no hurry.

Ambiguous Flow of Control

Suppose a program invokes a given paragraph sometimes with a GO TO and sometimes with a simple PERFORM (with no THRU clause). Suppose further that the paragraph contains a GO TO. What happens if execution follows the GO TO while a PERFORM is active?

Suppose that paragraph A, under some circumstances, can can GO TO paragraph B, which, under some circumstances, PERFORMs paragraph A. If execution ever follows that route, what happens when it reaches the end of paragraph A the second time?

There's no simple way to fix craziness like this. Before you can apply the usual techniques you must resolve the ambiguity.

For example, consider the first example again. It may turn out, due to some slippery logic, that under the conditions where the paragraph is PERFORMed, it never actually executes the GO TO, so that the ambiguity never arises.

In that case, make a copy of the paragraph. Use one copy as the target of GO TO, and the other as the object of PERFORM. In the PERFORMed version, remove the code which can no longer be executed.

There is no guarantee that any such fix is possible. The program may be just as crazy as it looks. Maybe the craziness shows up only under exotic and improbable circumstances which, so far as you know, have never happened yet.

If so, you'll just have to figure out what the program should have done. At this point a little telepathy can be helpful.


[style forum]COBOL Style Forum [spaghetti]Spaghetti code [stage]Next stage
[home]COBOL Home