Subprograms & CALL
25.1 Calling a subprogram
Main program (payroll.cob):
Subprogram (calctax.cob):
Parameters are matched by position, not by name. The LINKAGE layouts must match the caller's data exactly — a mismatch silently corrupts memory. Share layouts through copybooks (Chapter 27).
WORKING-STORAGE of the subprogram persists between calls (WS-CALL-COUNT keeps counting) until the caller issues CANCEL "CALCTAX". Use PROGRAM-ID. CALCTAX IS INITIAL. to get fresh storage on every call, or LOCAL-STORAGE.
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYROLL.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-GROSS PIC S9(7)V99 COMP-3 VALUE 5250.00.
01 WS-TAX-RATE PIC SV9(4) COMP-3 VALUE .2150.
01 WS-TAX PIC S9(7)V99 COMP-3.
01 ED-TAX PIC Z,ZZZ,ZZ9.99.
PROCEDURE DIVISION.
CALL "CALCTAX" USING BY REFERENCE WS-GROSS
BY CONTENT WS-TAX-RATE
BY REFERENCE WS-TAX
ON EXCEPTION
DISPLAY "CALCTAX not found"
MOVE 16 TO RETURN-CODE
STOP RUN
END-CALL
IF RETURN-CODE NOT = 0
DISPLAY "CALCTAX failed, RC = " RETURN-CODE
END-IF
MOVE WS-TAX TO ED-TAX
DISPLAY "Tax: " ED-TAX
STOP RUN.IDENTIFICATION DIVISION.
PROGRAM-ID. CALCTAX.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CALL-COUNT PIC 9(5) VALUE 0.
LINKAGE SECTION.
01 LK-GROSS PIC S9(7)V99 COMP-3.
01 LK-RATE PIC SV9(4) COMP-3.
01 LK-TAX PIC S9(7)V99 COMP-3.
PROCEDURE DIVISION USING LK-GROSS LK-RATE LK-TAX.
ADD 1 TO WS-CALL-COUNT
IF LK-GROSS < 0
MOVE 8 TO RETURN-CODE
GOBACK
END-IF
COMPUTE LK-TAX ROUNDED = LK-GROSS * LK-RATE
MOVE 0 TO RETURN-CODE
GOBACK.cobc -x payroll.cob calctax.cob # one executable (static)
# or: dynamic loading
cobc -x payroll.cob
cobc -m -o CALCTAX.so calctax.cob # module named after the PROGRAM-ID
# (.dll on Windows, .dylib/.so on macOS)
export COB_LIBRARY_PATH=. # where to find modules
./payroll # Tax: 1,128.7525.2 Passing modes
What is passed Callee changes visible to caller?
BY REFERENCE (default) Address of the caller's item Normal COBOL-to-COBOL parameters, outputs Address of a temporary copy Protect caller data; pass literals
The value itself (binary integers, pointers) Calling C and system APIs
RETURNING receives a function-style result: CALL "strlen" USING BY REFERENCE WS-CSTR RETURNING WS-LEN.
25.3 Static vs dynamic calls
CALL "LITERAL" compiled with IBM NODYNAM (or GnuCOBOL -fstatic-call)
CALL WS-PGM-NAME (identifier) always; CALL "LITERAL" with IBM DYNAM
Subprogram link-edited into the caller's load module Loaded from a library (STEPLIB/JOBLIB on z/OS, COB_LIBRARY_PATH in GnuCOBOL) at first call
Slightly faster call; single module to deploy Subprogram can be changed without relinking callers; smaller modules; CANCEL frees storage Relink every caller after a change
Load overhead on first call; S806 abend if module is missing
Example of a dynamic call: CALL WS-PGM-NAME USING WS-GROSS WS-TAX-RATE WS-TAX (with WS-PGM-NAME PIC X(8) VALUE "CALCTAX"), followed later by CANCEL WS-PGM-NAME to release it.
25.4 Calling C from GnuCOBOL
COMP-5 matches the native C int representation. On z/OS, COBOL calls C, PL/I, and Assembler through Language Environment (LE) interlanguage communication.
/* addints.c */
int add_ints(int a, int b) { return a + b; }IDENTIFICATION DIVISION.
PROGRAM-ID. CALLC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-A PIC S9(9) COMP-5 VALUE 40.
01 WS-B PIC S9(9) COMP-5 VALUE 2.
01 WS-SUM PIC S9(9) COMP-5.
PROCEDURE DIVISION.
CALL "add_ints" USING BY VALUE WS-A BY VALUE WS-B
RETURNING WS-SUM
END-CALL
DISPLAY "Sum from C: " WS-SUM
STOP RUN.cobc -x callc.cob addints.c && ./callc25.5 Receiving a JCL PARM (z/OS)
with //STEP1 EXEC PGM=MYPROG,PARM='2026-03-31,FULL'.
LINKAGE SECTION.
01 LK-PARM.
05 LK-PARM-LEN PIC S9(4) COMP.
05 LK-PARM-TEXT PIC X(100).
PROCEDURE DIVISION USING LK-PARM.
IF LK-PARM-LEN > 0
DISPLAY "PARM = " LK-PARM-TEXT(1:LK-PARM-LEN)
END-IF25.6 RETURN-CODE
RETURN-CODE is a special register. In a subprogram it returns a status to the caller; in the main program its final value becomes the step condition code on z/OS (or the process exit status on Linux), which JCL can test with COND or IF (Chapter 35). Conventions: 0 = OK, 4 = warning, 8 = error, 12 = severe, 16 = fatal.