COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x ·
✓ verified by execution on 2026-08-16
When maintaining legacy COBOL systems, you will inevitably encounter unstructured “spaghetti code.” Before the widespread adoption of structured programming, control flow was entirely manual. Understanding how legacy code directs execution is essential for safe maintenance and refactoring.
The Unconditional GO TO
The GO TO statement transfers control from one part of the Procedure Division to another. It unconditionally skips or repeats sections of your program.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. GotoBasic. PROCEDURE DIVISION. DISPLAY "START". GO TO PARA-END. DISPLAY "SKIPPED". PARA-END. DISPLAY "END". STOP RUN.
Output
START
END
Your output
Unlike modern function calls, a GO TO is a one-way trip. Control only returns if another GO TO sends it back. A PERFORM statement, by contrast, transfers control explicitly to one or more procedures and implicitly returns control to the next executable statement.
Predict the outputcobol
Read the code. What exactly will it print? Commit to an answer before you look.
IDENTIFICATION DIVISION. PROGRAM-ID. Oneway. DATA DIVISION. WORKING-STORAGE SECTION. 01 VAL PIC 9 VALUE 1. PROCEDURE DIVISION. ADD 1 TO VAL. GO TO DO-IT. ADD 2 TO VAL. DISPLAY VAL. STOP RUN. DO-IT. ADD 3 TO VAL. DISPLAY VAL.
Output
5
You predicted
Dynamic Branching: GO TO DEPENDING ON
Sometimes, legacy code needs to branch dynamically based on a value. The GO TO DEPENDING ON statement transfers control to one of a series of procedures, depending on the value of a data item.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. GotoDep. DATA DIVISION. WORKING-STORAGE SECTION. 01 CHOICE PIC 9 VALUE 2. PROCEDURE DIVISION. GO TO OPT-1 OPT-2 OPT-3 DEPENDING ON CHOICE. OPT-1. DISPLAY "ONE". STOP RUN. OPT-2. DISPLAY "TWO". STOP RUN. OPT-3. DISPLAY "THREE". STOP RUN.
Output
TWO
Your output
If CHOICE was 1, it would jump to OPT-1. If it was 3, to OPT-3. If it were 4, it would simply fall through and execute OPT-1 anyway. Today, this logic is entirely handled by EVALUATE.
The ALTER Statement: A Maintainer’s Nightmare
If GO TO creates spaghetti code, ALTER turns it into an invisible maze. The ALTER statement changes the transfer point specified in a GO TO statement at runtime. It physically alters the memory address of the target jump instruction.
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. AlterExample. PROCEDURE DIVISION. DISPLAY "START". ALTER PARA-B TO PROCEED TO PARA-C. GO TO PARA-B. PARA-B. GO TO PARA-D. PARA-C. DISPLAY "JUMPED TO C". STOP RUN. PARA-D. DISPLAY "JUMPED TO D". STOP RUN.
Output
START
JUMPED TO C
Your output
Notice that PARA-B explicitly states GO TO PARA-D. But because of the ALTER statement at the top, the program dynamically overwrites that instruction to point to PARA-C. You cannot rely on static analysis to know what the code will do.
The official IBM documentation states: “The ALTER statement encourages the use of unstructured programming practices; the EVALUATE statement provides the same function… but helps to ensure that a program is well-structured.”
Modern Replacements
Whenever possible, legacy GO TO loops should be refactored into structured PERFORM UNTIL blocks, and ALTER logic should be mapped to EVALUATE.
Legacy Loop:
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. GotoLoop. DATA DIVISION. WORKING-STORAGE SECTION. 01 I PIC 9 VALUE 1. PROCEDURE DIVISION. LOOP-START. IF I > 3 GO TO LOOP-END END-IF. DISPLAY "I = " I. ADD 1 TO I. GO TO LOOP-START. LOOP-END. STOP RUN.
Output
I = 1
I = 2
I = 3
Your output
Refactored with PERFORM:
cobol✓ verified output
IDENTIFICATION DIVISION. PROGRAM-ID. RefactorLoop. DATA DIVISION. WORKING-STORAGE SECTION. 01 I PIC 9 VALUE 1. PROCEDURE DIVISION. PERFORM UNTIL I > 3 DISPLAY "I = " I ADD 1 TO I END-PERFORM. STOP RUN.
Output
I = 1
I = 2
I = 3
Your output
By removing manual GO TO and ALTER references, your code becomes self-documenting and regression-safe.
Check yourself
Why is the ALTER statement considered fundamentally unsafe in COBOL?
Reveal answer
It changes the target of a GO TO at runtime, making static analysis impossible. — ALTER modifies the destination of a GO TO instruction in memory during execution. You cannot know where the GO TO will jump just by reading the code, as it depends on execution history.
How does a PERFORM statement differ from a simple unconditional GO TO?
Reveal answer
PERFORM automatically returns control to the caller, while GO TO is a one-way transfer. — The PERFORM statement explicitly returns control to the next executable statement once finished, making it a structured function call rather than a one-way jump.
What happens when a GO TO DEPENDING ON statement encounters an out-of-bounds integer value?
Reveal answer
Execution falls through to the next sequential statement. — If the value of the target integer is less than 1 or greater than the number of targets provided, the jump does not occur and execution proceeds naturally to the next line.
Challenges
Challenge 1 +50 XP
This program uses an ALTER statement to change behavior. Refactor it to use structured programming (EVALUATE or IF) instead, completely removing the ALTER and GO TO statements. The output must remain exactly the same.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects "PATH B\n"
Show solution (0 XP)
IDENTIFICATION DIVISION.PROGRAM-ID. AlterFix.DATA DIVISION.WORKING-STORAGE SECTION.01 CURRENT-PATH PIC X VALUE 'B'.PROCEDURE DIVISION. IF CURRENT-PATH = 'A' PERFORM PATH-A ELSE PERFORM PATH-B END-IF. STOP RUN.PATH-A. DISPLAY "PATH A".PATH-B. DISPLAY "PATH B".
🐞 Bug Hunt+50 XP
A maintainer accidentally broke this legacy spaghetti code. It should print ONE, then TWO, then stop. Find the bug and fix it.
This code runs. It just does the wrong thing. Read it, find the defect,
fix it — the tests below decide when you are right.
cobol✓ solution verified at build time
COBOL has no in-browser runtime, so this one is pen-and-paper: work out what the
fixed code should be, then open the solution and compare. The expected output
below is real — it came from compiling the solution with GnuCOBOL when this page
was built.
Test 1 — expects "ONE\nTWO\n"
Show solution (0 XP)
IDENTIFICATION DIVISION.PROGRAM-ID. SpaghettiBug.PROCEDURE DIVISION. GO TO STEP-1.STEP-3. STOP RUN.STEP-1. DISPLAY "ONE". GO TO STEP-2.STEP-2. DISPLAY "TWO". GO TO STEP-3.