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
Your output
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
Your output
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
Your output
Visualizing Architecture
Here is the architectural layout of the programs we just built, showing how containment governs scope:
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
Your output
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 outputcobol
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
You predicted
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.