ALTER

Almost no one has a good word to say about the COBOL ALTER verb (and with good reason). ALTER has long been obsolete; few people know how it works, and still fewer use it. Nevertheless, you may encounter ALTER in an old program.

ALTER changes the destination of a GO TO statement elsewhere in the program. It complicates the task of eliminating GO TO, especially if you don't notice that the ALTER is present.

If you find an ALTER, replace it with a flag, a case structure, and some ordinary GO TOs. Once the ALTER is gone, you can eliminate the GO TOs by the usual methods.

How ALTER works

Consider the following code:
     PERFORM 2100-PROCESS-RECORD THRU 2199-EXIT.
...
 2100-PROCESS-RECORD. 
     GO TO 2110-PROCESS-HEADER.
*
 2110-PROCESS-HEADER.
* code to process a file header
     ALTER 2100-PROCESS-RECORD TO 2120-PROCESS-DETAIL.
     GO TO 2199-EXIT.
*
 2120-PROCESS-DETAIL.
* code to process a detail record 
     GO TO 2199-EXIT.
...
*
 2199-EXIT.
     EXIT.
The first time we execute the PERFORM, control passes through 2110-PROCESS-HEADER. However, the ALTER at the end of that paragraph changes the destination of the GO TO in 2100-PROCESS-RECORD. As a result, on all subsequent executions of the PERFORM, control does not pass through 2110-PROCESS-HEADER. It passes through 2120-PROCESS-DETAIL instead.

The potential for confusion is obvious. The altered GO TO does not go where it claims to go -- instead, it goes to a place specified in some remote piece of code. To understand how the code works you need to know that the ALTER is present, and you need to know all the circumstances which execute the ALTER.

A variation

There is a slightly less malevolent variation. The example might be rewritten as follows:
     PERFORM 2100-PROCESS-RECORD THRU 2199-EXIT.
...
 2100-PROCESS-RECORD. 
     GO TO.
*
 2110-PROCESS-HEADER.
* code to process a file header
     ALTER 2100-PROCESS-RECORD TO 2120-PROCESS-DETAIL.
     GO TO 2199-EXIT.
*
 2120-PROCESS-DETAIL.
* code to process a detail record 
     GO TO 2199-EXIT.
...
*
 2199-EXIT.
     EXIT.
The only difference is in 2100-PROCESS-HEADER. The GO TO has no destination. The sheer weirdness of this syntax should be enough to alert you that there is an ALTER involved.

If a GO TO statement has no destination, then it behaves like a CONTINUE statement until an ALTER statement assigns it a destination. In the example: on the first time around, control falls through into 2110-PROCESS-HEADER. On subsequent passes the GO TO will have been assigned a destination of 2120-PROCESS-DETAIL, exactly as in the first example.

It gets worse

In the presence of segmentation, ALTER can behave in unexpected ways. If an independent segment contains an altered GO TO, and the segment is overlaid and then reloaded, the GO TO is reset to its original destination.

If you ever encounter this form of pathology, proceed with extreme caution. You have found either a bizarre and subtle bug or a vicious marauding style of programming. Quite possibly both.

If you determine that this resetting is appropriate rather than accidental, look for a way to preserve the logic while making the resetting visible. Find each spot which causes the reload of the independent segment containing the altered GO TO, and insert an ALTER statement as needed.

This transformation may be tricky if the resetting occurs through code which sometimes causes a reload and sometimes doesn't. As a last resort, you can keep track of which independent segment is currently loaded, if any. Let every paragraph in every independent segment set a flag to indicate which segment is loaded. Then you can check the flag as needed to determine whether to reset a GO TO.

(Any logic this strange is probably just somebody's blunder. Hence it's unlikely that you'll ever need to go to such lengths, but you can do it if you have to.)

Once the new ALTERS have made the resetting explicit, you can eliminate them as described below.

Eliminating ALTER

Apart with the segmentation problems described above, you can mechanically eliminate ALTER statements through a step-by-step procedure.
  1. Identify all the ALTER statements which alter the same GO TO.
  2. For each altered GO TO, create a flag in WORKING-STORAGE, with a blatantly artificial name like ALTER-DEST-A.
  3. For each destination assigned to a GO TO, create an 88-level for the flag. If necessary, include another 88-level to represent the initial destination. Give the 88-levels blatantly artificial names. If the destination is 2120-PROCESS-DETAIL, name the 88-level something like AD-2120-A.
  4. Use a VALUE clause to initialize the flag to the value corresponding to the initial destination of the GO TO.
  5. Replace each ALTER statement with a SET statement assigning a value to the flag, corresponding to the destination assigned by the ALTER. For example: SET AD-2120-A TO TRUE.
  6. Replace the altered GO TO with a case structure testing the flag, using either EVALUATE TRUE or a series of IF ELSE clauses. Each branch of the case structure should GO TO the corresponding destination. For example:
    ...
         WHEN AD-2120-A
            GO TO 2120-PROCESS-DETAIL
    ...
    
The resulting code will still be ugly, but it won't stay that way. Eventually you will eliminate the GO TOs, and probably the flag that controls them. Meanwhile, ugly names like AD-2120-A will remind you that the rewrite is not finished.
[style forum]COBOL Style Forum [spaghetti]Spaghetti code [stage]Next stage
[home]COBOL Home