CALL, USING and the LINKAGE SECTION
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.