COBOL Subprograms (original) (raw)

Comparison with Paragraphs

It is assumed that the reader is already familiar with fact that, within the PROCEDURE DIVISION of a COBOL (sub)program, each paragraph is a unit of executable code that is "callable" ---via the PERFORM verb--- from within that (sub)program. In effect, all the paragraphs in (the PROCEDURE DIVISION of) a COBOL (sub)program are parameter-less "routines" having access to the same data, namely, all those data items declared in the DATA DIVISION of that (sub)program.

In contrast, a COBOL subprogram is a separate compilation unit; that is, it belongs in a file by itself and is compiled independently of its clients (i.e., other COBOL (sub)programs that call it). In order to produce an executable file, the object code files produced by the separate compilations of a main program and any subprograms it calls (directly or indirectly) must be linked. (You may wish to read instructions on how to compile, link, and execute COBOL programs in a VMS environment.)

Because the data declared in one compilation unit is not visible in any other (and hence, subprograms cannot communicate with their callers through the mechanism of shared data, as do the paragraphs within a compilation unit), subprograms communicate with their callers through the mechanism of argument-passing. (What are called "parameters" in some languages are referred to as "arguments" in others, including COBOL and FORTRAN.)

Comparision with Programs

The syntactic form of a COBOL subprogram is nearly identical to that of a COBOL program; in particular, it has the same four divisions:IDENTIFICATION, ENVIRONMENT, DATA, andPROCEDURE.

In a subprogram, however, the DATA DIVISIONincludes ---in addition to the FILE and WORKING-STORAGE sections--- a LINKAGE section, where the subprogram's formal arguments are described (via PICTURE clauses, etc.)

Another syntactic difference is that, in a subprogram, the PROCEDURE DIVISION header includes a USING clause that lists the names of the formal arguments and, in so doing, indicates the order in which the corresponding actual argumentsmust be listed by the caller in making a call to the subprogram.

Finally, to terminate execution of a subprogram (and return control to its caller), the statement EXIT PROGRAM is used, rather thanSTOP RUN. The latter statement will, as usual, have the effect of terminating execution of the whole program; in other words, if it is executed within a subprogram, control will not return to its caller.

Calling and Passing Arguments to a Subprogram

A statement used for calling a subprogram has the syntax

CALL USING

A subprogram's name is that which is specified in its PROGRAM-IDparagraph. The argument list is a sequence of data-names (or literals), each (optionally) preceded by one of the two phrasesBY CONTENT or BY REFERENCE, which specifies the mode under which the argument is passed. The former is analogous to a non-VAR parameter in Pascal, or to an in parameter in Ada, or to all parameters in C and Java (which give you no choice but to "pass by value"). The latter is analogous to a VAR parameter in Pascal or to an in outparameter in Ada. The default is BY REFERENCE.

For example, the following invokes the subprogram Junk and passes to it four arguments, the first and last BY REFERENCEand the middle two BY CONTENT:

          CALL 'Junk' USING
             BY REFERENCE Garbage
             BY CONTENT   Refuse, 37
             BY REFERENCE Rubbish 

For another example, note that the PROGRAM-ID of this subprogramis Plus-One; then note that, to call it, another (sub)program would (most likely) use a statement of the form

CALL 'Plus-One' USING

as is illustrated by this calling program. (The need for quotes surrounding the name brings up a rather interesting issue, which is discussed below.)

Miscellaneous Facts

CANCEL

a calling program forces the local variables of the indicated subprogram to be "refreshed". Thus, if a calling (sub)program requires that the data items in a subprogram be in a refreshed state each time it invokes that subprogram, it should precede each CALL to that subprogram with a CANCEL statement.
Another way to ensure that all data items local to a subprogram are refreshed each time it is called is to insert the phrase
IS INITIAL PROGRAM
(both
IS
and
PROGRAM
are optional) immediately after the subprogram's name in its
PROGRAM-ID
paragraph. For example,
PROGRAM-ID. Stupid-Subprogram IS INITIAL PROGRAM.

CALL USING

Two points are of interest. The first is that the subprogram name_is evaluated_! That is, to call the subprogram Junk, you would (usually) write

CALL 'Junk' USING ....

Notice the single quotes surrounding the subprogram name. If you were instead to write

CALL Junk USING ....

the subprogram called would be the one whose name is the current value of the data item Junk!!! For example, if Junk had been declared using the picture clause PIC X(7) and had the value "Destroy" at the time the above call were made, then the call would be to the subprogram Destroy! If, later in execution, the value of Junk had been modified to, say, "MrSpock", then execution of the sameCALL statement would result in the invocation of the subprogram having that name!
This is an extremely powerful and dangerous feature, and one that you would expect to find in a language such as LISP that readily supports AI applications, but not in a data processing language!
The second interesting point is that it is the caller, rather than the subprogram, which determines the mode under which each argument is passed. (Did you notice this during the discussion of theCALL verb above?) In Pascal and Ada, for example, the mode of each formal parameter is specified in the definition of the subprogram. That is, the subprogram determines the mode of parameter passing for each parameter. By giving control of this to the caller, it makes it impossible to describe a subprogram's effects in terms of a single pre- and post-condition pair. Instead, (in the worst case) you'd need a distinct pair of conditions for each of the possible 2k choices of passing the arguments, where k is the # of arguments.

Reference

For a much more complete description of subprograms (and nested programs) in COBOL, see Chapter 23 of Comprehensive COBOL.