In COBOL, similarly to other languages, the main program is executed. The main program can have sub-programes (subroutines, program modules).
The execution environment is set up by JCL statements. COBOL will not read datasets and other inputs directly but through JCL.
JCL can send data to the main program:
execution parameter (EXEC statement PARM parameter; LINKAGE-STORAGE SECTION and PROCEDURE DIVISION USING ...)
datasets (DD statements; ENVIRONMENT DIVISION, FILE SECTION etc.)
text-like input (SYSIN in-stream DD statement)
The main program can send variables to the called modules (CALL ... USING ...) which can receive those (LINKAGE SECTION and PROCEDURE DIVISION USING ...).
Although the PROCEDURE DIVISION USING ... can include the PARM along with received arguments from a caller module, best practice is to let only the PARM into the main program, and let only the arguments from the main program into a submodule (e.g. the PARM is loaded into a variable which can be sent to the submodule).
FIGURE OF JCL AND MODULE CONNECTIONS:
A modul starts with the IDENTIFICATION DIVISION and closes with the END PROGRAM. In older COBOL the EXIT PROGRAM was used instead of the END PROGRAM.
The flow must reach a STOP RUN in the main program, and a GOBACK in a submodul.
The JCL EXEC statement optionally can contain the PARM parameter. This parameter is the execution parameter, and COBOL can receive it as a variable in the USING clause of the PROCEDURE DIVISION.
As a pre-condition, the variable receiving the PARM must be defined in the LINKAGE SECTION.
The maximum length of the PARM is 100 characters (although the JCL format does not let it be as long), it can contain a value or multiple values in a composite form. In the latter case, the PARM must be delimited as a second step into several other variables.
EXAMPLE FOR SYNTAX OF RECEIVING PARM:
EXAMPLE FOR RECEIVING AND PARSING PARM, UNSTRING:
EXAMPLE FOR RECEIVING AND PARSING PARM, INSPECT:
A program can start a subroutine by using the CALL command where the USING clause defines the parameters to be sent.
A subroutine can receive data in the LINKAGE SECTION under DATA DIVISION, can address the received data in PROCEDURE DIVISION with the USING clause, and gives back the execution to the caller with the GOBACK (modern COBOL) or the EXIT PROGRAM (old COBOL) instruction.
On receiver side, the order of parameters after the USING clause must follow the order of the parameters in caller side after the USING clause.
The STOP RUN must not be used in a subroutine.
The main program and their subroutines (sub-modules) must be placed into the LOADLIB dataset which must be defined in the JCL. The reason is that the modules are not refrenced by their full qualifier path but by their dataset (PDS member) names.
The parameters can be sent in two ways:
by their reference or memory address (default; the sender will send pointers; in case the parameter value changes in the subroutine, the original variables will change accordingly)
by their content (the subroutine will receive a temporal copy of the parameters on different memory addresses, upon value change they change, the original variables will not change)
In older COBOL all parameters had the same transfer mode. The BY ... was placed before the USING clause.
In modern COBOL, the mode can be defined per parameter, the BY ... clause is placed after the USING, before the corresponding parameter, per parameter. A BY VALUE or BY REFERENCE is applied to all following parameters until the compiler finds a new BY ... clause.
While variables defined under the WORKING-STORAGE section are initialized upon program start, variables defined under the LINKAGE SECTION in the caller side and sent BY VALUE to a subroutine are initialized and exist only upon the CALL execution.
When a submodul is called, its WS variables are initialized at the first run. In case of other CALLs, since the WS defines static data, the submodul starts will the old data held in the WS. If this behaviour is unaccepted, on the caller side, before the CALL sentence use the CANCEL instruction forces the JES to delete the cached module from the memory and re-initialize the module.
Because after CANCEL upon the CALL the module must be loaded from the LOADLIB, it makes calling the module slower.
Use the CANCEL when
at all calls of the module the module must be clean
the module is too big in the memory (typically when handling JSON/XML)
a submodul throws an error and re-starting it in original form is advised
Do not use CANCEL when
the submodule needs its actual WS data (e.g. counters, cache, session-data)
the submodule is thread-safe
the submodule is called many times rapidly
From strategic point of view, unless the memory consumption matters, instead of using CANCEL before the CALL it is better to:
give an initial value to the interesting variables as a first step in the PROCEDURE DIVISION, and not to use the VALUE clause on their definition
put the interesting variable definition to the LOCAL-STORAGE instead of the WORKING-STORAGE
EXAMPLE FOR CALLING SUBROUTINES:
EXAMPLE FOR MAIN PROGRAM:
EXAMPLE FOR SUBROUTINE:
EXAMPLE FOR THE CANCEL DILEMMA:
A parameter can be:
literal
variable
structure
pointer
Repeatedly, the order of the sent parameters and the order of the received parameters must be the same between the caller and the receiver programs.
It is important to define the variables or structures at the same way on both sides. Their names can be different per side.
In case the variable size on receiver side is smaller, silent truncate will appear.
In case the variable size on receiver side is larger, the rest of the length will be filled with zeros or spaces, the flow goes on normally.
In case the corresponding parameter types are different, COBOL tries to convert; in case of any errors a runtime error (e.g. from numeric to alphabet, S0C7, numeric conversion error) appears.
Literals can be sent only in BY CONTENT mode.
The pointer parameter appears in modern COBOL programming.
EXAMPLE FOR CALLING SUBROUTINES WITH POINTER:
Level-88 definitions can not be sent as parameters, only the field itself. The level-88 lines must be re-defined on receiver side if necessary.
The caller side can receive data through sent parameters by reference when the original variables in the caller program will change in the called subroutine.
It is happening via using the RETURNING formula:
the caller does not send parameters
the submodule has no LINKAGE SECTION
the submodule returns one value (numeric, alphanumeric, pointer, or a whole structure)
This call represents a one-directional process.
The caller uses the CALL RETURNING formula.
The submodule uses the PROCEDURE DIVISION RETURNING formula.
The submodule name in the CALL formula is inside single apostroph (old COBOL) but accepts double apostroph (modern COBOL) as well.
EXAMPLE FOR CALL RETURNING:
See more under the COBOL FUNCTIONS.