@comment *********************************************************************
@comment ** 11. Sub-Programming                                              **
@comment *********************************************************************
@newchapter{Sub-Programming}
@menu
* Subprogram Types.
* Independent vs Contained vs Nested Subprograms.
* Alternate Entry Points.
* Dynamic vs Static Subprograms.
* Subprogram Execution Flow.
@detailmenu
* Subroutine Execution Flow.
* User-Defined Function Execution Flow.
@end detailmenu
* Sharing Data Between Calling and Called Programs.
@detailmenu
* Subprogram Arguments.
* Calling Program Considerations.
* Called Program Considerations.
* GLOBAL Data Items.
* EXTERNAL Data Items.
@end detailmenu
* Recursive Subprograms.
* Combining GnuCOBOL and C Programs.
@detailmenu
* GnuCOBOL Run-Time Library Requirements.
* String Allocation Differences Between GnuCOBOL and C.
* Matching C Data Types with GnuCOBOL USAGE's.
* GnuCOBOL Main Programs CALLing C Subprograms.
* C Main Programs Calling GnuCOBOL Subprograms.
@end detailmenu
@end menu
@comment *********************************************************************
@comment ** 11.1 Subprogram Types                                           **
@comment *********************************************************************
@newsection{Subprogram Types}

Simply stated, a
@define{Subprogram} is a program that is invoked by another program; the subprogram performs whatever its designed operations are and --- when complete --- typically returns control back to the program that invoked it.  There are two different types of subprograms supported by GnuCOBOL, subroutines and user-defined functions.  The distinction between these two subprogram types lies in the manner in which they are executed.

When program @i{A} invokes subprogram @i{B} as a
@define{Subroutine}, it does so using a special statement dedicated to that function (the @statementref{CALL}, just as if @i{B} were one of the built-in system subroutines.

When program @i{A} invokes program @i{B} as a
@define{User-Defined Function}, it does so in a manner identical to how @i{B} would have been invoked had it been one of the many built-in intrinsic functions.

In either instance, program @i{A} is referred to as the
@define{Calling Program} while program @i{B} is known as the
@define{Called Program}.  GnuCOBOL programs may be a calling program, a called program or both.

A program written in the C programming language may serve as either the calling or called program too.  A called program may act as a calling program to another called program.  When a calling program does not serve as a called program to any program, that calling program is known as a
@define{Main Program}.

Both subroutines and user-defined functions may return a value.  The value they return must be an integer in the range -2147483648 to +2147483647.  This value will be available in the
@registerrefalt{RETURN-CODE,Special Registers} and also as the value of the data item specified on the @syntaxrefalt{RETURNING,CALL} clause of a subroutine's @code{CALL}.
@comment *********************************************************************
@comment ** 11.2 Independent vs Contained vs Nested Subprograms              **
@comment *********************************************************************
@newsection{Independent vs Contained vs Nested Subprograms}

Subprograms (either subroutines or user-defined functions) can be implemented in three different ways.
@table @asis

@item @itemdfn{Independent Subprograms}
These are subprograms that are coded as the only COBOL program in their @topic{Compilation Unit}.

@item @itemdfn{Contained Subprograms}
These are subprograms which occur in the same Compilation Unit as a main program and/or other subprograms.  Each contained subprogram is separated from the next via an @code{END PROGRAM} marker line.  As an example@dots{}

@example
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB1.
@dots{}
END PROGRAM SUB1.
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB2.
@dots{}
END PROGRAM SUB2.
@end example

Program source code may be concatenated as shown here, provided an @code{END PROGRAM} marker naming the @code{PROGRAM-ID} of the just-completed program is used to separate one program from another.

There's no reason that user-defined functions cannot be included too --- they'll just have @code{FUNCTION-ID}s and will be ended by @code{END FUNCTION} markers.

The last program in any GnuCOBOL source file need not have an @code{END} marker.

When multiple programs occur in a source file, it is assumed that the programs are related to one another in that they will be @code{CALL}ed or executed as functions from the others.

@item @itemdfn{Nested Subprograms}
It is also possible to create source files where GnuCOBOL programs are nested inside each other.  Take for example these four GnuCOBOL programs:

@example
IDENTIFICATION DIVISION.
PROGRAM-ID. PROG1.
@dots{}
IDENTIFICATION DIVISION.
PROGRAM-ID. PROG2.
@dots{}
IDENTIFICATION DIVISION.
PROGRAM-ID. PROG3.
@dots{}
END PROGRAM PROG3.
END PROGRAM PROG2.
IDENTIFICATION DIVISION.
PROGRAM-ID. PROG4.
@dots{}
END PROGRAM PROG4.
END PROGRAM PROG1.
@end example

Here we see that @code{PROG2} is nested inside of @code{PROG1} because there is no @code{END PROGRAM} marker separating them.  This means that data items or files defined within @code{PROG1} can be used within @code{PROG2} simply by attaching the @syntaxref{GLOBAL} attribute to them back in @code{PROG1} when they are defined.

Similarly, since there is no @code{END PROGRAM} marker separating @code{PROG3} from @code{PROG2}, it is possible for @code{PROG3} to access @code{GLOBAL} files and data items defined within @code{PROG2}.  Since @code{PROG2} is nested within @code{PROG1}, any @code{GLOBAL} resources defined within @code{PROG1} will be available to @code{PROG3} as well.

The two @code{END PROGRAM} markers for @code{PROG3} and @code{PROG2} (note their sequence) mean that PROG4 is nested within @code{PROG1} only.  It will not have access to any @code{GLOBAL} resources defined within either @code{PROG2} or @code{PROG3}.

The @code{END PROGRAM PROG1.} marker, since it is the last line in the source file, is entirely optional.
@end table
@comment *********************************************************************
@comment ** 11.3 Alternate Entry Points                                      **
@comment *********************************************************************
@newsection{Alternate Entry Points}

Any subroutine may have multiple entry-points defined within it.  This means the subroutine could be called either via a @code{CALL '@var{program-id}'} or a @code{CALL '@var{entry-point}'} statement.  There may be any number of alternate entry-points defined within a subroutine.

Alternate entry-points provide multiple ways in which the same subroutine may be called; presumably, each entry-point will provide some different functionality to the calling program.  For example, if you wished to write a subroutine that manipulates "student" records in a database, you might have the primary entry-point name retrieve a student record from the database, while the alternate entry points @code{Add-Student}, @code{Update-Student} and @code{Delete-Student} could provide the alternate functions implied by their entry-point names.

The alternative to using multiple entry points in your subroutine, by the way, would be to include an additional argument to the primary (and only) entry point of the subroutine; this new argument might be named @code{STUDENT-FUNCTION} and might have values of @samp{FETCH}, @samp{ADD}, @samp{UPDATE} or @samp{DELETE}.

The primary entry-point for any subroutine is always the first executable statement following any @syntaxref{DECLARATIVES} in the procedure division.  The name of that entry-point (the name that will be called) is the subroutine's @syntaxrefalt{PROGRAM-ID,IDENTIFICATION DIVISION}.

An alternate entry point is added to a subroutine using the @statementref{ENTRY}.

When an alternate entry-point is called, execution within the subroutine will begin at the first executable statement following the @statement{ENTRY}.
@comment *********************************************************************
@comment ** 11.4 Dynamic vs Static Subprograms                               **
@comment *********************************************************************
@newsection{Dynamic vs Static Subprograms}

Any subprogram may be either statically or dynamically loaded into memory.

A
@define{Static Subprogram} is one which was in the same @topic{Compilation Unit} as the other program(s) which call it, therefore meaning that its executable object code is part of the same executable file as its calling program.  The static subprogram was therefore loaded into memory as part of and at the same time as the calling program.

A
@define{Dynamic Subprogram} is one whose executable object code exists as an executable file separate from that containing the calling program; these two programs were therefore each compiled in their own separate @topic{Compilation Group}.  Dynamic subprograms are located and loaded into memory the first time they are executed.  Dynamic subprograms may be unloaded from memory via the @statementref{CANCEL}, if desired.

GnuCOBOL subprograms may be created as either static or dynamic subprograms, as desired by the programmer.

To demonstrate, assume that a GnuCOBOL Main Program (whose code resides in the file @file{M.cbl}) will be calling three subprograms, named @i{A}, @i{B} and @i{C} (these are the @code{PROGRAM-ID}s of the three subprograms, and their source code may be found in the files @file{A.cbl}, @file{B.cbl} and @file{C.cbl}, respectively.

Here is how these four programs would be compiled if the three subprograms are to be static:

@example
cobc -x M.cbl A.cbl B.cbl C.cbl
@end example

This command informs the compiler (cobc) that four programs are to be compiled (the first named on the command must always be the main program), and a single executable file is to be created (due to the
@switchidx{-x}).

Here is how the main program and the three subprograms could be compiled if the three subprograms are to be dynamic:

@example
cobc -x M.cbl
cobc -m A.cbl B.cbl C.cbl
@end example

These commands will create an executable file for the main program (@switch{-x}) and three separate dynamically-loadable libraries (see
@switchidx{-m}), one for each of the three subprograms.  Had we wished, we could have created a single dynamically-loadable library containing all three subprograms by adding the
@switchidx{-b} to their compilation:

@example
cobc -m -b A.cbl B.cbl C.cbl
@end example

Dynamically-loadable @i{libraries} are also known by the term dynamically-loadable @i{modules}.  The two terms are synonymous.

Here are the rules about GnuCOBOL dynamically-loadable modules:
@enumerate
@item
There may be multiple GnuCOBOL subprograms contained within a single dynamically-loadable library if the @code{-b} switch is used in addition to @code{-m}.  If not, each subprogram will be compiled to a separate dynamically-loadable library.

@item
Dynamically-loadable modules will be named @file{@var{xxxxxxxx}.dll} on a Windows system, @file{@var{xxxxxxxx}.so} on a Unix system or @file{@var{xxxxxxxx}.dylib} on an OSX system, where @file{@var{xxxxxxxx}} exactly matches, including the usage of upper- and lower-case letters, the primary entry-point name (@code{PROGRAM-ID} or @code{FUNCTION-ID}) or an alternate entry point name defined via the @statementref{ENTRY} of any one of the GnuCOBOL programs included in that module.

@item
The first time any of the GnuCOBOL subprograms in a dynamically-loadable module are invoked, the entry-point referenced must be the one for which the @file{.dll}, @file{.so} or @file{.dylib} file is named.

@item
@anchor{Locating Dynamically-Loadable Modules}When a dynamically-loadable module needs to be loaded (because it is not already in memory from a previous subprogram execution), the dynamically-loadable library will be sought in the same directory from which the main program was loaded.  If it cannot be found there, each directory named in the
@envvarruntimeref{PATH} will be searched.  If it was not located in any of those directories, the library specified by the
@envvarruntime{COB_LIBRARY_PATH} will be searched.  Finally, if it @i{still} cannot be located, execution will be terminated with an error message (@i{libcob: Cannot find module 'xxxxxxxx'}).

@item
Once the dynamically-loadable module has been successfully loaded, any of the entry-points contained within it are now available for reference.

@item
Dynamically-loadable modules may be removed from memory via the @statementref{CANCEL}.

@item
Once a dynamically-loadable module is actually loaded into memory, even if it is subsequently unloaded (via the @statement{CANCEL}), its list of entry-points remain available to the GnuCOBOL run-time library and subsequent re-executions of any of those entry points will be able to bypass the search (rule #4) as well as the @i{first-execution rule} (rule #3).
@end enumerate

Consult the documentation on the
@envvarruntime{COB_PRE_LOAD},
@envvarruntime{COB_PHYSICAL_CANCEL} and
@envvarruntimerefs{COB_LOAD_CASE} for additional options when using dynamically-loadable modules.
@comment *********************************************************************
@comment ** 11.5 Subprogram Execution Flow                                   **
@comment *********************************************************************
@newsection{Subprogram Execution Flow}

When a subprogram is invoked, the flow of execution will differ slightly depending on whether the subprogram is a subroutine or a user-defined function.
@menu
* Subroutine Execution Flow.
* User-Defined Function Execution Flow.
@end menu
@comment *********************************************************************
@comment ** 11.5.1 Subroutine Execution Flow                                 **
@comment *********************************************************************
@newsubsection{Subroutine Execution Flow}

When a subroutine is @code{CALL}ed:
@enumerate

@item
The calling program issues a statement of the form @code{CALL '@var{entry-point}' USING ...} to transfer control to the subroutine.

@item
The executable for the called program will be located and loaded into memory:
@enumerate A
@item
If it is a static subroutine, it will already be part of the executable program issuing the @syntaxref{CALL}.

@item
If it is a dynamic subroutine, the GnuCOBOL run-time system will check to see if a dynamically-loadable module containing the subprogram's entry point was already located.  If it was, no further ``location'' activity is needed.  If not, the dynamically-loadable module will be located (@pxref{Locating Dynamically-Loadable Modules}).

@item
Once the module has been located (if location was needed), it will be loaded into memory (if not already loaded).
@end enumerate
@item
Execution of the calling program is suspended and control will transfer to the called program, as follows:
@enumerate A
@item
If the @syntaxrefalt{PROGRAM-ID,IDENTIFICATION DIVISION} clause of the subprogram included the
@syntaxidx{INITIAL} clause, the program will be reinitialized back to its compile-time state.  This will happen regardless of the @code{INITIAL} clause the first time the subprogram is executed.

@item
Local-storage, if any, will be allocated and initialized.

@item
Execution will begin at the first executable statement following the subprograms entry-point.  The entry point will be either the first executable statement following any @syntaxref{DECLARATIVES} that might be present (if the subprogram was invoked using its primary entry-point name) or the first executable statement following the @statementref{ENTRY} naming the entry-point specified on the @code{CALL} if the subprogram was invoked using an alternate entry point.
@end enumerate
@item
The flow of execution will then progress through the coding of the subprogram as it would with any other program.

@item
If the subprogram issues a @statementref{STOP} with the @code{RUN} option, program execution ceases and control returns to the operating system or whatever execution shell invoked the main program.

@item
If the subprogram wishes to return control back to the calling program, it will do so using either the @statementref{GOBACK} or the @statementrefalt{EXIT PROGRAM,EXIT}.  At this time:
@enumerate A
@item
If the subprograms procedure division header or
@statement{ENTRY} included a
@syntaxidx{RETURNING}, the value of the data item found on that clause is moved to the
@registerref{RETURN-CODE}; this behaviour can be altered utilizing the
@syntaxrefalt{CALL-CONVENTION,SPECIAL-NAMES} feature to leave @code{RETURN-CODE} unchanged.

@item
Local-storage, if any, is de-allocated.

@item
If the calling program included a @code{RETURNING} clause on the @code{CALL} statement that invoked the subprogram, the value of the @code{RETURNING} data item in the subroutine is moved to that data item.  If there was no @code{RETURNING} specified in the subroutine, the value of the
@register{RETURN-CODE} is moved to that data item.

@item
Execution will resume back in the calling program with the first executable statement following the @code{CALL} that invoked the subprogram.
@end enumerate
@end enumerate
@comment *********************************************************************
@comment ** 11.5.2 User-Defined Function Execution Flow                      **
@comment *********************************************************************
@newsubsection{User-Defined Function Execution Flow}

When a user-defined function is executed:
@enumerate

@item
The object code for the called program (the user-defined function) will be located, as follows:
@enumerate A
@item
If it is a static user-defined function, it will already be part of the executable file containing the calling program.

@item
If it is a dynamic user-defined function, the GnuCOBOL run-time system will check to see if a dynamically-loadable module containing the function's entry point was already located.  If it was, no further ``location'' activity is needed.  If not, the dynamically-loadable module will be located (@pxref{Locating Dynamically-Loadable Modules}).

@item
Once the module has been located (if location was needed), it will be loaded into memory (if not already loaded).
@end enumerate
@item Execution of the calling program is suspended and control will transfer to the called program, as follows:
@enumerate A
@item
Local-storage, if any, will be allocated and initialized.

@item
Execution will begin with the first executable statement in the procedure division following any @syntaxref{DECLARATIVES} that might be present.
@end enumerate
@item
The flow of execution will then progress through the coding of the function as it would with any other program.

@item
If the function issues a @statementref{STOP} with the @code{RUN} option, program execution ceases and control returns to the operating system or whatever execution shell invoked the main program.

@item
If the function wishes to return control back to the calling program, it will do so using either the @statementref{GOBACK} or the @statementrefalt{EXIT FUNCTION,EXIT}.  At this time:
@enumerate A
@item
The value of the data item found on the user-defined functions @syntaxref{PROCEDURE DIVISION RETURNING} clause is moved to the
@registerref{RETURN-CODE}.

@item
Local-storage, if any, is de-allocated.

@item
Execution will resume back in the calling program at the point where the returned value of the function is needed.  At that point, the value in the
@register{RETURN-CODE} will be used for the function's value.
@end enumerate
@end enumerate
@comment *********************************************************************
@comment ** 11.6 Sharing Data Between Calling and Called Programs           **
@comment *********************************************************************
@page
@newsection{Sharing Data Between Calling and Called Programs}
@menu
* Subprogram Arguments.
@detailmenu
* Calling Program Considerations.
* Called Program Considerations.
@end detailmenu
* GLOBAL Data Items.
* EXTERNAL Data Items.
@end menu
@comment *********************************************************************
@comment ** 11.6.1 Subprogram Arguments                                     **
@comment *********************************************************************
@newsubsection{Subprogram Arguments}
@menu
* Calling Program Considerations.
* Called Program Considerations.
@end menu
@comment *********************************************************************
@comment ** 11.6.1.1 Calling Program Considerations                         **
@comment *********************************************************************
@newsubsubsection{Calling Program Considerations}

Data items defined in a calling program may be passed to either type of called program (subroutine or user-defined function) as arguments.

Arguments must be described in both the calling and called programs, and while they don't need to have the same names in both programs, they should be described in an identical manner with regard to the following characteristics:
@itemize @bullet

@item @syntaxref{PICTURE} (including both type and length)

@item @syntaxref{SIGN}

@item @syntaxref{SYNCHRONIZED}

@item @syntaxref{USAGE}
@end itemize

A subroutine may be passed a maximum of 251 arguments; if you build the GnuCOBOL software yourself from the distributed source, you CAN change this value by altering the defined value of @code{COB_MAX_FIELD_PARAMS} in the @file{call.h} header file but also see 7.8.5.11 for more information.  There is no built-in GnuCOBOL limit to how many arguments a user-defined function may be passed.

Whether or not changes made to an argument within a subroutine will be ``visible'' to the calling program depends on how the argument was passed.  There are three ways in which arguments may be passed from a calling program to a subroutine, as defined by the use of optional @code{BY} clauses in the @syntaxref{CALL} statement's list of arguments.

As an example, the following statement passes three arguments to a subroutine --- each argument is passed differently.

@example
CALL "subroutine" USING BY REFERENCE arg-1
                        BY CONTENT arg-2
                        BY VALUE arg-3
END-CALL
@end example

The three ways arguments are passed are as follows.
@table @asis

@item @code{BY REFERENCE}

When a subroutine argument is passed
@syntaxidx{BY REFERENCE}, the subroutine is passed the @i{address} of the @i{actual data item} being passed as an argument.  The item may be anything defined within the data division of the program.  If the subroutine modifies the contents of this argument, the calling program will ``see'' the results of that change when the subroutine returns control.  This is the default manner in which GnuCOBOL passes arguments to a subroutine, should no @code{BY} clauses be included on the @code{CALL}.

@item @code{BY CONTENT}

When a subroutine is passed an argument
@syntaxidx{BY CONTENT}, the subroutine is passed the @i{address} of a @i{copy} of the actual data being passed as an argument.  The item may be anything defined within the data division of the program.  The copy is made each time the @code{CALL} statement is executed, immediately before the @code{CALL} actually takes place.  If the subroutine modifies the contents of this argument, it will be the @i{copy} that is modified, not the original data item; the calling program will therefore not ``see'' the results of that change when the subroutine returns control.

@item @code{BY VALUE}

Passing a subroutine argument
@syntaxidx{BY VALUE} passes the @i{actual value} of the data being passed as an argument.  The item may be any elementary binary numeric item defined within the data division of the program.  If the subroutine modifies the contents of this argument, the calling program will not ``see'' the results of that change when the subroutine returns control.
@end table

The first two ways in which arguments may be passed (@code{BY REFERENCE} and @code{BY CONTENT}) are intended for use when a GnuCOBOL program is being called, while the first and third (@code{BY REFERENCE} and @code{BY VALUE}) are intended for use when a C program is being called.  You @i{can} use @code{BY VALUE} arguments when calling GnuCOBOL subroutines, but remember that those arguments are limited to being a numeric binary data item.

Arguments to user-defined functions are always passed @code{BY REFERENCE}.
@comment *********************************************************************
@comment ** 11.6.1.2 Called Program Considerations                           **
@comment *********************************************************************
@newsubsubsection{Called Program Considerations}

When coding a GnuCOBOL subprogram (a subroutine or user-defined function), all arguments to the subprogram must be defined in the subprogram's linkage section.

These arguments must be explicitly included on the @syntaxref{PROCEDURE DIVISION USING} clause that lists the arguments in the sequence in which they will be passed to the subprogram.

These arguments described in the @code{PROCEDURE DIVISION USING} clause may each be defined as either @code{BY REFERENCE}, if the calling program is passing them either
@syntaxidx{BY REFERENCE} or
@syntaxidx{BY CONTENT}, or as
@syntaxidx{BY VALUE} if they are being passed @code{BY VALUE}.

By default, all arguments are assumed to be @code{BY REFERENCE} unless explicitly stated otherwise on the procedure division header.

Arguments to a user-defined function are always to be specified as @code{BY REFERENCE} (either explicitly or by not using any @code{BY}).

If the subprogram returns a value, the data item in which the value is returned must also be defined in the subprogram's linkage section, with a @syntaxref{USAGE} of @code{BINARY-LONG SIGNED}, or its equivalent.
@comment *********************************************************************
@comment ** 11.6.2 GLOBAL Data Items                                         **
@comment *********************************************************************
@newsubsection{GLOBAL Data Items}

Another way in which a data item may be shared between a calling program (@i{A}) and a called program (@i{B}) is by defining the data item in the calling program and attaching the @syntaxref{GLOBAL} clause to it so that it may be used within the called program.  In order for this to work, program @i{B} (the one called by program @i{A}) must be a nested subprogram within program @i{A}.

Here's a small example:

@example
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoGLOBAL.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Arg GLOBAL                     PIC X(10).
PROCEDURE DIVISION.
000-Main.
    MOVE ALL "X" TO Arg
    CALL "DemoSub" END-CALL
    DISPLAY "DemoGLOBAL: " Arg END-DISPLAY
    GOBACK
    .
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoSub.
PROCEDURE DIVISION.
000-Main.
    MOVE ALL "*" TO Arg.
    GOBACK
    .
END PROGRAM DemoSub.
END PROGRAM DemoGLOBAL.
@end example

When the program runs, it produces the output:

@example
DemoGLOBAL: **********
@end example
@comment *********************************************************************
@comment ** 11.6.3 EXTERNAL Data Items                                       **
@comment *********************************************************************
@newsubsection{EXTERNAL Data Items}

The final way in which a data item may be shared between a calling program (@i{A}) and a called program (@i{B}) is by defining the data item (with the same name) in both programs and attaching the @syntaxref{EXTERNAL} clause to it (again, in both programs).  This approach works regardless of whether the called program is nested within the calling program or not.  It also works even if the two programs are compiled separately.

Here's a demonstration:

@example
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoEXTERNAL.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Arg EXTERNAL                PIC X(10).
PROCEDURE DIVISION.
000-Main.
    MOVE ALL "X" TO Arg
    CALL "DemoSub" END-CALL
    DISPLAY "DemoEXTERNAL: " Arg END-DISPLAY
    GOBACK
    .
END PROGRAM DemoEXTERNAL.
IDENTIFICATION DIVISION.
PROGRAM-ID. DemoSub.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Arg EXTERNAL                PIC X(10).
PROCEDURE DIVISION.
000-Main.
    MOVE ALL "*" TO Arg.
    GOBACK
    .
END PROGRAM DemoSub.
@end example

When the program runs, it produces the output:

@example
DemoEXTERNAL: **********
@end example
@comment *********************************************************************
@comment ** 11.7 Recursive Subprograms                                       **
@comment *********************************************************************
@newsection{Recursive Subprograms}

A subroutine may @code{CALL} itself, either directly or indirectly from another subroutine or user-defined function that it @code{CALL}s.  Any subroutine that indulges in this sort of behaviour (called recursion) is called a
@define{Recursive Subprogram}.

Any GnuCOBOL subroutine can be recursively invoked only if it is defined to the GnuCOBOL compiler as @i{being} a recursive subroutine.  This is accomplished by adding the @code{RECURSIVE} attribute to its @syntaxrefalt{PROGRAM-ID,IDENTIFICATION DIVISION}.

All User-defined functions are automatically capable of being executed recursively.

Here is an example of a main program (DEMOFACT) that calls both a subprogram (SUB) and a user-defined function (FUNC) to compute the factorial value of a number.

@example
IDENTIFICATION DIVISION.
PROGRAM-ID. DEMOFACT.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
    FUNCTION RECURSIVEFUNC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Result    USAGE BINARY-LONG.
01  Arg       USAGE BINARY-LONG.
PROCEDURE DIVISION.
000-Main.
    MOVE 6 TO Arg
    CALL "RECURSIVESUB"
        USING BY CONTENT Arg
        RETURNING Result
    DISPLAY Arg "! = "
            Result
    DISPLAY Arg "! = "
            RECURSIVEFUNC(Arg)
    GOBACK
    .
END PROGRAM DEMOFACT.
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB RECURSIVE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Result      USAGE BINARY-LONG.
01  Next-Arg    USAGE BINARY-LONG.
01  Next-Result USAGE BINARY-LONG.
LINKAGE SECTION.
01  Arg         USAGE BINARY-LONG.
PROCEDURE DIVISION USING Arg
               RETURNING Result.
000-Main.
    DISPLAY "Entering SUB"
            " Arg=" Arg
    IF Arg = 1
      MOVE 1 TO Result
      DISPLAY "Leaving SUB"
              " Returning " Result
    ELSE
      SUBTRACT 1 FROM Arg
          GIVING Next-Arg
      CALL "SUB"
           USING BY CONTENT Next-Arg
           RETURNING Next-Result
      COMPUTE Result =
              Arg * Next-Result
      DISPLAY "Leaving SUB"
              " Returning "
              Result "=" Arg "*"
              Next-Result
    END-IF
    GOBACK
    .
END PROGRAM SUB.
IDENTIFICATION DIVISION.
FUNCTION-ID. FUNC.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
    FUNCTION RECURSIVEFUNC.
DATA DIVISION.
WORKING-STORAGE SECTION.
LINKAGE SECTION.
01  Arg     USAGE BINARY-LONG.
01  Result  USAGE BINARY-LONG
            SIGNED.
PROCEDURE DIVISION USING Arg
               RETURNING Result.
000-Main.
    DISPLAY "Entering FUNC"
            " Arg=" Arg
    IF Arg = 1
      MOVE 1 TO Result
    ELSE
      COMPUTE Result = Arg *
              FUNC(Arg - 1)
    END-IF
    DISPLAY "Leaving FUNC"
            " Returning " Result
    GOBACK
    .
END FUNCTION FUNC.
@end example

When DEMOFACT is executed, the output shown below is generated.

@example
E:\Programs\Demos>demofact
Entering RECURSIVESUB Arg=+0000000006
Entering RECURSIVESUB Arg=+0000000005
Entering RECURSIVESUB Arg=+0000000004
Entering RECURSIVESUB Arg=+0000000003
Entering RECURSIVESUB Arg=+0000000002
Entering RECURSIVESUB Arg=+0000000001
Leaving RECURSIVESUB Returning +0000000001
Leaving RECURSIVESUB Returning +0000000002=+0000000002*+0000000001
Leaving RECURSIVESUB Returning +0000000006=+0000000003*+0000000002
Leaving RECURSIVESUB Returning +0000000024=+0000000004*+0000000006
Leaving RECURSIVESUB Returning +0000000120=+0000000005*+0000000024
Leaving RECURSIVESUB Returning +0000000720=+0000000006*+0000000120
+0000000006! = +0000000720
Entering RECURSIVEFUNC Arg=+0000000006
Entering RECURSIVEFUNC Arg=+0000000005
Entering RECURSIVEFUNC Arg=+0000000004
Entering RECURSIVEFUNC Arg=+0000000003
Entering RECURSIVEFUNC Arg=+0000000002
Entering RECURSIVEFUNC Arg=+0000000001
Leaving RECURSIVEFUNC Returning +0000000001
Leaving RECURSIVEFUNC Returning +0000000002
Leaving RECURSIVEFUNC Returning +0000000006
Leaving RECURSIVEFUNC Returning +0000000024
Leaving RECURSIVEFUNC Returning +0000000120
Leaving RECURSIVEFUNC Returning +0000000720
+0000000006! = +0000000720
@end example
@comment *********************************************************************
@comment ** 11.8 Combining GnuCOBOL and C Programs                          **
@comment *********************************************************************
@newsection{Combining GnuCOBOL and C Programs}

The upcoming sections deal the issues pertaining to calling C language programs from GnuCOBOL programs, and vice versa.  Two additional sections provide samples illustrating specifics as to how those issues are overcome in actual program code.
@menu
* GnuCOBOL Run-Time Library Requirements.
* String Allocation Differences Between GnuCOBOL and C.
* Matching C Data Types with GnuCOBOL USAGE's.
* GnuCOBOL Main Programs CALLing C Subprograms.
* C Main Programs Calling GnuCOBOL Subprograms.
@end menu
@comment *********************************************************************
@comment ** 11.8.1 GnuCOBOL Run-Time Library Requirements                   **
@comment *********************************************************************
@newsubsection{GnuCOBOL Run-Time Library Requirements}

Like most other implementations of the COBOL language, GnuCOBOL utilizes a run-time library.  When the first program executed in a given execution sequence is a GnuCOBOL program, any run-time library initialization will be performed by the compiled COBOL code in a manner that is transparent to the C-language programmer.  If, however, a C program is the first to execute, the burden of performing GnuCOBOL run-time library initialization falls upon the C program.  @xref{C Main Programs Calling GnuCOBOL Subprograms}, for an example of how to do this.
@comment *********************************************************************
@comment ** 11.8.2 String Allocation Differences Between GnuCOBOL and C     **
@comment *********************************************************************
@newsubsection{String Allocation Differences Between GnuCOBOL and C}

Both languages store strings as a fixed-length continuous sequence of characters.

COBOL stores these character sequences up to a specific quantity limit imposed by the @syntaxref{PICTURE} clause of the data item.  For example: @code{01  LastName   PIC X(15).}.

There is never an issue of exactly what the length of a string contained in a @syntaxrefalt{USAGE DISPLAY,USAGE} data item is --- there are always exactly how ever many characters as were allowed for by the @code{PICTURE} clause.  In the example above, @code{LastName} will always contain exactly fifteen characters; of course, there may be anywhere from 0 to 15 trailing SPACES as part of the current LastName value.

C actually has no ``string'' data type; it stores strings as an array of @code{char} data type items where each element of the array is a single character.  Being an array, there is an upper limit to how many characters may be stored in a given ``string''.  For example:

@example
char lastName[15]; /* 15 chars: lastName[0] through lastName[14] */
@end example

C provides a robust set of string-manipulation functions to copy strings from one char array to another, search strings for certain characters, compare one char array to another, concatenate char arrays and so forth.  To make these functions possible, it was necessary to be able to define the logical end of a string.  C accomplishes this via the expectation that all strings (char arrays) will be terminated by a NULL character (@code{x'00'}).  Of course, no one forces a programmer to do this, but if [s]he ever expects to use any of the C standard functions to manipulate that string they had @i{better} be null-terminating their strings!

So, GnuCOBOL programmers expecting to pass strings to or receive strings from C programs had best be prepared to deal with the null-termination issue, as follows:
@enumerate
@item
Pass a quoted literal string from GnuCOBOL to C as a zero-delimited string literal (@code{Z'@var{string}'}).

@item
Pass alphanumeric (@code{PIC X}) or alphabetic (@code{PIC A}) data items to C subroutines by appending an @sc{ASCII} @code{NUL} character (@code{X'00'}) to them.  For example, to pass the 15-character @code{LastName} data item described above to a C subroutine:

@example
01  LastName-Arg-to-C     PIC X(16).
...
    MOVE FUNCTION CONCATENATE(LastName,X'00') TO LastName-Arg-to-C
@end example

And then pass @code{LastName-Arg-to-C} to the C subprogram!

@item
When a COBOL program needs to process string data prepared by a C program, the embedded null character must be accounted for.  This can easily be accomplished with an @statementref{INSPECT} such as the following:

@example
INSPECT Data-From-a-C-Program
    REPLACING FIRST X'00' BY SPACE
              CHARACTERS BY SPACE AFTER INITIAL X'00'
@end example
@end enumerate
@comment *********************************************************************
@comment ** 11.8.3 Matching C Data Types with GnuCOBOL USAGE's               **
@comment *********************************************************************
@newsubsection{Matching C Data Types with GnuCOBOL USAGE's}

Matching up GnuCOBOL numeric Usage's with their C language data type equivalents is possible via the following chart:
@float
@multitable @columnfractions 0.5 0.5
@headitem COBOL @tab C
@item
BINARY-CHAR UNSIGNED @tab unsigned char
@item
BINARY-CHAR [ SIGNED ] @tab signed char
@item
BINARY-SHORT UNSIGNED @tab unsigned @* unsigned int @* unsigned short @* unsigned short int
@item
BINARY-SHORT [ SIGNED ] @tab int @* short @* short int @* signed int @* signed short @* signed short int
@item
BINARY-LONG UNSIGNED @tab unsigned long @* unsigned long int
@item
BINARY-LONG [ SIGNED ] @* BINARY-INT @tab long @* long int @* signed long @* signed long int
@item
BINARY-C-LONG [ SIGNED ] @tab long
@item
BINARY-DOUBLE UNSIGNED @tab unsigned long long @* unsigned long long int
@item
BINARY-DOUBLE [ SIGNED ] @* BINARY-LONG-LONG @tab long long int @* signed long long int
@item
COMPUTATIONAL-1 @tab float
@item
COMPUTATIONAL-2 @tab double
@item
N/A (no GnuCOBOL equivalent) @tab long double
@end multitable
@comment tex-style @caption{C and COBOL Datatypes}
@end float
These sizes conform to the COBOL standard and the minimum sizes of the COBOL types are the same as the minimum sizes of the corresponding C data types. There's no official compatibility between them. Note that values in square braces '[]' are the defaults.
@comment *********************************************************************
@comment ** 11.8.4 GnuCOBOL Main Programs CALLing C Subprograms             **
@comment *********************************************************************
@newsubsection{GnuCOBOL Main Programs CALLing C Subprograms}

Here's a sample of a GnuCOBOL program that CALLs a C subprogram.
@smallformat
@verbatim
COBOL Calling Program               C Called Program
==================================  ===============================
IDENTIFICATION DIVISION.            #include <stdio.h>
PROGRAM-ID. maincob.                int subc(char *arg1,
DATA DIVISION.                               char *arg2,
WORKING-STORAGE SECTION.                     unsigned long *arg3) {
01  Arg1     PIC X(7).                char nu1[7]="New1";
01  Arg2     PIC X(7).                char nu2[7]="New2";
01  Arg3     USAGE BINARY-LONG.       printf("Starting subc\n");
PROCEDURE DIVISION.                   printf("Arg1=%s\n",arg1);
000-Main.                             printf("Arg2=%s\n",arg2);
    DISPLAY 'Starting maincob'        printf("Arg3=%d\n",*arg3);
    MOVE Z'Arg1'   TO Arg1            arg1[0]='X';
    MOVE Z'Arg2'   TO Arg2            arg2[0]='Y';
    MOVE 123456789 TO Arg3            *arg3=987654321;
    CALL 'subc'                       return 2;
        USING BY CONTENT   Arg1,    }
              BY REFERENCE Arg2,
              BY REFERENCE Arg3
    DISPLAY 'Back'
    DISPLAY 'Arg1=' Arg1
    DISPLAY 'Arg2=' Arg2
    DISPLAY 'Arg3=' Arg3
    DISPLAY 'Returned value='
            RETURN-CODE
    STOP RUN
    .
@end verbatim
@end smallformat

The idea is to pass two string and one full-word unsigned arguments to the subprogram, have the subprogram print them out, change all three and pass a return code of 2 back to the caller.  The caller will then re-display the three arguments (showing changes only to the two @code{BY REFERENCE} arguments), display the return code and halt.

While simple, these two programs illustrate the techniques required quite nicely.

Note how the COBOL program ensures that a null end-of-string terminator is present on both string arguments.

Since the C program is planning on making changes to all three arguments, it declares all three as pointers in the function header and references the third argument as a pointer in the function body.  It actually had no choice for the two string (char array) arguments --- they must be defined as pointers in the function even though the function code references them without the leading @samp{*} that normally signifies pointers.

These programs are compiled and executed as follows.

@example
$ cobc -x maincob.cbl subc.c
$ maincob
Starting maincob
Starting subc
Arg1=Arg1
Arg2=Arg2
Arg3=123456789
Back
Arg1=Arg1
Arg2=Yrg2
Arg3=+0987654321
Returned value=+000000002
$
@end example

Remember that the null characters are actually in the GnuCOBOL @code{Arg1} and @code{Arg2} data items.  They don't appear in the output, but they @i{are} there.

Did you notice the output showing the contents of @code{Arg1} after the subroutine was called?  Those contents were unchanged!  The subroutine @i{definitely} changed that argument, but since the COBOL program passed that argument @code{BY CONTENT}, the change was made to a @i{copy} of the argument, not to the @code{Arg1} data item itself.
@comment *********************************************************************
@comment ** 11.8.5 C Main Programs Calling GnuCOBOL Subprograms             **
@comment *********************************************************************
@newsubsection{C Main Programs Calling GnuCOBOL Subprograms}

Now, the roles of the two languages in the previous section will be reversed, having a C main program execute a GnuCOBOL subprogram.
@smallformat
@verbatim
C Calling Program                              GNU-COBOL Called Program
=============================================  =================================
#include <libcob.h> /* COB RUN-TIME */         IDENTIFICATION DIVISION.
#include <stdio.h>                             PROGRAM-ID. subcob.
int main (int argc, char **argv) {             DATA DIVISION.
   int returnCode;                             LINKAGE SECTION.
   char arg1[7] = "Arg1";                      01  Arg1      PIC X(7).
   char arg2[7] = "Arg2";                      01  Arg2      PIC X(7).
   unsigned long arg3 = 123456789;             01  Arg3      USAGE BINARY-LONG.
   printf("Starting mainc...\n");              PROCEDURE DIVISION USING
   cob_init (argc, argv); /* COB RUN-TIME */       BY VALUE     Arg1,
   returnCode = subcob(arg1,arg2,&arg3);           BY REFERENCE Arg2,
   printf("Back\n");                               BY REFERENCE Arg3.
   printf("Arg1=%s\n",arg1);                   000-Main.
   printf("Arg2=%s\n",arg2);                       DISPLAY 'Starting cobsub.cbl'
   printf("Arg3=%d\n",arg3);                       DISPLAY 'Arg1=' Arg1
   printf("Returned value=%d\n",returnCode);       DISPLAY 'Arg2=' Arg2
   return returnCode;                              DISPLAY 'Arg3=' Arg3
}                                                  MOVE 'X' TO Arg1 (1:1)
                                                   MOVE 'Y' TO Arg2 (1:1)
                                                   MOVE 987654321 TO Arg3
                                                   MOVE 2 TO RETURN-CODE
                                                   GOBACK
                                                   .
@end verbatim
@end smallformat

Since the C program is the one that will execute first, before the GnuCOBOL subroutine, the burden of initializing the GnuCOBOL run-time environment lies with that C program; it will have to invoke the @code{cob_init} function, which is part of the @code{libcob} library.  The two required C statements are shown highlighted.

The arguments to the @code{cob_init} routine are the argument count and value parameters passed to the main function when the program began execution.  By passing them into the GnuCOBOL subprogram, it will be possible for that GnuCOBOL program to retrieve the command line or individual command-line arguments.  If that won't be necessary, @code{cob_init(0,NULL);} could be specified instead.

Since the C program wants to allow @code{arg3} to be changed by the subprogram, it prefixes it with a @samp{&} to force a @code{CALL BY REFERENCE} for that argument.  Since @code{arg1} and @code{arg2} are strings (char arrays), they are automatically passed by reference.

Here's the output of the compilation process as well as the program's execution.  The example assumes a Windows system with a GnuCOBOL build that uses the GNU C compiler on that system; the technique works equally well regardless of which C compiler and which operating system you're using.

@example
C:\Users\Gary\Documents\Programs> cobc -S subcob.cbl
C:\Users\Gary\Documents\Programs> gcc mainc.c subcob.s -o mainc.exe -llibcob
C:\Users\Gary\Documents\Programs> mainc.exe
Starting mainc...
Starting cobsub.cbl
Arg1=Arg1
Arg2=Arg2
Arg3=+0123456789
Back
Arg1=Xrg1
Arg2=Yrg2
Arg3=987654321
Returned value=2
C:\Users\Gary\Documents\Programs>
@end example

Note that even though we told GnuCOBOL that the 1st argument was to be @code{BY VALUE}, it was treated as if it were @code{BY REFERENCE} anyway.  String (char array) arguments passed from C callers to GnuCOBOL subprograms will be modifiable by the subprogram.  It's best to pass a copy of such data if you want to ensure that the subprogram doesn't change it.

The third argument is different, however.  Since it's not an array you have the choice of passing it either @code{BY REFERENCE} or @code{BY VALUE}.
@iftex
@sp 3
@center ------------------------------------------------------------
@center End of Chapter 11 --- Sub-Programming
@end iftex
