Chapter 17 Exercises: Subprograms and the CALL Statement

Tier 1: Comprehension (Exercises 1-8)

Exercise 1: Identify the Call Type

For each of the following CALL statements, identify whether it is a static call or a dynamic call. Assume the compiler option is NODYNAM unless stated otherwise.

      * (a)
       CALL 'VALIDATE' USING WS-DATA

      * (b)
       MOVE 'VALIDATE' TO WS-PROG-NAME
       CALL WS-PROG-NAME USING WS-DATA

      * (c) Compiled with DYNAM option
       CALL 'VALIDATE' USING WS-DATA

      * (d)
       01 WS-PGM PIC X(08) VALUE 'CALCPAY'.
       CALL WS-PGM USING WS-EMPLOYEE-REC

      * (e) Compiled with NODYNAM option
       CALL 'LOGMSG' USING WS-MESSAGE

Exercise 2: Parameter Passing Analysis

Given the following code in the main program:

       01  WS-FIELD-A    PIC X(10) VALUE 'AAAAAAAAAA'.
       01  WS-FIELD-B    PIC X(10) VALUE 'BBBBBBBBBB'.
       01  WS-FIELD-C    PIC S9(08) COMP-5 VALUE 100.
       ...
       CALL 'MYSUB' USING BY REFERENCE WS-FIELD-A
                          BY CONTENT   WS-FIELD-B
                          BY VALUE     WS-FIELD-C

And the subprogram modifies all three parameters:

       MOVE 'XXXXXXXXXX' TO LS-FIELD-A
       MOVE 'YYYYYYYYYY' TO LS-FIELD-B
       ADD 50 TO LS-FIELD-C

After the CALL returns, what are the values of WS-FIELD-A, WS-FIELD-B, and WS-FIELD-C in the calling program? Explain your answer for each.

Exercise 3: Temperature Conversion Subprogram

Write a subprogram called TEMPCONV that converts temperatures between Fahrenheit, Celsius, and Kelvin. The subprogram should accept: - An input temperature (PIC S9(05)V99) - A source scale indicator ('F', 'C', or 'K') - A target scale indicator ('F', 'C', or 'K') - An output temperature field - A return status code

Write a main program that calls TEMPCONV to convert: - 212 degrees Fahrenheit to Celsius - 100 degrees Celsius to Kelvin - 0 Kelvin to Fahrenheit

Solution: See exercise-solutions.cob, Exercise 3 section.

Exercise 4: GOBACK vs. STOP RUN

Explain the difference between GOBACK and STOP RUN when used in a subprogram. Given the following call chain:

MAINPROG calls SUBPROG-A
SUBPROG-A calls SUBPROG-B
SUBPROG-B calls SUBPROG-C

What happens if SUBPROG-C executes: 1. GOBACK 2. STOP RUN 3. EXIT PROGRAM

Exercise 5: LINKAGE SECTION Matching

The calling program has:

       01  WS-PARMS.
           05  WS-CODE    PIC X(03).
           05  WS-AMOUNT  PIC 9(07)V99.
           05  WS-DATE    PIC 9(08).
       CALL 'MYSUB' USING WS-PARMS

The called program has:

       LINKAGE SECTION.
       01  LS-PARMS.
           05  LS-CODE    PIC X(03).
           05  LS-VALUE   PIC 9(09).
           05  LS-YEAR    PIC 9(04).
           05  LS-REST    PIC X(04).

Will this work? What problems might occur? How would you fix it?

Exercise 6: WORKING-STORAGE Persistence

A subprogram has the following WORKING-STORAGE:

       01  WS-COUNTER   PIC 9(04) VALUE 0.
       01  WS-TOTAL     PIC 9(08)V99 VALUE 0.

The main program calls this subprogram five times, and each time the subprogram adds 1 to WS-COUNTER and adds 100.00 to WS-TOTAL.

  1. What are the values of WS-COUNTER and WS-TOTAL after the fifth call?
  2. The main program then executes CANCEL 'SUBPROG' and calls it again. What are the values now?
  3. If the subprogram had PROGRAM-ID. SUBPROG IS INITIAL, what would happen on each call?

Exercise 7: String Utility Subprogram

Write a COBOL subprogram called STRUTIL that performs string operations. It should accept: - An operation code: 'UPPER' (uppercase), 'LOWER' (lowercase), 'REVRS' (reverse), 'TRIM' (trim trailing spaces), 'LNGTH' (calculate length) - An input string (PIC X(100)) - An output string (PIC X(100)) - A result length (PIC 9(04)) - A status code

Write a main program that tests each operation.

Solution: See exercise-solutions.cob, Exercise 7 section.

Exercise 8: Nested Program Visibility

Given this structure:

       PROGRAM-ID. MAIN-PROG.
           PROGRAM-ID. SUB-A.
           END PROGRAM SUB-A.
           PROGRAM-ID. SUB-B.
           END PROGRAM SUB-B.
           PROGRAM-ID. SUB-C IS COMMON.
           END PROGRAM SUB-C.
       END PROGRAM MAIN-PROG.

Answer the following: 1. Can MAIN-PROG call SUB-A? SUB-B? SUB-C? 2. Can SUB-A call SUB-B? 3. Can SUB-A call SUB-C? 4. Can SUB-B call SUB-A? 5. Can SUB-B call SUB-C?


Tier 2: Application (Exercises 9-15)

Exercise 9: Multi-Subprogram Payroll System

Design and implement a payroll processing system with the following subprograms:

  1. VALIDEMP - Validates employee input data (checks for required fields, valid ranges)
  2. CALCGROS - Calculates gross pay from hours worked and hourly rate (including overtime at 1.5x for hours over 40)
  3. CALCTAX - Calculates federal tax based on a progressive tax bracket table
  4. CALCNET - Calculates net pay after tax

Write a main program that reads employee records, calls each subprogram in sequence, and produces a report. Use BY CONTENT for input parameters and BY REFERENCE for output parameters.

Exercise 10: Dynamic Dispatch Table

Write a program that uses a table-driven approach to dynamic calls. Define a table of transaction types and their corresponding subprogram names:

       01  WS-DISPATCH-TABLE.
           05  FILLER  PIC X(10) VALUE 'ADEPOSITP'.
           05  FILLER  PIC X(10) VALUE 'WWITHDRAW'.
           05  FILLER  PIC X(10) VALUE 'TTRANSFER'.
           05  FILLER  PIC X(10) VALUE 'IINQUIRYP'.

The main program should look up the transaction type in the table, extract the program name, and make a dynamic CALL. Include ON EXCEPTION handling for programs that are not found.

Exercise 11: Error Handling Subprogram

Write a reusable error handling subprogram called ERRHANDL that: - Accepts an error severity level ('I'=Info, 'W'=Warning, 'E'=Error, 'C'=Critical) - Accepts the calling program name - Accepts a paragraph name where the error occurred - Accepts an error code and message - Writes the error to a log file with timestamp - Maintains a count of errors by severity (using persistent WORKING-STORAGE) - Returns the total error count

Exercise 12: Account Validation with RETURNING

Write a subprogram called ACCTVAL that validates a bank account number and returns the validation result using the RETURNING clause. The subprogram should: - Check that all positions are numeric - Verify the account number length - Perform a simple checksum calculation - Return 0 for valid, 4 for format error, 8 for checksum failure

Write a main program that tests several account numbers.

Solution: See exercise-solutions.cob, Exercise 12 section.

Exercise 13: CANCEL and Reinitialization

Write a program that demonstrates the difference between calling a subprogram with and without CANCEL. The subprogram should: - Maintain a running total across calls - Track the maximum value seen - Count the number of calls - Return all three statistics

The main program should: 1. Call the subprogram five times with values 10, 20, 30, 40, 50 2. Display the statistics (total=150, max=50, count=5) 3. CANCEL the subprogram 4. Call it three more times with values 5, 15, 25 5. Display the statistics (total=45, max=25, count=3)

Exercise 14: Copybook-Based Interface

Create a copybook (CUSTPARM.cpy) that defines the parameter structure for a customer lookup subprogram. Then write: 1. The subprogram CUSTLOOK that accepts a customer ID and returns customer details (name, address, phone, balance) 2. A main program that uses the same copybook and calls CUSTLOOK 3. Show how the copybook is used in both programs

Exercise 15: JCL for Multiple Subprograms

Write complete JCL to compile, link, and execute a system consisting of: - A main program (MAINPGM) - Three subprograms (SUBPGM1, SUBPGM2, SUBPGM3) - Two subprograms called statically, one called dynamically

Show both the static link step and the separate dynamic link step. Include the STEPLIB DD to make the dynamic module available at runtime.


Tier 3: Analysis and Design (Exercises 16-22)

Exercise 16: Parameter Passing Mode Selection

For each of the following scenarios, determine the most appropriate parameter passing mode (BY REFERENCE, BY CONTENT, or BY VALUE) and justify your choice:

  1. A customer name field that the subprogram reads but should never modify
  2. A running total that the subprogram updates and the caller needs to see the updated value
  3. An integer flag passed to a C function
  4. A large record structure (500 bytes) that the subprogram only reads
  5. A status code that the subprogram sets to indicate success or failure
  6. A constant value (like a tax rate) that is the same for every call
  7. A buffer that the subprogram fills with output data

Exercise 17: Static vs. Dynamic Analysis

A COBOL application consists of a main program and 15 subprograms. The main program always calls 5 of them. The other 10 are called only for specific transaction types, and on average only 3 of those 10 are needed per run.

Analyze the tradeoffs of: 1. Making all 15 calls static 2. Making all 15 calls dynamic 3. Making the 5 always-needed calls static and the 10 conditional calls dynamic

Consider: load module size, runtime performance, memory usage, deployment flexibility, and maintenance effort.

Exercise 18: Nested Program Calculator

Design and implement a calculator program using nested programs. The parent program (EX18CALC) should contain nested programs for: - CALCADD (addition) - CALCSUB (subtraction) - CALCMUL (multiplication) - CALCDIV (division with error handling) - CALCLOG (COMMON logging program)

Use GLOBAL data for the operands and result. The CALCLOG program should be COMMON so all operation programs can call it.

Solution: See exercise-solutions.cob, Exercise 18 section.

Exercise 19: Subprogram State Management

A reporting subprogram must track page numbers, line counts, and report totals across multiple calls. When the report is complete, the caller needs to reset the subprogram for the next report.

Design two solutions: 1. Using CANCEL to reset the subprogram 2. Using a "reset" operation code parameter

Discuss the advantages and disadvantages of each approach. Which would you recommend for a production system?

Exercise 20: Interface Versioning

A subprogram DATEVAL is currently in production with this interface:

       01  LS-DATE-PARMS.
           05  LS-INPUT-DATE    PIC X(10).
           05  LS-RETURN-CODE   PIC 9(02).
           05  LS-ERROR-MSG     PIC X(50).

A new requirement adds output fields for day-of-week and Julian date. Design a strategy to update the interface without breaking the 50 existing callers that use the old interface. Write the updated copybook and modified subprogram.

Exercise 21: Cross-Language Call Design

Design a COBOL program that calls a C function with the following prototype:

int calculate_hash(const char *input, int length, char *output, int out_len);

Write the COBOL CALL statement and the WORKING-STORAGE definitions for the parameters. Address issues of: - String null-termination - Integer type matching (COMP-5) - BY VALUE vs. BY REFERENCE for each parameter - Checking the return value

Exercise 22: Subprogram Dependency Analysis

Given the following call graph:

MAIN --> PROGA --> PROGD
     --> PROGB --> PROGD
              --> PROGE --> PROGF
     --> PROGC --> PROGF
  1. If PROGD has a bug, which programs are affected?
  2. If PROGF's interface changes, what must be recompiled?
  3. Draw the compilation dependency order (what must be compiled before what?)
  4. If all calls are static, how many link steps are needed?
  5. If PROGD and PROGF are dynamic, how many link steps are needed? Which modules go in which link step?

Tier 4: Advanced Challenges (Exercises 23-30)

Exercise 23: Plugin Architecture

Implement a plugin-based processing system where: - A configuration file lists available processing modules (subprogram names) - The main program reads the configuration at startup - For each input record, the main program dynamically calls each configured module in sequence - Each module can transform the data, and the modified data is passed to the next module - Include ON EXCEPTION handling for modules that fail to load

Exercise 24: Recursive Tree Processor

Write a recursive COBOL program that processes a bill-of-materials (BOM) structure. Each component can contain sub-components. The program should: - Use the RECURSIVE attribute - Use LOCAL-STORAGE for per-invocation data - Calculate the total cost of a product by recursively summing component costs - Track and display the depth of recursion - Handle circular references (component A contains B, B contains A)

Exercise 25: Subprogram Pool Manager

Write a main program that manages a pool of dynamically loaded subprograms. The manager should: - Track which subprograms are currently loaded (up to 20) - Implement a least-recently-used (LRU) policy - When the pool is full, CANCEL the least recently used subprogram before loading a new one - Provide statistics: total loads, total cancels, cache hit ratio - Use a table-driven approach with timestamps

Exercise 26: Regression Test Harness

Design and implement a test harness program that can: - Read test case definitions from a file (input parameters and expected outputs) - Dynamically call any specified subprogram - Compare actual results with expected results - Report pass/fail for each test case - Produce a summary report with counts and percentages

Exercise 27: Interface Wrapper Subprogram

A legacy subprogram OLDCALC has a complex, poorly designed interface with 12 individual parameters in a specific order. Write a wrapper subprogram NEWCALC that: - Accepts a single, well-structured group item - Maps the fields to OLDCALC's parameter list - Calls OLDCALC - Maps the results back to the new structure - Adds input validation that OLDCALC lacks - Translates OLDCALC's cryptic return codes into meaningful messages

Exercise 28: Parallel Subprogram Design

A batch processing system needs to validate 10 million records. A single validation subprogram takes 0.5 milliseconds per record (83 minutes total). Design a modular architecture that: - Splits the workload across multiple tasks - Uses a common validation subprogram - Aggregates results from all tasks - Handles the case where different tasks have different versions of the subprogram loaded - Addresses WORKING-STORAGE persistence concerns in a multi-task environment

Exercise 29: Subprogram Performance Benchmarking

Write a benchmarking program that measures the overhead of different call types. The program should: - Call a trivial subprogram (immediate GOBACK) 100,000 times using static CALL - Call the same subprogram 100,000 times using dynamic CALL (without CANCEL) - Call the same subprogram 100,000 times using dynamic CALL (with CANCEL before each call) - Use FUNCTION CURRENT-DATE or the system clock to measure elapsed time for each batch - Display the results in a comparison table

Exercise 30: Complete Modular System Design

Design a complete student grade management system using modular COBOL: - Main driver program - Student record validation subprogram - Grade calculation subprogram (weighted average of assignments, midterm, final) - Letter grade assignment subprogram (with configurable grade boundaries) - GPA calculation subprogram - Report generation subprogram - Error handling subprogram (COMMON nested program)

For each subprogram, define: - The copybook for its interface parameters - The return code values and their meanings - Whether it should be static or dynamic, and why - Whether it needs persistent WORKING-STORAGE or IS INITIAL - The JCL to compile, link, and run the complete system


Tier 5: Research and Exploration (Exercises 31-38)

Exercise 31: Object-Oriented COBOL Comparison

Research how COBOL 2002's object-oriented features (INVOKE, METHOD-ID) compare to the traditional CALL-based modular approach. Write a brief comparison covering: - When to use CALL vs. INVOKE - How method parameters differ from CALL parameters - Encapsulation differences - Practical adoption in enterprise environments

Exercise 32: COBOL and Web Services

Research how modern COBOL programs can expose subprograms as web services on IBM z/OS (using CICS, MQ, or Language Environment). How does CICS LINK differ from a standard COBOL CALL? What is the role of DFHCOMMAREA in this context?

Exercise 33: GnuCOBOL Module System

Using GnuCOBOL, experiment with dynamic module loading: 1. Compile a subprogram as a shared library (-m flag) 2. Write a main program that dynamically calls it 3. Replace the shared library with a new version without recompiling the main program 4. Document the process and any platform-specific considerations (Linux vs. Windows)

Exercise 34: Micro Focus COBOL Differences

Research how Micro Focus COBOL handles subprogram calls differently from IBM Enterprise COBOL. Specifically investigate: - The CALL convention differences - How INT and GNT modules work - The role of the Micro Focus runtime in dynamic calls - Compatibility considerations when porting between platforms

Exercise 35: COBOL and Java Interoperability

Research how IBM Enterprise COBOL can call Java methods and how Java can call COBOL programs. What infrastructure is needed? How are data types mapped? What are the performance implications?

Exercise 36: Subprogram Memory Layout

Using the IBM COBOL compiler listing (LIST option), examine the actual memory layout of: - A WORKING-STORAGE SECTION in a subprogram - A LINKAGE SECTION with multiple parameters - The parameter address list structure

Document how the compiler sets up the parameter passing mechanism at the machine level.

Exercise 37: Legacy Migration Patterns

Research common patterns used when migrating COBOL subprograms from one mainframe to another (e.g., Unisys to IBM, or mainframe to distributed). What interface compatibility issues arise? How are they resolved? Cite at least two real-world case studies.

Exercise 38: Testing Frameworks for COBOL Subprograms

Research and compare at least three testing frameworks or approaches for COBOL subprogram testing: - IBM Debug Tool / zUnit - Micro Focus Unit Testing Framework - Manual test driver approach - Any open-source alternatives

For each, describe the setup process, how tests are defined, and how results are reported. Which would you recommend for a shop with 500 COBOL subprograms?