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:
-
Create a copybook
TEMPCONV.cpydefining 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) -
Write the subprogram
TEMPCONVthat: - 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 -
Write the driver program
TEMPDRVRthat: - 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:
-
Write a subprogram
COUNTERthat: - Has a WORKING-STORAGE counter initialized to 0 - Increments the counter each time it is called - Returns the current counter value via LINKAGE SECTION -
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
-
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:
-
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
-
Write two subprograms: -
GOODPROG: Accepts a message, displays it, returns code 0 -FAILPROG: Accepts a message, simulates an error, returns code 8 -
The main program should call: - 'GOODPROG' — should succeed - 'BADNAME' — should trigger ON EXCEPTION (program doesn't exist) - 'FAILPROG' — should succeed but return code 8
-
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:
-
Define copybooks for: - Employee record (EMPRECP.cpy) - Pay calculation area (PAYCALP.cpy) - Standardized return code area (RETCODCP.cpy)
-
Implement at least PAYROLL (driver), PAYCALC, and TAXCALC as working programs.
-
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)
-
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:
-
Create a table of function codes and corresponding program names:
Function Program ADD FUNCADD UPD FUNCUPD DEL FUNCDEL INQ FUNCINQ RPT FUNCRPT -
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
-
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:
-
Write a C function that calculates the square root of a number:
c double calc_sqrt(double *value); -
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
-
Compile and link using GnuCOBOL:
bash gcc -c sqrt_func.c cobc -x -o sqrtprog sqrtprog.cbl sqrt_func.o -
Document the parameter passing requirements for C interop.