Using GnuCOBOL (cobc) 3.2.0 on Windows, I'm trying to write a simple COBOL program that calls a subroutine in another file, but the subroutine is not found.
foo1.cob
:
IDENTIFICATION DIVISION.
PROGRAM-ID. MAINPROG.
PROCEDURE DIVISION.
MAIN-PROCEDURE.
PERFORM "SUB-SAY-HELLO1".
CALL "SUB-SAY-HELLO2".
STOP RUN.
SUB-SAY-HELLO1.
DISPLAY "HELLO1".
foo2.cob
:
IDENTIFICATION DIVISION.
PROGRAM-ID. SUBPROG.
PROCEDURE DIVISION.
SUB-SAY-HELLO2.
DISPLAY "HELLO2!".
EXIT PROGRAM.
First I run the command
cobc -m foo2.cob
that produces foo2.dll
.
Then I run the command
cobc -x foo1.cob -L c:\dev -l foo2
that produces foo1.exe
.
Then I try to execute foo1.exe, and get the following output:
HELLO1
libcob: error: module 'SUB-SAY-HELLO2' not found
What do I need to do for my main program to find the sub program?
EDIT: I first claimed what I want to do as not possible, but that is not true. I have now found out how to do it, which is explained below.
After more testing, and having a colleague of mine test this on the VSI VMS Integrity operating system with the native VSI COBOL compiler, it appears that what I wanted to achieve is not possible in COBOL in the way that I did it. One COBOL program cannot specify multiple subroutines that are callable separately - a single program is instead callable, and will then execute the PROCEDURE DIVISION
from the top.
In my original posted code, the
CALL "SUB-SAY-HELLO2".
can be replaced with
CALL "SUBPROG".
Which will execute just fine with the following output
HELLO1
HELLO2!
The SUBPROG
program will be executed from the top of the PROCEDURE DIVISION
, stopping at EXIT PROGRAM
.
If multiple subroutines are to be declared, they need to be declared in separate programs. A COBOL file can however include multiple programs, so if the file foo2.cob
above was to be changed to:
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB-SAY-HELLO2.
PROCEDURE DIVISION.
SUB-ROUTINE.
DISPLAY "HELLO2!".
EXIT PROGRAM.
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB-SAY-HELLO3.
PROCEDURE DIVISION.
SUB-ROUTINE.
DISPLAY "HELLO3!".
EXIT PROGRAM.
The main program foo1.cob
would be able to call the programs separately like this:
IDENTIFICATION DIVISION.
PROGRAM-ID. MAINPROG.
PROCEDURE DIVISION.
MAIN-PROCEDURE.
PERFORM SUB-SAY-HELLO1.
CALL "SUB-SAY-HELLO2".
CALL "SUB-SAY-HELLO3".
STOP RUN.
SUB-SAY-HELLO1.
DISPLAY "HELLO1".
This is supported both by GnuCOBOL and VSI COBOL. There is an ENTRY
statement that can also be used, which is supported by GnuCOBOL and IBM COBOL, but not VSI COBOL, which would allow for the foo2.cob
program to look like this instead:
IDENTIFICATION DIVISION.
PROGRAM-ID. SUBPROG.
PROCEDURE DIVISION.
ENTRY "SUB-SAY-HELLO2".
DISPLAY "HELLO2!".
EXIT PROGRAM.
ENTRY "SUB-SAY-HELLO3".
DISPLAY "HELLO3!".
EXIT PROGRAM.
And the foo1.cob
program can now call the entries in the same manner as mentioned above. This is not the approach I will use however, as my COBOL programs need to work for both GnuCOBOL and VSI COBOL.
NOTE: If these instructions are followed in GnuCOBOL but there are still link errors because the programs/entries are not found, this might be due to preloading being required. Set the environment variable COB_PRE_LOAD
to your built library, in this case (Windows example):
set COB_PRE_LOAD=C:\dev\foo2.dll