Nested Programs and GLOBAL

COBOL COBOL 2014 (ISO/IEC 1989:2014), built with GnuCOBOL 3.x Β· βœ“ verified by execution on 2026-08-16

In COBOL-85, a program can contain other programs, which in turn can contain their own nested programs. This architectural feature allows you to encapsulate logic modularly without the overhead of maintaining separate source files.

A nested program must be placed immediately before the END PROGRAM statement of its parent, and it must contain its own IDENTIFICATION DIVISION and END PROGRAM terminator.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. OuterProg.
       PROCEDURE DIVISION.
           DISPLAY "In Outer".
           CALL "InnerProg".
           DISPLAY "Back in Outer".
           STOP RUN.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. InnerProg.
       PROCEDURE DIVISION.
           DISPLAY "In Inner".
           EXIT PROGRAM.
       END PROGRAM InnerProg.
       END PROGRAM OuterProg.
Output
In Outer
In Inner
Back in Outer

By default, a nested program is only visible to the program that directly contains it. When compiled, the entire hierarchy acts as a single compilation unit, making calls highly efficient.

Sharing State: The GLOBAL Clause

Unlike some languages where inner functions automatically inherit their parent’s scope, COBOL requires explicit permission. The GLOBAL clause specifies that a data-name is available to every program contained within the program that declares it.

The GLOBAL clause must be used on an 01 level data item in the parent program.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. OuterProg.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-GLOBAL-VAR PIC X(20) VALUE "I AM GLOBAL" GLOBAL.
       01 WS-LOCAL-VAR  PIC X(20) VALUE "I AM LOCAL".
       PROCEDURE DIVISION.
           DISPLAY "Outer: " WS-GLOBAL-VAR.
           CALL "InnerProg".
           STOP RUN.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. InnerProg.
       PROCEDURE DIVISION.
           DISPLAY "Inner: " WS-GLOBAL-VAR.
           EXIT PROGRAM.
       END PROGRAM InnerProg.
       END PROGRAM OuterProg.
Output
Outer: I AM GLOBAL         
Inner: I AM GLOBAL         

This provides a cleaner alternative to passing dozens of variables down through the LINKAGE SECTION for every nested subprogram call.

Scope Visibility: Sibling Programs

What if one nested program wants to call another nested program at the same level? The COMMON clause is used to make a nested program available to other sibling nested programs. Without COMMON, they cannot see each other.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. TopProg.
       PROCEDURE DIVISION.
           CALL "MiddleProg".
           STOP RUN.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. MiddleProg.
       PROCEDURE DIVISION.
           DISPLAY "In Middle".
           CALL "HelperProg".
           EXIT PROGRAM.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. HelperProg COMMON.
       PROCEDURE DIVISION.
           DISPLAY "In Helper".
           EXIT PROGRAM.
       END PROGRAM HelperProg.
       END PROGRAM MiddleProg.
       END PROGRAM TopProg.
Output
In Middle
In Helper

Visualizing Architecture

Here is the architectural layout of the programs we just built, showing how containment governs scope:

TopProg (Outer) MiddleProg (Nested) HelperProg (COMMON) TopProg can CALL MiddleProg MiddleProg can CALL HelperProg TopProg cannot directly CALL HelperProg
Nested Program Architecture and Visibility

The LOCAL-STORAGE Section

Often confused with WORKING-STORAGE, the LOCAL-STORAGE SECTION serves a specific purpose: allocating memory per invocation. While WORKING-STORAGE is initialized once and retains its state across calls (static memory), LOCAL-STORAGE guarantees a fresh copy of data every time the program is called.

cobol βœ“ verified output
       IDENTIFICATION DIVISION.
       PROGRAM-ID. MainProg.
       PROCEDURE DIVISION.
           PERFORM 3 TIMES
               CALL "RecurseProg"
           END-PERFORM.
           STOP RUN.
       END PROGRAM MainProg.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. RecurseProg.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01 WS-COUNT PIC 9 VALUE 0.
       LOCAL-STORAGE SECTION.
       01 LS-COUNT PIC 9 VALUE 0.
       PROCEDURE DIVISION.
           ADD 1 TO WS-COUNT.
           ADD 1 TO LS-COUNT.
           DISPLAY "WS: " WS-COUNT " LS: " LS-COUNT.
           EXIT PROGRAM.
       END PROGRAM RecurseProg.
Output
WS: 1 LS: 1
WS: 2 LS: 1
WS: 3 LS: 1

A Critical Restriction

Because nested programs share the same physical memory space during a single compilation unit’s execution, a nested program cannot have a Local-Storage Section. It is strictly forbidden.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. MainProg.
       PROCEDURE DIVISION.
           CALL "RecurseProg"
           STOP RUN.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. RecurseProg.
       DATA DIVISION.
       LOCAL-STORAGE SECTION.
       01 LS-COUNT PIC 9 VALUE 0.
       PROCEDURE DIVISION.
           EXIT PROGRAM.
       END PROGRAM RecurseProg.
       END PROGRAM MainProg.
LOCAL-STORAGE not allowed in nested programs

Common Misconceptions

A frequent mistake is halting execution inside a nested subprogram when the intention was only to return to the parent.

Predict the output cobol

Read the code. What exactly will it print? Commit to an answer before you look.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. TopProg.
       PROCEDURE DIVISION.
           DISPLAY "Start".
           CALL "InnerProg".
           DISPLAY "End".
           STOP RUN.
       IDENTIFICATION DIVISION.
       PROGRAM-ID. InnerProg.
       PROCEDURE DIVISION.
           DISPLAY "Inside".
           STOP RUN.
       END PROGRAM InnerProg.
       END PROGRAM TopProg.
Output
Start
Inside

Using STOP RUN terminates the entire run unit. To return control from a nested program (or any subprogram) back to its caller, always use EXIT PROGRAM or GOBACK.

Check yourself

Which of the following is true regarding nested programs in COBOL?

Reveal answer

They can only access parent variables explicitly declared with the GLOBAL clause, or passed via linkage. β€” Nested programs are contained within the parent's source and can only access parent variables explicitly declared with the GLOBAL clause, or passed via linkage.

What is the primary characteristic of the LOCAL-STORAGE section?

Reveal answer

It is strictly forbidden in nested programs. It is used in recursive or multi-threaded subprograms to allocate fresh memory per call. β€” LOCAL-STORAGE is strictly forbidden in nested programs. It is used in recursive or multi-threaded subprograms to allocate fresh memory per call.

By default, which programs can call a nested program?

Reveal answer

Only its immediate parent. β€” By default, a nested program is only visible to its immediate parent. It needs the COMMON attribute to be visible to sibling programs.

What happens when you use STOP RUN inside a nested program?

Reveal answer

It stops the entire run unit (application). You must use EXIT PROGRAM or GOBACK to return to the parent program. β€” STOP RUN halts the entire run unit (application). You must use EXIT PROGRAM or GOBACK to return to the parent program.

Challenges

Challenge 1 +50 XP

Fix the following program so that it successfully calls the nested program and displays 'Welcome to COBOL!'. Pay attention to the program terminator.

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 "Welcome to COBOL!"
Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. MainApp.
PROCEDURE DIVISION.
    CALL "GreetUser".
    STOP RUN.

IDENTIFICATION DIVISION.
PROGRAM-ID. GreetUser.
PROCEDURE DIVISION.
    DISPLAY "Welcome to COBOL!".
    EXIT PROGRAM.
END PROGRAM GreetUser.

END PROGRAM MainApp.

🐞 Bug Hunt +50 XP

This program tries to update a counter from a nested program, but the main program prints the original value. Fix the visibility of the counter so the update applies globally.

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 "Total Tx: 01"
Show solution (0 XP)
IDENTIFICATION DIVISION.
PROGRAM-ID. AppRoot.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 TRANSACTION-COUNT PIC 99 VALUE 00 GLOBAL.
PROCEDURE DIVISION.
    CALL "ProcessTx".
    DISPLAY "Total Tx: " TRANSACTION-COUNT.
    STOP RUN.

IDENTIFICATION DIVISION.
PROGRAM-ID. ProcessTx.
PROCEDURE DIVISION.
    ADD 1 TO TRANSACTION-COUNT.
    EXIT PROGRAM.
END PROGRAM ProcessTx.

END PROGRAM AppRoot.