Procedure branching in COBOL allows programs to alter the normal sequential flow of execution. While COBOL supports traditional branching with statements like GO TO, modern COBOL programming emphasizes structured approaches that make programs easier to understand and maintain.
COBOL's approach to program flow control has evolved significantly over the decades:
Era | Approach | Key Features |
---|---|---|
Early COBOL (1960s-70s) | Heavy GO TO usage | Spaghetti code, difficult to follow |
Structured era (1970s-80s) | PERFORM, nested IFs | Modular design, reduced GO TO usage |
COBOL-85 | Scope terminators | END-IF, END-PERFORM, clearer nesting |
Modern COBOL | Structured exceptions | ON EXCEPTION, EXIT PERFORM, structured error handling |
The GO TO statement transfers program control unconditionally to the specified procedure name. While it has legitimate uses, overuse of GO TO can lead to confusing program logic that is difficult to maintain.
Format 1: Simple GO TO
1GO TO procedure-name
Format 2: GO TO with DEPENDING ON (computed GO TO)
12GO TO procedure-name-1 [procedure-name-2] ... DEPENDING ON identifier
1234567891011121314151617181920212223242526272829303132* Example 1: Simple GO TO IF AMOUNT > 1000 GO TO LARGE-AMOUNT-PARAGRAPH ELSE GO TO SMALL-AMOUNT-PARAGRAPH. * Example 2: GO TO with DEPENDING ON MOVE 2 TO CHOICE-INDEX. GO TO OPTION-A OPTION-B OPTION-C OPTION-D DEPENDING ON CHOICE-INDEX. * This will transfer control to OPTION-B (the 2nd procedure) * Example 3: Error handling with GO TO READ CUSTOMER-FILE AT END GO TO EOF-ROUTINE. PROCESS-RECORD. IF RECORD-ERROR GO TO ERROR-ROUTINE. * Example 4: Forward reference (to avoid falling through) PROCESS-VALID-RECORD. PERFORM VALIDATION-ROUTINE. IF VALID-RECORD PERFORM UPDATE-RECORD ELSE PERFORM REJECT-RECORD. GO TO READ-NEXT-RECORD. READ-NEXT-RECORD. READ CUSTOMER-FILE AT END GO TO EOF-ROUTINE. GO TO PROCESS-VALID-RECORD.
In modern COBOL, most GO TO usage can be replaced with structured alternatives like PERFORM, EXIT PERFORM, and EVALUATE statements.
The EXIT statement provides a common end point for a procedure and serves as a placeholder when needed. Its enhanced forms provide structured exits from specific program constructs.
Format 1: Simple EXIT
1EXIT.
Format 2: EXIT PROGRAM
1EXIT PROGRAM.
Format 3: EXIT PERFORM [CYCLE]
1EXIT PERFORM [CYCLE].
Other variants include EXIT PARAGRAPH, EXIT SECTION, and program construct exits like EXIT FUNCTION.
123456789101112131415161718192021222324252627282930313233343536373839404142* Example 1: Simple EXIT as a procedure placeholder EMPTY-PARAGRAPH. EXIT. * Example 2: EXIT as a common termination point PROCESS-CUSTOMER. IF NOT VALID-CUSTOMER DISPLAY "Invalid customer record" GO TO PROCESS-CUSTOMER-EXIT. PERFORM UPDATE-CUSTOMER-RECORD. PERFORM PRINT-CONFIRMATION. PROCESS-CUSTOMER-EXIT. EXIT. * Example 3: EXIT PERFORM to terminate a loop early PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > TABLE-SIZE IF TABLE-ENTRY(IDX) = SEARCH-VALUE MOVE IDX TO FOUND-INDEX EXIT PERFORM END-IF END-PERFORM. * Example 4: EXIT PERFORM CYCLE to skip the current iteration PERFORM VARYING IDX FROM 1 BY 1 UNTIL IDX > RECORD-COUNT IF RECORD-STATUS(IDX) = "DELETED" EXIT PERFORM CYCLE END-IF PERFORM PROCESS-ACTIVE-RECORD END-PERFORM. * Example 5: EXIT PROGRAM in a subprogram PROCESS-REQUEST. IF INVALID-REQUEST MOVE "E001" TO RETURN-CODE EXIT PROGRAM END-IF. PERFORM PROCESS-VALID-REQUEST. MOVE "0000" TO RETURN-CODE. EXIT PROGRAM.
The GOBACK statement returns control to the calling program or to the operating system if executed in a main program. It's a versatile statement that works appropriately in both main programs and subprograms.
1GOBACK.
GOBACK is a simple statement with no variations in syntax.
12345678910111213141516171819202122232425262728293031323334* Example 1: GOBACK at normal program termination PROCEDURE DIVISION. PERFORM INITIALIZATION. PERFORM MAIN-PROCESS UNTIL END-OF-FILE. PERFORM CLEANUP. GOBACK. * Example 2: GOBACK for early program termination PROCEDURE DIVISION. PERFORM INITIALIZATION. IF SETUP-ERROR DISPLAY "Critical initialization error" MOVE 8 TO RETURN-CODE GOBACK END-IF. PERFORM MAIN-PROCESS. PERFORM CLEANUP. GOBACK. * Example 3: GOBACK in a subprogram PROCEDURE DIVISION USING INPUT-DATA OUTPUT-DATA. MOVE SPACES TO ERROR-MESSAGE. PERFORM VALIDATE-INPUT. IF INPUT-ERROR MOVE "Invalid input data" TO ERROR-MESSAGE MOVE 4 TO RETURN-CODE GOBACK END-IF. PERFORM PROCESS-DATA. MOVE 0 TO RETURN-CODE. GOBACK.
Context | GOBACK Behavior |
---|---|
Main program | Terminates execution and returns to operating system (like STOP RUN) |
Subprogram called with CALL | Returns control to calling program (like EXIT PROGRAM) |
Nested program | Returns control to calling program |
User-defined function | Returns to calling function with the current function value |
Feature | GOBACK | STOP RUN | EXIT PROGRAM |
---|---|---|---|
Works in main program | Yes | Yes | No effect |
Works in subprogram | Yes | Terminates entire run | Yes |
Context sensitive | Yes | No | No |
Recommended for new code | Yes | Rarely | In specific cases |
The STOP RUN statement terminates the entire COBOL run unit, closing all files and releasing all resources. It's the most definitive way to end program execution.
1STOP RUN.
There is also a legacy format:
1STOP {literal|identifier}.
The literal/identifier format displays a message but is generally considered obsolete.
123456789101112131415161718192021222324252627282930* Example 1: Simple program termination PROCEDURE DIVISION. PERFORM MAIN-PROCESS. CLOSE ALL FILES. STOP RUN. * Example 2: Emergency termination PROCESS-TRANSACTION. IF CRITICAL-ERROR DISPLAY "Fatal error encountered: " ERROR-MESSAGE MOVE 16 TO RETURN-CODE CLOSE ALL FILES STOP RUN END-IF. PERFORM PROCESS-VALID-TRANSACTION. * Example 3: Conditional termination PROCESS-USER-COMMAND. IF COMMAND-CODE = "EXIT" OR "QUIT" PERFORM CLEANUP-ROUTINE DISPLAY "Program terminated by user request" STOP RUN END-IF. PERFORM PROCESS-COMMAND. GO TO PROCESS-USER-COMMAND. * Example 4: Obsolete format (not recommended) STOP "End of processing".
In a main program, both STOP RUN and GOBACK have similar effects, but there are subtle differences:
Feature | STOP RUN | GOBACK |
---|---|---|
Intention clarity | Explicit termination | Context-dependent |
Code reusability | Less flexible if code is moved to a subprogram | Works in both contexts |
Historical usage | Traditional in older code | More common in modern code |
Modern COBOL programming emphasizes structured techniques that minimize or eliminate the need for GO TO statements. These alternatives lead to code that is easier to understand, maintain, and debug.
Legacy Pattern | Modern Alternative | Advantage |
---|---|---|
GO TO for loops | PERFORM UNTIL | Clear loop boundaries and termination condition |
Computed GO TO | EVALUATE | Table-like structure with clear case mapping |
Early loop exit | EXIT PERFORM | Maintains loop structure while allowing early exit |
Error jumps | On-condition phrases | Local error handling where the error occurs |
Sequential paragraph fall-through | PERFORM...THRU | Explicit execution of a range of paragraphs |
Legacy approach with GO TO:
123456789READ-RECORDS. READ INPUT-FILE AT END GO TO END-PROCESS. PERFORM PROCESS-RECORD. GO TO READ-RECORDS. END-PROCESS. CLOSE INPUT-FILE.
Modern approach with PERFORM UNTIL:
12345678910PROCESS-ALL-RECORDS. PERFORM UNTIL END-OF-FILE READ INPUT-FILE AT END SET END-OF-FILE TO TRUE NOT AT END PERFORM PROCESS-RECORD END-READ END-PERFORM. CLOSE INPUT-FILE.
Legacy approach with GO TO DEPENDING ON:
12345678910111213141516171819202122232425MOVE TRANSACTION-TYPE TO TYPE-INDEX. GO TO PROCESS-SALE PROCESS-RETURN PROCESS-ADJUSTMENT PROCESS-INQUIRY DEPENDING ON TYPE-INDEX. PROCESS-SALE. PERFORM SALE-ROUTINE. GO TO TRANSACTION-EXIT. PROCESS-RETURN. PERFORM RETURN-ROUTINE. GO TO TRANSACTION-EXIT. PROCESS-ADJUSTMENT. PERFORM ADJUSTMENT-ROUTINE. GO TO TRANSACTION-EXIT. PROCESS-INQUIRY. PERFORM INQUIRY-ROUTINE. GO TO TRANSACTION-EXIT. TRANSACTION-EXIT. EXIT.
Modern approach with EVALUATE:
123456789101112EVALUATE TRANSACTION-TYPE WHEN 1 PERFORM SALE-ROUTINE WHEN 2 PERFORM RETURN-ROUTINE WHEN 3 PERFORM ADJUSTMENT-ROUTINE WHEN 4 PERFORM INQUIRY-ROUTINE WHEN OTHER PERFORM UNKNOWN-TRANSACTION END-EVALUATE.
Legacy approach with GO TO for errors:
12345678910111213141516171819202122PROCESS-RECORD. IF RECORD-TYPE NOT = "CUSTOMER" GO TO INVALID-RECORD-TYPE. IF CUSTOMER-ID = SPACES GO TO MISSING-CUSTOMER-ID. PERFORM UPDATE-CUSTOMER-RECORD. GO TO PROCESS-RECORD-EXIT. INVALID-RECORD-TYPE. DISPLAY "Invalid record type". MOVE "E001" TO ERROR-CODE. GO TO PROCESS-RECORD-EXIT. MISSING-CUSTOMER-ID. DISPLAY "Missing customer ID". MOVE "E002" TO ERROR-CODE. GO TO PROCESS-RECORD-EXIT. PROCESS-RECORD-EXIT. EXIT.
Modern structured approach:
1234567891011PROCESS-RECORD. EVALUATE TRUE WHEN RECORD-TYPE NOT = "CUSTOMER" DISPLAY "Invalid record type" MOVE "E001" TO ERROR-CODE WHEN CUSTOMER-ID = SPACES DISPLAY "Missing customer ID" MOVE "E002" TO ERROR-CODE WHEN OTHER PERFORM UPDATE-CUSTOMER-RECORD END-EVALUATE.
Legacy approach with GO TO:
1234567891011121314151617SEARCH-TABLE. MOVE 1 TO TABLE-INDEX. MOVE "N" TO FOUND-FLAG. SEARCH-LOOP. IF TABLE-INDEX > TABLE-SIZE GO TO SEARCH-EXIT. IF TABLE-ENTRY(TABLE-INDEX) = SEARCH-VALUE MOVE "Y" TO FOUND-FLAG GO TO SEARCH-EXIT. ADD 1 TO TABLE-INDEX. GO TO SEARCH-LOOP. SEARCH-EXIT. EXIT.
Modern approach with EXIT PERFORM:
12345678910SEARCH-TABLE. MOVE "N" TO FOUND-FLAG. PERFORM VARYING TABLE-INDEX FROM 1 BY 1 UNTIL TABLE-INDEX > TABLE-SIZE IF TABLE-ENTRY(TABLE-INDEX) = SEARCH-VALUE MOVE "Y" TO FOUND-FLAG EXIT PERFORM END-IF END-PERFORM.
Refactor the following legacy code to eliminate GO TO statements using structured programming techniques.
1234567891011121314151617181920212223242526272829303132333435363738394041* Legacy code with GO TO loops: PROCESS-TRANSACTIONS. READ TRANSACTION-FILE AT END GO TO END-TRANSACTIONS. IF TRANSACTION-CODE = "ADD" GO TO PROCESS-ADD. IF TRANSACTION-CODE = "UPDATE" GO TO PROCESS-UPDATE. IF TRANSACTION-CODE = "DELETE" GO TO PROCESS-DELETE. GO TO PROCESS-UNKNOWN. PROCESS-ADD. PERFORM ADD-ROUTINE. GO TO READ-NEXT. PROCESS-UPDATE. PERFORM UPDATE-ROUTINE. GO TO READ-NEXT. PROCESS-DELETE. PERFORM DELETE-ROUTINE. GO TO READ-NEXT. PROCESS-UNKNOWN. DISPLAY "Unknown transaction code: " TRANSACTION-CODE. GO TO READ-NEXT. READ-NEXT. GO TO PROCESS-TRANSACTIONS. END-TRANSACTIONS. CLOSE TRANSACTION-FILE. * Your task: * Refactor this code using: * 1. PERFORM UNTIL to handle the main processing loop * 2. EVALUATE to handle the transaction code logic * 3. Eliminate all GO TO statements
Refactor the following error-handling code to use structured techniques instead of GO TO.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950* Legacy error handling with GO TO: VALIDATE-CUSTOMER. IF CUSTOMER-ID = SPACES GO TO ERROR-MISSING-ID. IF CUSTOMER-NAME = SPACES GO TO ERROR-MISSING-NAME. IF CUSTOMER-TYPE NOT = "R" AND NOT = "W" GO TO ERROR-INVALID-TYPE. IF CREDIT-LIMIT < 0 GO TO ERROR-NEGATIVE-CREDIT. MOVE "Y" TO VALID-CUSTOMER. GO TO VALIDATION-EXIT. ERROR-MISSING-ID. MOVE "Customer ID is required" TO ERROR-MESSAGE. MOVE "E001" TO ERROR-CODE. MOVE "N" TO VALID-CUSTOMER. GO TO VALIDATION-EXIT. ERROR-MISSING-NAME. MOVE "Customer name is required" TO ERROR-MESSAGE. MOVE "E002" TO ERROR-CODE. MOVE "N" TO VALID-CUSTOMER. GO TO VALIDATION-EXIT. ERROR-INVALID-TYPE. MOVE "Invalid customer type" TO ERROR-MESSAGE. MOVE "E003" TO ERROR-CODE. MOVE "N" TO VALID-CUSTOMER. GO TO VALIDATION-EXIT. ERROR-NEGATIVE-CREDIT. MOVE "Credit limit cannot be negative" TO ERROR-MESSAGE. MOVE "E004" TO ERROR-CODE. MOVE "N" TO VALID-CUSTOMER. GO TO VALIDATION-EXIT. VALIDATION-EXIT. EXIT. * Your task: * Refactor this code using: * 1. EVALUATE TRUE for conditional validation * 2. Consider using functions or nested conditions * 3. Eliminate all GO TO statements * 4. Make the code more maintainable
Rewrite the following computed GO TO using structured programming techniques.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849* Legacy code with computed GO TO: PROCESS-MENU-OPTION. DISPLAY "Main Menu:". DISPLAY "1. Add Record". DISPLAY "2. Update Record". DISPLAY "3. Delete Record". DISPLAY "4. Display Record". DISPLAY "5. Exit". DISPLAY "Enter choice (1-5): ". ACCEPT MENU-CHOICE. IF MENU-CHOICE < 1 OR MENU-CHOICE > 5 DISPLAY "Invalid choice, try again" GO TO PROCESS-MENU-OPTION. GO TO MENU-ADD MENU-UPDATE MENU-DELETE MENU-DISPLAY MENU-EXIT DEPENDING ON MENU-CHOICE. MENU-ADD. PERFORM ADD-RECORD. GO TO PROCESS-MENU-OPTION. MENU-UPDATE. PERFORM UPDATE-RECORD. GO TO PROCESS-MENU-OPTION. MENU-DELETE. PERFORM DELETE-RECORD. GO TO PROCESS-MENU-OPTION. MENU-DISPLAY. PERFORM DISPLAY-RECORD. GO TO PROCESS-MENU-OPTION. MENU-EXIT. DISPLAY "Exiting program...". CLOSE ALL FILES. STOP RUN. * Your task: * Refactor this code using: * 1. EVALUATE for menu selection * 2. PERFORM UNTIL for the menu loop * 3. A clean program exit strategy * 4. No GO TO statements
Programming paradigm focused on clarity, quality and maintainability
Understanding sections, paragraphs, and program flow
Structured alternative to GO TO for procedural control
Structured alternative to GO TO for conditional processing
Using explicit statement terminators like END-IF, END-PERFORM
1. What is the main criticism of the GO TO statement in structured programming?
2. What does the EXIT statement do in COBOL?
3. What is the difference between STOP RUN and GOBACK?
4. Which is the recommended modern alternative to GO TO for loop control?
5. Which scope terminator is specifically designed for exiting a PERFORM loop before its normal termination?