From: charles.goodman on
Thanks for the tips.
Yes I needed to add my curent directory to LD_LIBRARY_PATH
I also nneded to add "-L./" to the cobol command to compile the main
program.
My compile commands, that work are:
cobol -dy -shared -WC,"BINARY(BYTE)" -o libMYSUB1.so MYSUB1.cbl
cobol -dy -shared -WC,"BINARY(BYTE)" -o libMYSUB2.so MYSUB2.cbl
cobol -M -dy -WC,"BINARY(BYTE),DLOAD" -o MYMAIN -L./ -lMYSUB1 -lMYSUB2
MYMAIN.cbl

I am able to compile and execute. My simple programs are designed to
allow me to see the functioning of CALL and CANCEL.....

However the results is NOT exactly what I want. Using -l does not
allow for proper functioning of the CANCEL verb (see pg 77 of user's
guide). Once a subprogram is loaded with a CALL statement, it remains
in memory regardless of CANCEL statements. The working-storage of the
sub-program is not reinitialized upon a second CALL.

---Charlie
From: Richard on
On Feb 1, 6:48 am, charles.good...(a)bell.ca wrote:
> Thanks for the tips.
> Yes I needed to add my curent directory to LD_LIBRARY_PATH
> I also nneded to add "-L./" to the cobol command to compile the main
> program.
> My compile commands, that work are:
> cobol -dy -shared -WC,"BINARY(BYTE)" -o libMYSUB1.so MYSUB1.cbl
> cobol -dy -shared -WC,"BINARY(BYTE)" -o libMYSUB2.so MYSUB2.cbl
> cobol -M -dy -WC,"BINARY(BYTE),DLOAD" -o MYMAIN -L./ -lMYSUB1 -lMYSUB2
> MYMAIN.cbl
>
> I am able to compile and execute. My simple programs are designed to
> allow me to see the functioning of CALL and CANCEL.....
>
> However the results is NOT exactly what I want. Using -l does not
> allow for proper functioning of the CANCEL verb (see pg 77 of user's
> guide). Once a subprogram is loaded with a CALL statement, it remains
> in memory regardless of CANCEL statements. The working-storage of the
> sub-program is not reinitialized upon a second CALL.

Robert is completely wrong. You do not need a -l or a -L. These will
turn the CALLs into a static load and, as you say, the CANCEL will not
work as expected.

Go back to using your original compiles and links _without_ the -l or -
L.
It was only the LD_LIBRARY_PATH change that was required.

I am not sure how you determined that the CANCEL did not work but I
modified your programs to add a 2nd CALL and a CANCEL followed by a
3nd CALL in MYMAIN and then added a check for 'first time in' into
MYSUB1 and it worked as _I_ expected.

IDENTIFICATION DIVISION.
PROGRAM-ID. MYMAIN.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 ACPT PIC X.
PROCEDURE DIVISION.
OPEN-PARA.
DISPLAY "BEGIN MYMAIN".
CALL 'MYSUB1'.
CALL 'MYSUB1'.
CANCEL 'MYSUB1'.
CALL 'MYSUB1'.
DISPLAY "THE END - ACCEPTING ONE BYTE".
ACCEPT ACPT.
STOP RUN.

IDENTIFICATION DIVISION.
PROGRAM-ID. MYSUB1.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 ACPT PIC X.
01 FIRST-IN PIC X VALUE "Y".
PROCEDURE DIVISION.
OPEN-PARA.
IF FIRST-IN = "Y"
DISPLAY "First Time In"
ELSE
DISPLAY "Been here before"
END-IF
MOVE "N" TO FIRST-IN

DISPLAY "BEGIN MYSUB1 - ACCEPTING ONE BYTE".
ACCEPT ACPT.
EXIT PROGRAM.

As expected I got (ignoring your displays and accepts):

First Time In
Been here before
First Time In

So the CANCEL worked exactly as it should.

From: Richard on
On Jan 31, 7:23 pm, Robert <n...(a)e.mail> wrote:
> On Wed, 30 Jan 2008 20:46:28 -0800 (PST), Richard <rip...(a)azonic.co.nz> wrote:
> >On Jan 31, 4:38 pm, Robert <n...(a)e.mail> wrote:
> >> >when I try to execute I see my first DISPLAY and then it crashes:
> >> >BEGIN MYMAIN
> >> >cobol-rts:: HALT: JMP0015I-U [PID:0000763D TID:002516C0] CANNOT CALL
> >> >PROGRAM 'MY
> >> >SUB1'. ./MYMAIN: undefined symbol: MYSUB1 PGM=MYMAIN
> >> >Aborted
>
> >> >I am running on Red Hat Enterprise, and Fujitsu support say they will
> >> >only support:
> >> > * Red Hat Linux 7.2, Locale C
> >> > * Red Hat Linux 7.3, Locale C
> >> > * Red Hat Linux Advanced Server 2.1, Locale C
>
> >> >I am hoping that someone here has figured out how to compile and line
> >> >on less ancient versions of Linux.
>
> >> Try '-l MYSUB1' (lower case el) on the compilation of MYMAIN. As written, MYMAIN has no
> >> way of knowing the library name.
>
> >I think that you fail to understand what 'Dynamic Load' means.
>
> There is no Cobol syntax to specify a library name. You can only specify an entry point
> name. When you do a CALL, Unix doesn't search every library in the library path. That
> would be hopelessly slow. It searches only the libraries named in the executable's ELF
> header.
>
> Libraries normally contain many programs and entry points. They are not one-for-one like
> the example here.

Robert, you really should try to understand the problem and its
solution _before_ you show your complete lack of understanding of what
is happening.

I had already said that the code and compiles as given in the first
message _worked_ on my machine and that the only change required was
to the LD_LIBRARY_PATH which is the environment variable used for
_dynamic_ loads.

I had actually compiled and ran these programs to ensure that what I
said was correct and that I was not giving bad or wrong advice. I had
indicated, gently, to you that you were not on the right track.

I have used dynamic loading of Cobol with mainframes, with Micro Focus
since CIS Cobol, on RM, Fujitsu and others since the days of CP/M and
with Unix, DOS, Windows and Linux. I have even done dynamic loading
with C.

You have made several claims above which are FACTUALLY WRONG and show
that you, as I said before, completely fail to understand dynamic
loading, or even that it is possible.

With Fujitsu Cobol the DLOAD directive tells the system that CALLs
might be dynamic. In these cases there is no need for the library
containing the called routine to be known to the ELF binary, there is
no need for a -l, nor for the library to even exist at link (ld) time.

At run time a dynamic call will look for a file called libNAME.so
along the LD_LIBRARY_PATH, where NAME is that in the CALL, and it will
load that and find the required entry point.

As you should be able to tell from the results in charles' 2nd message
your BAD and WRONG advice has meant that his program does not work as
he expected. He statically linked the dynamic library which will cause
the CANCEL to fail to unload it and thus a reload does not find a new
copy but reuses the old.

From: Robert on
On Thu, 31 Jan 2008 11:47:51 -0800 (PST), Richard <riplin(a)azonic.co.nz> wrote:

>On Jan 31, 7:23 pm, Robert <n...(a)e.mail> wrote:
>> On Wed, 30 Jan 2008 20:46:28 -0800 (PST), Richard <rip...(a)azonic.co.nz> wrote:
>> >On Jan 31, 4:38 pm, Robert <n...(a)e.mail> wrote:
>> >> >when I try to execute I see my first DISPLAY and then it crashes:
>> >> >BEGIN MYMAIN
>> >> >cobol-rts:: HALT: JMP0015I-U [PID:0000763D TID:002516C0] CANNOT CALL
>> >> >PROGRAM 'MY
>> >> >SUB1'. ./MYMAIN: undefined symbol: MYSUB1 PGM=MYMAIN
>> >> >Aborted
>>
>> >> >I am running on Red Hat Enterprise, and Fujitsu support say they will
>> >> >only support:
>> >> > * Red Hat Linux 7.2, Locale C
>> >> > * Red Hat Linux 7.3, Locale C
>> >> > * Red Hat Linux Advanced Server 2.1, Locale C
>>
>> >> >I am hoping that someone here has figured out how to compile and line
>> >> >on less ancient versions of Linux.
>>
>> >> Try '-l MYSUB1' (lower case el) on the compilation of MYMAIN. As written, MYMAIN has no
>> >> way of knowing the library name.
>>
>> >I think that you fail to understand what 'Dynamic Load' means.
>>
>> There is no Cobol syntax to specify a library name. You can only specify an entry point
>> name. When you do a CALL, Unix doesn't search every library in the library path. That
>> would be hopelessly slow. It searches only the libraries named in the executable's ELF
>> header.
>>
>> Libraries normally contain many programs and entry points. They are not one-for-one like
>> the example here.

[the usual insults snipped]

>With Fujitsu Cobol the DLOAD directive tells the system that CALLs
>might be dynamic. In these cases there is no need for the library
>containing the called routine to be known to the ELF binary, there is
>no need for a -l, nor for the library to even exist at link (ld) time.

Normal Unix binding, outside Cobol, is to enter the names of called libraries in the
executable's header, using -l . Doing so does NOT mean they are statically linked as the
term is understood by mainframers and others from the Old School. It means the library
files will be loaded (if not already in memory) when the executable starts. If any cannot
be found, the program will not start, which guarantees the program will not abort mid-run
because a called program is missing. It also allows useful diagnostics to be run before
starting a long batch job.

A Windows dll works almost exactly the same as a Unix library (.so).

Cobol can, and I believe should, use the normal Unix binding mechanism. There are several
advantages and no good reason not to. In addition to the advantages given above, one
specific to Cobol is non-proliferation of program files, which I'll explain below.

Dynamic binding is the alternative. A running program can ask the OS to load an additional
library by specifying its FILE NAME. Technically, this is done with a call to dlopen() (or
LoadLibrary() on Windows). The OS first checks to see whether the library is already
loaded in memory, either because it was in the program's own header or because some other
running process is using it. If not, it searches the library path looking for the file
name and loads it. In either case it returns a handle to THE FILE that the program can use
to search for a specific entry point or the file's default entry point (with the dlsym()
function).

The problem with dynamic binding in Cobol is that Cobol has no concept of library FILE
NAME, it only knows about entry point names, which are essentially the same as program
names. Thus, Charles' application with "hundreds of COBOL programs", if packaged for
dynamic call, will have HUNDREDS OF LIBRARY FILES, each named libPROGRAM.so. I find that
ugly and, from a deployment point of view, clunky and amateurish. It would be cleaner to
package his hundreds of programs into one or a few libraries that are linked to the main
executable.

How many third-party apps have you seen that came with hundreds of libraries or dlls?

>At run time a dynamic call will look for a file called libNAME.so
>along the LD_LIBRARY_PATH, where NAME is that in the CALL, and it will
>load that and find the required entry point.

It will first look for the symbol NAME already loaded. If not found THEN it will load
libNAME.so.

>As you should be able to tell from the results in charles' 2nd message
>your BAD and WRONG advice has meant that his program does not work as
>he expected. He statically linked the dynamic library which will cause
>the CANCEL to fail to unload it and thus a reload does not find a new
>copy but reuses the old.

Wrong. If Cobol issues a dlclose() on libMYSUB1.so, even though it was 'statically' linked
with -l, it will be unloaded .. and reloaded the next time he calls it.

If it is packaged in a library with a hundred other programs, the whole library might be
unloaded, because the handle for NAME is the handle for libMYSUBS.so. Or Fujitsu might be
smart enough to know it wasn't dynamically loaded. If he really needs initial values, he
should use the Cobol INITIAL clause.

Incidentally, CANCEL is not guaranteed to unload the program your way, either. A
dynamically loaded library can only be unloaded when its user count is zero. If another
developer happens to be using the same called program, CANCEL will fail, and Cobol has no
way of checking for that. If you want to be hackerish, issue the CANCEL 100 times. Each
call to dlopen() subtracts 1 from the user count. Then listen for cursing from the next
cubicle. :) The reason Windows installers want you to reboot is because they don't have a
reliable way of deleting old dlls they just replaced. The solution is to call FreeLibrary
until it disappears from memory.
From: Robert on
On Thu, 31 Jan 2008 09:48:48 -0800 (PST), charles.goodman(a)bell.ca wrote:

>Thanks for the tips.
>Yes I needed to add my curent directory to LD_LIBRARY_PATH
>I also nneded to add "-L./" to the cobol command to compile the main
>program.

-L is used to override the user's LD_LIBRARY_PATH. It shouldn't be necessary on your own
machine.

>My compile commands, that work are:
>cobol -dy -shared -WC,"BINARY(BYTE)" -o libMYSUB1.so MYSUB1.cbl
>cobol -dy -shared -WC,"BINARY(BYTE)" -o libMYSUB2.so MYSUB2.cbl
>cobol -M -dy -WC,"BINARY(BYTE),DLOAD" -o MYMAIN -L./ -lMYSUB1 -lMYSUB2
>MYMAIN.cbl
>
>I am able to compile and execute. My simple programs are designed to
>allow me to see the functioning of CALL and CANCEL.....
>
>However the results is NOT exactly what I want. Using -l does not
>allow for proper functioning of the CANCEL verb (see pg 77 of user's
>guide). Once a subprogram is loaded with a CALL statement, it remains
>in memory regardless of CANCEL statements. The working-storage of the
>sub-program is not reinitialized upon a second CALL.

I answered Richard before reading this reply. Failure of the CANCEL means Fujitsu figured
out the library (.so) had not been dynamically loaded, so did not issue a dlclose(). If
you want the program initialized every time, use the INITIAL clause on PROGRAM-ID.

See my comments to Richard about the disadvantage of hundreds of little libraries.