MODULE 11 · SUBPROGRAMS AND COPYBOOKS · 2/8

CALL, USING and the LINKAGE SECTION

15 min30 XPExercise

A CALL names the program to run and, with USING, the data items to hand it:

           CALL "CALCVAT" USING WS-NET WS-CODE WS-VAT WS-GROSS

On the other side, the called program declares matching items in its LINKAGE SECTION and lists them, in the same order, on its PROCEDURE DIVISION header:

       LINKAGE SECTION.
       01  LS-NET           PIC 9(7)V99.
       01  LS-CODE          PIC X.
       01  LS-VAT           PIC 9(7)V99.
       01  LS-GROSS         PIC 9(7)V99.
       PROCEDURE DIVISION USING LS-NET LS-CODE LS-VAT LS-GROSS.

BY REFERENCE is the default

Unless you say otherwise, every parameter is passed BY REFERENCE: the caller hands over the address of its field, not a copy of the value. A LINKAGE SECTION item owns no storage at all; it is a template laid over the caller's memory. So when the subprogram moves a value into LS-VAT, it lands in the caller's WS-VAT. That is how a subprogram returns results. CALL X USING A B and CALL X USING BY REFERENCE A B mean the same thing.

Matching is by position, not by name

The names on each side are irrelevant. The first item in the CALL becomes the first item in PROCEDURE DIVISION USING, and so on. Swap two parameters and the subprogram silently works on the wrong data:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. ORDERDEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-PRICE         PIC 9(3)V99 VALUE 20.00.
       01  WS-QTY           PIC 9(3)V99 VALUE 3.
       01  WS-TOTAL         PIC 9(5)V99.
       PROCEDURE DIVISION.
           CALL "LINETOT" USING WS-QTY WS-PRICE WS-TOTAL
           DISPLAY "TOTAL: " WS-TOTAL
           STOP RUN.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. LINETOT.
       DATA DIVISION.
       LINKAGE SECTION.
       01  LS-PRICE         PIC 9(3)V99.
       01  LS-QTY           PIC 9(3)V99.
       01  LS-TOTAL         PIC 9(5)V99.
       PROCEDURE DIVISION USING LS-PRICE LS-QTY LS-TOTAL.
           DISPLAY "PRICE: " LS-PRICE
           COMPUTE LS-TOTAL = LS-PRICE * LS-QTY
           GOBACK.
       END PROGRAM LINETOT.
       END PROGRAM ORDERDEMO.
PRICE: 003.00
TOTAL: 00060.00

Here the answer happens to be right, because multiplication doesn't care about order, but LINETOT believes the price is 3.00. Any rule that uses the price alone (a discount above 10.00, say) would now be wrong.

Sizes must match too

Nothing checks that the caller's field and the LINKAGE item are the same size. If the subprogram declares a longer item, it reads and writes past the end of the caller's field into whatever comes next:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SIZEDEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-FIELDS.
           05  WS-CODE      PIC X(5) VALUE "AB123".
           05  WS-NAME      PIC X(10) VALUE "JONES".
       PROCEDURE DIVISION.
           CALL "SHOWCODE" USING WS-CODE
           DISPLAY "NAME NOW: " WS-NAME
           STOP RUN.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SHOWCODE.
       DATA DIVISION.
       LINKAGE SECTION.
       01  LS-CODE          PIC X(10).
       PROCEDURE DIVISION USING LS-CODE.
           DISPLAY "CODE: [" LS-CODE "]"
           MOVE ALL "*" TO LS-CODE
           GOBACK.
       END PROGRAM SHOWCODE.
       END PROGRAM SIZEDEMO.
CODE: [AB123JONES]
NAME NOW: *****

SHOWCODE never mentioned WS-NAME, yet it overwrote half of it. This is exactly the kind of bug that surfaces months later as corrupted data, and the reason shops put parameter layouts in copybooks.

Returning to the caller

GOBACK ends the subprogram and resumes the caller at the statement after the CALL. The caller's fields now hold whatever the subprogram put there.

On the job

A shared routine's parameter list is a contract. Before calling one, open its source or its interface copybook and read the LINKAGE SECTION: order, pictures, which fields are input and which are output. Never guess from the name.

Your task

The finance team already has a subprogram, CALCVAT, that works out Irish VAT. Its interface:

       LINKAGE SECTION.
       01  LS-NET           PIC 9(7)V99.
       01  LS-CODE          PIC X.
       01  LS-VAT           PIC 9(7)V99.
       01  LS-GROSS         PIC 9(7)V99.
       PROCEDURE DIVISION USING LS-NET LS-CODE LS-VAT LS-GROSS.

LS-NET and LS-CODE are inputs (S standard 23%, R reduced 13.5%, Z zero-rated). It fills in LS-VAT (rounded) and LS-GROSS.

The starter reads a count, then that many invoice lines of 9 digits of net amount (two implied decimals) followed by the VAT code, and prints them. It never calls CALCVAT, so VAT and gross come out as zero. Add the CALL so that the input

03
000010000S
000025050R
000001999Z

prints

S NET     100.00 VAT      23.00 GROSS     123.00
R NET     250.50 VAT      33.82 GROSS     284.32
Z NET      19.99 VAT       0.00 GROSS      19.99
TOTAL GROSS      427.31

Don't calculate VAT yourself: the rates belong to CALCVAT.

fixed format
Run your program to see its output here. The first visible test's input and datasets are used.
Submit to grade your program against every test.