Exercises — Chapter 22: CALL and Subprogram Linkage

Exercise 22.1: Your First Subprogram (Beginner)

Objective: Write a main program and a subprogram that converts temperatures between Fahrenheit and Celsius.

Requirements:

  1. Create a copybook TEMPCONV.cpy defining the interface: - Input temperature (PIC S9(5)V99 COMP-3) - Conversion direction: 'F2C' or 'C2F' (PIC X(3)) - Output temperature (PIC S9(5)V99 COMP-3) - Return code (PIC S9(4) COMP)

  2. Write the subprogram TEMPCONV that: - Accepts the interface area via LINKAGE SECTION - Performs the conversion (F to C: subtract 32, multiply by 5/9; C to F: multiply by 9/5, add 32) - Sets return code 0 for success, 8 for invalid direction

  3. Write the driver program TEMPDRVR that: - Calls TEMPCONV for 32°F, 100°C, 212°F, -40°C - Displays the results - Uses GOBACK in the subprogram, STOP RUN in the driver

Deliverables: TEMPCONV.cpy, TEMPCONV.cbl, TEMPDRVR.cbl


Exercise 22.2: Static vs. Dynamic CALL Experiment (Beginner)

Objective: Observe the behavioral differences between static and dynamic CALL.

Tasks:

  1. Write a subprogram COUNTER that: - Has a WORKING-STORAGE counter initialized to 0 - Increments the counter each time it is called - Returns the current counter value via LINKAGE SECTION

  2. Write a driver program that: - Calls COUNTER five times using a static CALL (literal name) - Displays the counter value after each call - Issues CANCEL 'COUNTER' - Calls COUNTER three more times - Displays the counter value after each call

  3. Answer these questions: - What values does the counter return on calls 1-5? - What value does the counter return on call 6 (after CANCEL)? - If the CALL is static, does CANCEL have any effect? Why or why not?


Exercise 22.3: Error-Handling Pattern (Intermediate)

Objective: Implement robust error handling for CALL statements.

Requirements:

  1. Write a main program that: - Accepts a program name from ACCEPT or hardcoded data - Dynamically calls the named program - Handles ON EXCEPTION gracefully - Logs the error and continues processing

  2. Write two subprograms: - GOODPROG: Accepts a message, displays it, returns code 0 - FAILPROG: Accepts a message, simulates an error, returns code 8

  3. The main program should call: - 'GOODPROG' — should succeed - 'BADNAME' — should trigger ON EXCEPTION (program doesn't exist) - 'FAILPROG' — should succeed but return code 8

  4. Display appropriate messages for each scenario.


Exercise 22.4: Modular Payroll System (Intermediate)

Objective: Design and implement a modular payroll calculation system using CALL.

System structure:

PAYROLL (Driver)
├── CALL 'EMPREAD'  — Read employee record
├── CALL 'PAYCALC'  — Calculate gross pay
├── CALL 'TAXCALC'  — Calculate tax withholdings
├── CALL 'DEDUCTN'  — Calculate deductions
└── CALL 'PAYSLIP'  — Generate pay slip output

Requirements:

  1. Define copybooks for: - Employee record (EMPRECP.cpy) - Pay calculation area (PAYCALP.cpy) - Standardized return code area (RETCODCP.cpy)

  2. Implement at least PAYROLL (driver), PAYCALC, and TAXCALC as working programs.

  3. PAYCALC should handle: - Regular hours (up to 40) at base rate - Overtime hours (over 40) at 1.5x rate - Return code 4 if overtime exceeds 20 hours (warning)

  4. TAXCALC should handle: - Three tax brackets: 10% up to $30,000, 22% up to $80,000, 32% above - Based on annualized gross (gross × 26 pay periods)


Exercise 22.5: Debugging CALL Problems (Advanced)

Objective: Practice diagnosing common CALL-related errors.

Each of the following code pairs has a bug. Identify the bug, explain what would happen at runtime, and write the corrected code.

Bug 1: Parameter Order

* Calling program:
CALL 'VALIDATE' USING WS-AMOUNT
                      WS-ACCOUNT-ID
                      WS-RETURN-CODE

* Called program:
LINKAGE SECTION.
01  LS-ACCOUNT-ID    PIC X(10).
01  LS-AMOUNT        PIC S9(9)V99 COMP-3.
01  LS-RETURN-CODE   PIC S9(4) COMP.
PROCEDURE DIVISION USING LS-ACCOUNT-ID
                         LS-AMOUNT
                         LS-RETURN-CODE.

Bug 2: Size Mismatch

* Calling program:
01  WS-NAME          PIC X(20).
CALL 'FMTNAME' USING WS-NAME WS-RETURN-CODE

* Called program:
LINKAGE SECTION.
01  LS-NAME          PIC X(50).
01  LS-RETURN-CODE   PIC S9(4) COMP.
PROCEDURE DIVISION USING LS-NAME LS-RETURN-CODE.
    MOVE 'JOHN JACOB JINGLEHEIMER SCHMIDT JR III' TO LS-NAME

Bug 3: STOP RUN in Subprogram

* Called program:
PROCEDURE DIVISION USING LS-DATA LS-RETURN-CODE.
    IF LS-DATA = SPACES
        MOVE 8 TO LS-RETURN-CODE
        STOP RUN
    END-IF
    PERFORM PROCESS-DATA
    STOP RUN.

Exercise 22.6: Build a Dispatch Table (Advanced)

Objective: Implement a dynamic dispatch mechanism using variable program names.

Requirements:

  1. Create a table of function codes and corresponding program names: Function Program ADD FUNCADD UPD FUNCUPD DEL FUNCDEL INQ FUNCINQ RPT FUNCRPT

  2. Write a driver program that: - Reads function codes from input (or hardcoded test data) - Looks up the program name in the dispatch table - Dynamically calls the appropriate program - Handles unknown function codes gracefully - Handles ON EXCEPTION for missing programs

  3. Write at least two of the FUNC* subprograms as stubs that display their function and return code 0.

Bonus: Add the ability to load the dispatch table from a configuration file, making the system extensible without recompilation.


Exercise 22.7: Cross-Language Calling (Advanced — GnuCOBOL)

Objective: Call a C function from a COBOL program using GnuCOBOL.

Requirements:

  1. Write a C function that calculates the square root of a number: c double calc_sqrt(double *value);

  2. Write a COBOL program that: - Defines a COMP-2 (double precision) data item - Calls the C function using CALL with BY REFERENCE - Displays the result

  3. Compile and link using GnuCOBOL: bash gcc -c sqrt_func.c cobc -x -o sqrtprog sqrtprog.cbl sqrt_func.o

  4. Document the parameter passing requirements for C interop.