MainframeMaster

COBOL Tutorial

COBOL CALL Statement

The CALL statement represents one of the most sophisticated and powerful features in COBOL, enabling comprehensive program linkage, modular programming architecture, and inter-program communication that forms the backbone of enterprise application design. Far more than just a simple program invocation mechanism, the CALL statement facilitates the creation of complex, maintainable software systems by allowing programs to be broken down into specialized, reusable components that can be developed, tested, and maintained independently while working together as cohesive application suites. This capability is fundamental to modern COBOL development practices and is essential for building scalable, enterprise-grade applications that can adapt to changing business requirements while maintaining reliability and performance.

Understanding the CALL statement goes beyond basic syntax to encompass advanced concepts such as dynamic program loading, sophisticated parameter passing mechanisms, error handling strategies, memory management, and integration patterns that enable COBOL applications to interface seamlessly with contemporary technology stacks. The CALL statement serves as the foundation for creating service-oriented architectures, implementing business logic separation, and establishing communication protocols between different application components, making it an indispensable tool for enterprise software architects and developers.

Understanding CALL Statement Architecture

The CALL statement implements a sophisticated program linkage mechanism that enables one COBOL program (the calling program) to transfer control to another program (the called program or subprogram) while maintaining the ability to pass data between them and return control to the original program upon completion. This mechanism goes far beyond simple program execution to provide a comprehensive framework for building modular applications where complex business logic can be decomposed into manageable, specialized components that work together to accomplish larger objectives.

At its core, the CALL statement manages program context switching, parameter marshaling, memory allocation, and execution environment setup in a way that preserves data integrity and program state across program boundaries. This involves sophisticated runtime operations including stack management, register preservation, memory mapping, and execution context switching that occur transparently to the application programmer but are crucial for reliable program operation.

The architectural implications of the CALL statement extend throughout the entire application design process. It enables the implementation of layered architectures where presentation logic, business logic, and data access logic can be separated into distinct programs. It facilitates the creation of utility libraries that can be shared across multiple applications. It supports the development of plugin architectures where functionality can be added or modified without changing core application code. These capabilities make the CALL statement essential for creating maintainable, scalable enterprise applications.

Comprehensive CALL Statement Capabilities:

  • Dynamic Program Loading and Execution: The CALL statement can load and execute programs dynamically at runtime, enabling flexible application architectures where program components can be determined based on runtime conditions, user input, or configuration parameters.
  • Sophisticated Parameter Passing Mechanisms: Multiple parameter passing methods (BY REFERENCE, BY CONTENT, BY VALUE) provide fine-grained control over how data is shared between programs, enabling both efficient data sharing and protection against unintended modifications.
  • Bi-directional Data Communication: Called programs can modify data in the calling program (when using BY REFERENCE), return values through parameters, and communicate status information, enabling rich inter-program communication patterns.
  • Nested and Recursive Program Calls: Programs can call other programs which can in turn call additional programs, creating call stacks and enabling complex processing hierarchies and recursive algorithms.
  • Error Detection and Exception Handling: The CALL statement provides comprehensive error handling through ON EXCEPTION clauses, enabling robust error recovery and graceful degradation when called programs are unavailable or fail.
  • Cross-Language Integration: CALL statements can invoke programs written in other languages (C, C++, Assembly, Java), facilitating integration with existing systems and enabling access to specialized functionality not available in COBOL.
  • Memory and Resource Management: The CALL mechanism automatically handles memory allocation, deallocation, and resource cleanup, ensuring that system resources are managed efficiently across program boundaries.
  • Platform-Independent Operation: CALL statements work consistently across different operating systems and COBOL implementations, providing portability for applications that need to run in multiple environments.

Modular Programming and Software Architecture

The CALL statement is fundamental to implementing modular programming principles in COBOL applications. Modular programming involves breaking down complex applications into smaller, focused programs that each handle specific aspects of the overall functionality. This approach provides numerous benefits including improved maintainability, easier testing, better code reusability, clearer separation of concerns, and enhanced team productivity through parallel development of different modules.

In enterprise environments, modular programming enabled by CALL statements allows organizations to create standardized libraries of business logic that can be shared across multiple applications. Common functions such as date calculations, validation routines, data formatting, error handling, and business rule processing can be centralized in called programs, ensuring consistency across the organization and reducing duplication of code and effort.

The modular approach also supports agile development practices by enabling teams to work on different components simultaneously without interfering with each other. Changes to specific business logic can be isolated to individual programs, reducing the risk of unintended side effects and making application maintenance more predictable and manageable.

Performance and Efficiency Considerations

The performance characteristics of CALL statements are crucial considerations in enterprise application design. While CALL statements provide tremendous flexibility and architectural benefits, they do introduce overhead related to program loading, context switching, parameter marshaling, and stack management. Understanding these performance implications enables developers to make informed decisions about when to use CALL statements versus alternative approaches such as PERFORM statements or inline processing.

Static CALL statements (where the program name is specified as a literal) generally provide better performance than dynamic CALL statements (where the program name is determined at runtime) because the called program can be loaded and linked at compile time. However, dynamic CALL statements offer greater flexibility for building configurable applications where program behavior can be modified without recompiling the calling program.

Optimization strategies for CALL statement performance include minimizing the frequency of calls in tight loops, using appropriate parameter passing methods to avoid unnecessary data copying, caching frequently called programs in memory, and structuring program hierarchies to minimize call depth and complexity. These optimizations can significantly impact application performance in high-volume processing scenarios.

Enterprise Integration and Service Architecture

In modern enterprise environments, CALL statements serve as building blocks for service-oriented architectures and integration patterns that connect COBOL applications with contemporary technology stacks. Called programs can act as service interfaces, data transformation engines, protocol adapters, and integration points that enable COBOL applications to participate in distributed computing environments while maintaining their core business logic and data processing capabilities.

The CALL mechanism facilitates the implementation of adapter patterns where legacy COBOL business logic can be wrapped in modern interfaces, enabling integration with web services, message queuing systems, database APIs, and cloud computing platforms. This capability is essential for organizations that need to modernize their technology infrastructure while preserving investments in proven business logic and maintaining operational continuity.

Additionally, CALL statements enable the creation of plugin architectures where functionality can be extended through the addition of new called programs without modifying existing application code. This extensibility is crucial for applications that need to adapt to changing business requirements, integrate with new systems, or support customization for different organizational units or customer requirements.

Advanced Parameter Management and Data Flow

The parameter passing capabilities of CALL statements represent one of the most sophisticated aspects of COBOL's inter-program communication model. The three primary parameter passing methods (BY REFERENCE, BY CONTENT, BY VALUE) each serve specific purposes in data sharing and protection strategies, enabling developers to implement precise control over how data flows between programs and what modifications are permitted.

BY REFERENCE parameter passing enables efficient sharing of large data structures without the overhead of copying data, while also allowing called programs to modify the original data in the calling program. BY CONTENT provides protection against unintended modifications by passing copies of data, ensuring that the original data remains unchanged. BY VALUE is optimized for passing simple values and literals, providing the best performance for scalar data types.

Understanding these parameter passing mechanisms is crucial for implementing effective data flow architectures, ensuring data integrity across program boundaries, and optimizing application performance. The choice of parameter passing method can significantly impact both the functionality and performance characteristics of inter-program communication, making it an important design consideration in enterprise application development.

Understanding CALL Statement

The CALL statement allows:

  • Invoking external programs and subprograms
  • Passing parameters between programs
  • Dynamic program loading and execution
  • Modular program design and code reuse
  • Interface with external libraries and APIs
  • Error handling for failed program calls

CALL Statement Syntax

Basic CALL Syntax

cobol
1
2
3
4
5
6
7
CALL { "program-name" | identifier-1 } [USING { { [BY REFERENCE] } { identifier-2 | file-name-1 } | { BY CONTENT } { identifier-3 | literal-1 } | { BY VALUE } { identifier-4 | literal-2 } }...] [ON EXCEPTION imperative-statement-1] [NOT ON EXCEPTION imperative-statement-2] [END-CALL]

Simple Program Call

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
IDENTIFICATION DIVISION. PROGRAM-ID. MAIN-PROGRAM. DATA DIVISION. WORKING-STORAGE SECTION. 01 CUSTOMER-ID PIC 9(8) VALUE 12345678. 01 CUSTOMER-NAME PIC X(30). 01 ACCOUNT-BALANCE PIC S9(8)V99. 01 RETURN-CODE PIC 9(2). PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Main program starting...". *> Simple call without parameters CALL "INITIALIZE" ON EXCEPTION DISPLAY "Failed to call INITIALIZE program" STOP RUN END-CALL. *> Call with parameters CALL "GET-CUSTOMER" USING CUSTOMER-ID CUSTOMER-NAME ACCOUNT-BALANCE ON EXCEPTION DISPLAY "Failed to call GET-CUSTOMER" MOVE 99 TO RETURN-CODE NOT ON EXCEPTION DISPLAY "Customer retrieved successfully" PERFORM DISPLAY-CUSTOMER-INFO END-CALL. DISPLAY "Main program ending...". STOP RUN. DISPLAY-CUSTOMER-INFO. DISPLAY "Customer Information:". DISPLAY "ID: " CUSTOMER-ID. DISPLAY "Name: " CUSTOMER-NAME. DISPLAY "Balance: $" ACCOUNT-BALANCE.

Called Subprogram Example

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
IDENTIFICATION DIVISION. PROGRAM-ID. GET-CUSTOMER. DATA DIVISION. LINKAGE SECTION. 01 LK-CUSTOMER-ID PIC 9(8). 01 LK-CUSTOMER-NAME PIC X(30). 01 LK-ACCOUNT-BALANCE PIC S9(8)V99. WORKING-STORAGE SECTION. 01 CUSTOMER-TABLE. 05 CUSTOMER-ENTRY OCCURS 5 TIMES. 10 CUST-ID PIC 9(8). 10 CUST-NAME PIC X(30). 10 CUST-BAL PIC S9(8)V99. 01 INDEX-VAR PIC 9(2). 01 FOUND-FLAG PIC X VALUE 'N'. PROCEDURE DIVISION USING LK-CUSTOMER-ID LK-CUSTOMER-NAME LK-ACCOUNT-BALANCE. MAIN-PARA. PERFORM INITIALIZE-CUSTOMER-DATA. PERFORM SEARCH-CUSTOMER. IF FOUND-FLAG = 'Y' DISPLAY "Customer found in subprogram" ELSE DISPLAY "Customer not found" MOVE "UNKNOWN CUSTOMER" TO LK-CUSTOMER-NAME MOVE ZERO TO LK-ACCOUNT-BALANCE END-IF. GOBACK. INITIALIZE-CUSTOMER-DATA. *> Initialize sample customer data MOVE 12345678 TO CUST-ID(1). MOVE "John Smith" TO CUST-NAME(1). MOVE 1500.75 TO CUST-BAL(1). MOVE 23456789 TO CUST-ID(2). MOVE "Jane Johnson" TO CUST-NAME(2). MOVE 2750.50 TO CUST-BAL(2). MOVE 34567890 TO CUST-ID(3). MOVE "Bob Wilson" TO CUST-NAME(3). MOVE -150.25 TO CUST-BAL(3). SEARCH-CUSTOMER. PERFORM VARYING INDEX-VAR FROM 1 BY 1 UNTIL INDEX-VAR > 5 IF CUST-ID(INDEX-VAR) = LK-CUSTOMER-ID MOVE CUST-NAME(INDEX-VAR) TO LK-CUSTOMER-NAME MOVE CUST-BAL(INDEX-VAR) TO LK-ACCOUNT-BALANCE MOVE 'Y' TO FOUND-FLAG EXIT PERFORM END-IF END-PERFORM.

Parameter Passing Methods

BY REFERENCE (Default)

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
IDENTIFICATION DIVISION. PROGRAM-ID. REFERENCE-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-NUMBER PIC 9(5) VALUE 100. 01 OUTPUT-NUMBER PIC 9(5). 01 COUNTER PIC 9(3) VALUE 0. PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Before CALL - Input: " INPUT-NUMBER. DISPLAY "Before CALL - Counter: " COUNTER. *> BY REFERENCE allows the called program to modify values CALL "MODIFY-VALUES" USING BY REFERENCE INPUT-NUMBER BY REFERENCE COUNTER BY REFERENCE OUTPUT-NUMBER. DISPLAY "After CALL - Input: " INPUT-NUMBER. DISPLAY "After CALL - Counter: " COUNTER. DISPLAY "After CALL - Output: " OUTPUT-NUMBER. STOP RUN. *> Called subprogram IDENTIFICATION DIVISION. PROGRAM-ID. MODIFY-VALUES. DATA DIVISION. LINKAGE SECTION. 01 LK-INPUT PIC 9(5). 01 LK-COUNTER PIC 9(3). 01 LK-OUTPUT PIC 9(5). PROCEDURE DIVISION USING LK-INPUT LK-COUNTER LK-OUTPUT. MAIN-PARA. *> Modify input parameter MULTIPLY LK-INPUT BY 2 GIVING LK-INPUT. *> Increment counter ADD 1 TO LK-COUNTER. *> Set output value COMPUTE LK-OUTPUT = LK-INPUT + LK-COUNTER. DISPLAY "In subprogram - Modified input: " LK-INPUT. DISPLAY "In subprogram - Counter: " LK-COUNTER. DISPLAY "In subprogram - Output: " LK-OUTPUT. GOBACK.

BY CONTENT (Copy)

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
IDENTIFICATION DIVISION. PROGRAM-ID. CONTENT-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 ORIGINAL-VALUE PIC 9(5) VALUE 500. 01 CALCULATION-RESULT PIC 9(8). PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Before CALL - Original: " ORIGINAL-VALUE. *> BY CONTENT passes a copy - original cannot be modified CALL "CALCULATE" USING BY CONTENT ORIGINAL-VALUE BY REFERENCE CALCULATION-RESULT. DISPLAY "After CALL - Original: " ORIGINAL-VALUE. DISPLAY "After CALL - Result: " CALCULATION-RESULT. STOP RUN. *> Called subprogram IDENTIFICATION DIVISION. PROGRAM-ID. CALCULATE. DATA DIVISION. LINKAGE SECTION. 01 LK-INPUT-VALUE PIC 9(5). 01 LK-RESULT PIC 9(8). PROCEDURE DIVISION USING LK-INPUT-VALUE LK-RESULT. MAIN-PARA. DISPLAY "In subprogram - Received: " LK-INPUT-VALUE. *> Try to modify input (won't affect original) MULTIPLY LK-INPUT-VALUE BY 10 GIVING LK-INPUT-VALUE. DISPLAY "In subprogram - Modified: " LK-INPUT-VALUE. *> Calculate result COMPUTE LK-RESULT = LK-INPUT-VALUE * LK-INPUT-VALUE. GOBACK.

BY VALUE (Literals and Values)

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
IDENTIFICATION DIVISION. PROGRAM-ID. VALUE-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 CALCULATION-TYPE PIC 9 VALUE 1. 01 BASE-VALUE PIC 9(5) VALUE 100. 01 RESULT PIC 9(8). PROCEDURE DIVISION. MAIN-PARA. *> BY VALUE for passing literals and simple values CALL "MATHEMATICAL-OPERATION" USING BY VALUE CALCULATION-TYPE BY VALUE 25 BY VALUE BASE-VALUE BY REFERENCE RESULT. DISPLAY "Result of operation: " RESULT. *> Call with different literal values CALL "MATHEMATICAL-OPERATION" USING BY VALUE 2 BY VALUE 50 BY VALUE BASE-VALUE BY REFERENCE RESULT. DISPLAY "Result of second operation: " RESULT. STOP RUN. *> Called subprogram IDENTIFICATION DIVISION. PROGRAM-ID. MATHEMATICAL-OPERATION. DATA DIVISION. LINKAGE SECTION. 01 LK-OPERATION-TYPE PIC 9. 01 LK-MULTIPLIER PIC 9(3). 01 LK-BASE PIC 9(5). 01 LK-RESULT PIC 9(8). PROCEDURE DIVISION USING LK-OPERATION-TYPE LK-MULTIPLIER LK-BASE LK-RESULT. MAIN-PARA. DISPLAY "Operation: " LK-OPERATION-TYPE. DISPLAY "Multiplier: " LK-MULTIPLIER. DISPLAY "Base: " LK-BASE. EVALUATE LK-OPERATION-TYPE WHEN 1 MULTIPLY LK-BASE BY LK-MULTIPLIER GIVING LK-RESULT WHEN 2 COMPUTE LK-RESULT = LK-BASE + LK-MULTIPLIER WHEN 3 COMPUTE LK-RESULT = LK-BASE - LK-MULTIPLIER WHEN OTHER MOVE ZERO TO LK-RESULT END-EVALUATE. GOBACK.

Dynamic CALL and Error Handling

Dynamic Program Loading

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
IDENTIFICATION DIVISION. PROGRAM-ID. DYNAMIC-CALL-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 PROGRAM-NAME PIC X(20). 01 USER-CHOICE PIC 9. 01 INPUT-DATA PIC X(50). 01 OUTPUT-DATA PIC X(100). 01 RETURN-CODE PIC 9(2). PROCEDURE DIVISION. MAIN-PARA. PERFORM DISPLAY-MENU. PERFORM GET-USER-CHOICE. PERFORM CALL-SELECTED-PROGRAM. STOP RUN. DISPLAY-MENU. DISPLAY "Dynamic Program Menu:". DISPLAY "1. Data Validation". DISPLAY "2. Data Formatting". DISPLAY "3. Data Calculation". DISPLAY "4. Data Reporting". DISPLAY "Enter choice (1-4): " WITH NO ADVANCING. GET-USER-CHOICE. ACCEPT USER-CHOICE. EVALUATE USER-CHOICE WHEN 1 MOVE "VALIDATE-DATA" TO PROGRAM-NAME WHEN 2 MOVE "FORMAT-DATA" TO PROGRAM-NAME WHEN 3 MOVE "CALC-DATA" TO PROGRAM-NAME WHEN 4 MOVE "REPORT-DATA" TO PROGRAM-NAME WHEN OTHER DISPLAY "Invalid choice" STOP RUN END-EVALUATE. CALL-SELECTED-PROGRAM. MOVE "Sample input data" TO INPUT-DATA. DISPLAY "Calling program: " PROGRAM-NAME. CALL PROGRAM-NAME USING INPUT-DATA OUTPUT-DATA ON EXCEPTION DISPLAY "Error: Program " PROGRAM-NAME " not found" DISPLAY "or failed to load" MOVE 99 TO RETURN-CODE NOT ON EXCEPTION DISPLAY "Program executed successfully" DISPLAY "Output: " OUTPUT-DATA MOVE 0 TO RETURN-CODE END-CALL. DISPLAY "Return code: " RETURN-CODE.

Error Handling and Recovery

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
IDENTIFICATION DIVISION. PROGRAM-ID. CALL-ERROR-HANDLING. DATA DIVISION. WORKING-STORAGE SECTION. 01 PROGRAM-LIST. 05 PROG-ENTRY OCCURS 5 TIMES. 10 PROG-NAME PIC X(15). 10 PROG-STATUS PIC X(10). 01 INDEX-VAR PIC 9(2). 01 SUCCESS-COUNT PIC 9(2) VALUE 0. 01 FAILURE-COUNT PIC 9(2) VALUE 0. 01 TEST-DATA PIC X(20) VALUE "TEST DATA". 01 RESULT-DATA PIC X(50). PROCEDURE DIVISION. MAIN-PARA. PERFORM INITIALIZE-PROGRAM-LIST. PERFORM TEST-ALL-PROGRAMS. PERFORM DISPLAY-RESULTS. STOP RUN. INITIALIZE-PROGRAM-LIST. MOVE "UTILITY1" TO PROG-NAME(1). MOVE "UTILITY2" TO PROG-NAME(2). MOVE "UTILITY3" TO PROG-NAME(3). MOVE "NONEXISTENT" TO PROG-NAME(4). MOVE "UTILITY5" TO PROG-NAME(5). TEST-ALL-PROGRAMS. PERFORM VARYING INDEX-VAR FROM 1 BY 1 UNTIL INDEX-VAR > 5 PERFORM TEST-SINGLE-PROGRAM END-PERFORM. TEST-SINGLE-PROGRAM. DISPLAY "Testing program: " PROG-NAME(INDEX-VAR). CALL PROG-NAME(INDEX-VAR) USING TEST-DATA RESULT-DATA ON EXCEPTION MOVE "FAILED" TO PROG-STATUS(INDEX-VAR) ADD 1 TO FAILURE-COUNT DISPLAY " Status: FAILED - Program not found or error" NOT ON EXCEPTION MOVE "SUCCESS" TO PROG-STATUS(INDEX-VAR) ADD 1 TO SUCCESS-COUNT DISPLAY " Status: SUCCESS - " RESULT-DATA END-CALL. DISPLAY-RESULTS. DISPLAY " ". DISPLAY "Program Test Summary:". DISPLAY "====================". DISPLAY "Successful calls: " SUCCESS-COUNT. DISPLAY "Failed calls: " FAILURE-COUNT. DISPLAY " ". DISPLAY "Detailed Results:". PERFORM VARYING INDEX-VAR FROM 1 BY 1 UNTIL INDEX-VAR > 5 DISPLAY PROG-NAME(INDEX-VAR) " - " PROG-STATUS(INDEX-VAR) END-PERFORM.

Advanced CALL Techniques

Nested Program Calls

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
IDENTIFICATION DIVISION. PROGRAM-ID. NESTED-CALLS-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 LEVEL-INDICATOR PIC 9 VALUE 1. 01 PROCESSING-DATA PIC X(100). 01 FINAL-RESULT PIC X(200). PROCEDURE DIVISION. MAIN-PARA. MOVE "Initial data for processing" TO PROCESSING-DATA. DISPLAY "Level " LEVEL-INDICATOR " - Main program starting". CALL "LEVEL-TWO" USING LEVEL-INDICATOR PROCESSING-DATA FINAL-RESULT. DISPLAY "Level " LEVEL-INDICATOR " - Main program ending". DISPLAY "Final result: " FINAL-RESULT. STOP RUN. *> Second level program IDENTIFICATION DIVISION. PROGRAM-ID. LEVEL-TWO. DATA DIVISION. LINKAGE SECTION. 01 LK-LEVEL PIC 9. 01 LK-DATA PIC X(100). 01 LK-RESULT PIC X(200). WORKING-STORAGE SECTION. 01 NEXT-LEVEL PIC 9. 01 INTERMEDIATE-RESULT PIC X(150). PROCEDURE DIVISION USING LK-LEVEL LK-DATA LK-RESULT. MAIN-PARA. ADD 1 TO LK-LEVEL GIVING NEXT-LEVEL. DISPLAY "Level " LK-LEVEL " - Processing data: " LK-DATA. STRING "Level-2 processed: " LK-DATA DELIMITED BY SIZE INTO INTERMEDIATE-RESULT. CALL "LEVEL-THREE" USING NEXT-LEVEL INTERMEDIATE-RESULT LK-RESULT. DISPLAY "Level " LK-LEVEL " - Returning to caller". GOBACK. *> Third level program IDENTIFICATION DIVISION. PROGRAM-ID. LEVEL-THREE. DATA DIVISION. LINKAGE SECTION. 01 LK-LEVEL PIC 9. 01 LK-DATA PIC X(150). 01 LK-RESULT PIC X(200). PROCEDURE DIVISION USING LK-LEVEL LK-DATA LK-RESULT. MAIN-PARA. DISPLAY "Level " LK-LEVEL " - Final processing: " LK-DATA. STRING "Level-3 final: " LK-DATA DELIMITED BY SIZE INTO LK-RESULT. DISPLAY "Level " LK-LEVEL " - Processing complete". GOBACK.

Recursive Calls

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
IDENTIFICATION DIVISION. PROGRAM-ID. RECURSIVE-DEMO. DATA DIVISION. WORKING-STORAGE SECTION. 01 INPUT-NUMBER PIC 9(2) VALUE 5. 01 FACTORIAL-RESULT PIC 9(10). PROCEDURE DIVISION. MAIN-PARA. DISPLAY "Calculating factorial of " INPUT-NUMBER. CALL "FACTORIAL" USING INPUT-NUMBER FACTORIAL-RESULT. DISPLAY "Factorial of " INPUT-NUMBER " is " FACTORIAL-RESULT. STOP RUN. *> Recursive factorial program IDENTIFICATION DIVISION. PROGRAM-ID. FACTORIAL. OPTIONS. RECURSIVE. DATA DIVISION. LINKAGE SECTION. 01 LK-NUMBER PIC 9(2). 01 LK-RESULT PIC 9(10). WORKING-STORAGE SECTION. 01 TEMP-NUMBER PIC 9(2). 01 TEMP-RESULT PIC 9(10). PROCEDURE DIVISION USING LK-NUMBER LK-RESULT. MAIN-PARA. DISPLAY "Calculating factorial for: " LK-NUMBER. IF LK-NUMBER <= 1 MOVE 1 TO LK-RESULT DISPLAY "Base case reached: " LK-RESULT ELSE SUBTRACT 1 FROM LK-NUMBER GIVING TEMP-NUMBER CALL "FACTORIAL" USING TEMP-NUMBER TEMP-RESULT MULTIPLY LK-NUMBER BY TEMP-RESULT GIVING LK-RESULT DISPLAY "Calculated: " LK-NUMBER " * " TEMP-RESULT " = " LK-RESULT END-IF. GOBACK.

Parameter Passing Rules

Passing MethodData TransferModificationUse Case
BY REFERENCEAddress passedOriginal can be modifiedInput/Output parameters
BY CONTENTCopy of dataOriginal protectedInput-only parameters
BY VALUEValue copiedCannot be modifiedLiterals and constants

CALL vs PERFORM

When to Use CALL

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
*> Use CALL for: *> 1. Separate compiled programs *> 2. Reusable utility functions *> 3. Modular architecture *> 4. Dynamic loading *> 5. Different programming languages CALL "UTILITY-PROGRAM" USING PARAMETER-LIST. *> Use PERFORM for: *> 1. Internal paragraphs/sections *> 2. Same program structure *> 3. Better performance *> 4. Simple code organization PERFORM CALCULATE-TOTALS.

Best Practices

Do

  • Use LINKAGE SECTION for called programs
  • Handle ON EXCEPTION conditions
  • Use appropriate parameter passing methods
  • Document parameter interfaces clearly
  • Use GOBACK to return from subprograms
  • Validate parameters in called programs

Don't

  • Ignore CALL exceptions
  • Mix parameter passing methods carelessly
  • Use STOP RUN in called subprograms
  • Assume programs are always available
  • Pass uninitialized parameters
  • Exceed maximum parameter limits

Related COBOL Concepts

  • LINKAGE SECTION - Parameter definition area
  • GOBACK - Return from called program
  • CANCEL - Remove program from memory
  • PERFORM - Internal paragraph execution
  • USING - Parameter specification
  • PROCEDURE DIVISION USING - Parameter declaration