MODULE 11 · SUBPROGRAMS AND COPYBOOKS · 4/8

BY CONTENT and BY VALUE

14 min30 XPExercise

BY REFERENCE gives the called program your actual field. That is what you want for results, but it also means the subprogram can change anything you pass, deliberately or by accident. COBOL has two other passing modes.

BY CONTENT: pass a copy

With BY CONTENT, the system copies your item into a temporary area and passes the address of the copy. The subprogram sees the same bytes and can even change them, but when it returns, your field is untouched.

A mode applies to every item that follows it until you name another one:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. MODEDEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-A             PIC X(4) VALUE "AAAA".
       01  WS-B             PIC X(4) VALUE "BBBB".
       01  WS-C             PIC X(4) VALUE "CCCC".
       PROCEDURE DIVISION.
           CALL "CLOBBER" USING BY REFERENCE WS-A
                                BY CONTENT   WS-B WS-C
           DISPLAY WS-A " " WS-B " " WS-C
           CALL "CLOBBER" USING BY CONTENT "LIT1" "LIT2"
                                BY REFERENCE WS-C
           DISPLAY WS-A " " WS-B " " WS-C
           STOP RUN.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CLOBBER.
       DATA DIVISION.
       LINKAGE SECTION.
       01  LS-1             PIC X(4).
       01  LS-2             PIC X(4).
       01  LS-3             PIC X(4).
       PROCEDURE DIVISION USING LS-1 LS-2 LS-3.
           DISPLAY "GOT " LS-1 " " LS-2 " " LS-3
           MOVE "1111" TO LS-1
           MOVE "2222" TO LS-2
           MOVE "3333" TO LS-3
           GOBACK.
       END PROGRAM CLOBBER.
       END PROGRAM MODEDEMO.
GOT AAAA BBBB CCCC
1111 BBBB CCCC
GOT LIT1 LIT2 CCCC
1111 BBBB 3333

CLOBBER overwrote all three parameters both times, but only the items passed BY REFERENCE (WS-A on the first call, WS-C on the second) changed in the caller.

Notice the second call passes literals. You can't pass a literal by reference on IBM compilers, because there is no field for the subprogram to write into; pass literals BY CONTENT.

When to use it:

  • For input-only parameters to a routine you don't own, when your program relies on the value afterwards.
  • For literals and constants.
  • When a routine is known to use a parameter as scratch space, as some old utilities do.

The called program doesn't know or care which mode the caller used; its LINKAGE SECTION looks the same either way.

BY VALUE: for C and system services

BY VALUE puts the value itself, not an address, into the argument list. That is how C functions and many operating-system services expect arguments, so BY VALUE is what you use to call them. Binary fields (COMP-5) match C's integer types, and RETURNING receives the function's return value:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CDEMO.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  WS-CH            PIC S9(9) COMP-5 VALUE 97.
       01  WS-UP            PIC S9(9) COMP-5.
       01  WS-OUT           PIC 999.
       PROCEDURE DIVISION.
           CALL "toupper" USING BY VALUE WS-CH RETURNING WS-UP
           MOVE WS-UP TO WS-OUT
           DISPLAY "TOUPPER(97) = " WS-OUT
           STOP RUN.
TOUPPER(97) = 065

That calls the C library's toupper on the character code for a and gets back 65, the code for A. Between two COBOL programs, stick to BY REFERENCE and BY CONTENT. GnuCOBOL even warns that BY VALUE in a COBOL program's PROCEDURE DIVISION USING is unfinished.

On the job

On z/OS you'll see BY VALUE in calls to Language Environment callable services (the CEE... routines) and to C or Java code, and BY CONTENT wherever a program passes a literal such as a message number to a shared error routine.

Your task

The customer team wants to spot duplicate customers keyed with different spelling. The shared routine MATCHKEY (already in the starter as a nested program; don't change it) builds a key from a name: letters only, upper case.

       LINKAGE SECTION.
       01  LS-NAME          PIC X(30).
       01  LS-KEY           PIC X(30).
       PROCEDURE DIVISION USING LS-NAME LS-KEY.

Read its code: it upper-cases LS-NAME in place to do its work.

In NAMEKEYS, add the CALL so each name is printed exactly as it was typed, followed by its key. For the input

03
Mary O'Neill
mary oneill
Jean-Luc Picard

the output is

Mary O'Neill                   -> MARYONEILL
mary oneill                    -> MARYONEILL
Jean-Luc Picard                -> JEANLUCPICARD

Protect the name by choosing the right passing mode, not by copying it to another field first.

Check your understanding

1. In CALL "SUB" USING BY CONTENT WS-A WS-B BY REFERENCE WS-C, how is WS-B passed?
2. A subprogram moves a new value into a parameter the caller passed BY CONTENT. What does the caller see?
3. What is BY VALUE mainly used for?
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.