Exercises — Chapter 23: Parameter Passing Patterns

Exercise 23.1: BY REFERENCE vs. BY CONTENT Experiment (Beginner)

Objective: Observe the difference between BY REFERENCE and BY CONTENT through direct experimentation.

Tasks:

  1. Write a subprogram MODIFIER that: - Receives two parameters: LS-DATA (PIC X(20)) and LS-RC (PIC S9(4) COMP) - Moves 'MODIFIED BY SUBPROG' to LS-DATA - Moves 0 to LS-RC - Returns via GOBACK

  2. Write a driver program that: - Sets WS-DATA to 'ORIGINAL VALUE' - Displays WS-DATA - Calls MODIFIER with WS-DATA passed BY REFERENCE - Displays WS-DATA (what do you expect?) - Resets WS-DATA to 'ORIGINAL VALUE' - Calls MODIFIER with WS-DATA passed BY CONTENT - Displays WS-DATA (what do you expect?)

  3. Document your observations. Which call preserved the caller's data?


Exercise 23.2: Return Code Standard (Beginner)

Objective: Implement and use a standardized return code convention.

Requirements:

  1. Create a copybook RETCODCP.cpy with: - Return code field (PIC S9(4) COMP) - Level 88 names for SUCCESS (0), WARNING (4), ERROR (8), SEVERE (12), FATAL (16) - Level 88 names for OK (0 THRU 4) and FAILED (8 THRU 16)

  2. Write a subprogram AGECHK that validates a person's age: - Input: age (PIC 9(3)) - Returns 0 if age is 18-65 (standard) - Returns 4 if age is 16-17 or 66-99 (warning — needs review) - Returns 8 if age < 0 or > 150 (error — invalid) - Returns 12 if age is non-numeric (severe — bad data)

  3. Write a driver that tests ages: 25, 17, 75, 0, 200, and displays the return code and a message for each.


Exercise 23.3: Error Structure Implementation (Intermediate)

Objective: Design and use a comprehensive error communication structure.

Requirements:

  1. Create an error structure copybook ERRSTRCP.cpy containing: - Program ID (PIC X(8)) - Error code (PIC X(8)) - Short message (PIC X(40)) - Long message (PIC X(200)) - Field name (PIC X(30)) - Field value (PIC X(50)) - Timestamp (PIC X(26))

  2. Write a subprogram ADDRVAL (address validator) that: - Receives an address structure (street, city, state, zip) - Validates each field:

    • Street: not blank, max 40 chars
    • City: not blank, max 30 chars
    • State: must be a valid 2-letter state code (at least check for 5 states)
    • ZIP: must be 5 digits or 5+4 format (NNNNN or NNNNN-NNNN)
    • Populates the error structure for the FIRST validation failure
    • Returns appropriate return code
  3. Test with both valid and invalid addresses.


Exercise 23.4: COMMAREA Pattern (Intermediate)

Objective: Implement a communication area pattern for a multi-stage processing pipeline.

Scenario: A student registration system with three stages:

REGISTER (Driver)
├── CALL 'REGVALID' — Validate student data
├── CALL 'REGFEE'   — Calculate fees
└── CALL 'REGENRL'  — Create enrollment record

Requirements:

  1. Design a COMMAREA copybook REGCOMCP.cpy containing: - Function code (which stage) - Student data (ID, name, major, GPA, credits) - Fee calculation results (tuition, fees, total) - Enrollment status - Return code and error information

  2. Implement REGISTER (driver) and at least REGVALID: - REGVALID checks: student ID format (9 digits), GPA range (0.0-4.0), credits range (0-200) - Return code 4 if GPA < 2.0 (academic probation warning) - Return code 8 for invalid data

  3. Test with valid and invalid student data.


Exercise 23.5: Mixed Parameter Modes (Intermediate)

Objective: Practice using different passing modes on a single CALL.

Requirements:

Write a subprogram AMTFMT (amount formatter) with these parameters: 1. BY CONTENT: Input amount (PIC S9(9)V99 COMP-3) — protected input 2. BY CONTENT: Format code (PIC X(3)) — 'USD', 'EUR', 'PCT' 3. BY REFERENCE: Output string (PIC X(20)) — formatted result 4. BY REFERENCE: Return code (PIC S9(4) COMP) — status

Formatting rules: - 'USD': $Z,ZZZ,ZZ9.99 with leading dollar sign - 'EUR': Z,ZZZ,ZZ9.99€ with trailing euro symbol - 'PCT': ZZ9.99% with trailing percent

Test with amounts: 1234567.89, 0.50, -500.00, 999999999.99


Exercise 23.6: Optional Parameters with OMITTED (Advanced)

Objective: Implement a subprogram that handles optional parameters gracefully.

Requirements:

Write a logging subprogram LOGENTRY that accepts: 1. Log message (required) — PIC X(200) 2. Log level (optional) — PIC X(5), defaults to 'INFO' 3. Module name (optional) — PIC X(8), defaults to 'UNKNOWN' 4. Timestamp (optional) — PIC X(26), defaults to CURRENT-DATE 5. Return code (required) — PIC S9(4) COMP

The subprogram should: - Check ADDRESS OF for each optional parameter - Use defaults when parameters are OMITTED - Format and display the log entry

Write a driver that calls LOGENTRY in four ways:

* All parameters provided
CALL 'LOGENTRY' USING WS-MSG WS-LEVEL WS-MODULE
                      WS-TIMESTAMP WS-RC

* Only level omitted (use default INFO)
CALL 'LOGENTRY' USING WS-MSG OMITTED WS-MODULE
                      WS-TIMESTAMP WS-RC

* Level, module, and timestamp all omitted
CALL 'LOGENTRY' USING WS-MSG OMITTED OMITTED
                      OMITTED WS-RC

* Only message and return code
CALL 'LOGENTRY' USING WS-MSG OMITTED OMITTED
                      OMITTED WS-RC

Exercise 23.7: C Interop with BY VALUE (Advanced — GnuCOBOL)

Objective: Practice BY VALUE parameter passing for cross-language interoperability.

Requirements:

  1. Write a C function: c int compute_checksum(char *data, int length); That computes a simple checksum: sum of all byte values modulo 256.

  2. Write a COBOL program that: - Defines a data buffer (PIC X(50)) - Passes the buffer BY REFERENCE and its length BY VALUE - Captures the checksum via RETURNING - Displays the result

  3. Compile and link with GnuCOBOL: bash gcc -c checksum.c cobc -x -o checkprog checkprog.cbl checksum.o

  4. Compare the COBOL result with a manual calculation for a known input string.


Exercise 23.8: Return Code Propagation (Advanced)

Objective: Implement proper return code propagation through a multi-level call chain.

Scenario: A three-level call chain:

MAINPROG → LEVEL1 → LEVEL2

Requirements:

  1. LEVEL2 subprogram: - Receives a number (PIC 9(5)) and return code - Returns 0 if number is 1-50000 - Returns 4 if number is 50001-99999 - Returns 8 if number is 0

  2. LEVEL1 subprogram: - Receives an array of 5 numbers and a return code - Calls LEVEL2 for each number - Tracks the maximum (highest-severity) return code - Returns the maximum return code

  3. MAINPROG: - Calls LEVEL1 with test arrays - Sets RETURN-CODE special register to the maximum - Tests with: [100, 200, 300, 400, 500] (expect RC=0) - Tests with: [100, 60000, 300, 0, 500] (expect RC=8)

  4. Verify that the highest-severity return code propagates correctly from LEVEL2 through LEVEL1 to MAINPROG.