bug-gnucobol
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: The next question


From: Brian Tiffin
Subject: Re: The next question
Date: Sun, 22 Mar 2020 04:53:28 -0400
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0 SeaMonkey/2.49.5

James Smith wrote:
> Brian Tiffin kindly showed me the error of my compile script. All OK now.
> Each module now compiles properly. Thank you, Brian. Now I would like to
> learn about CALLs. Here is my saga to date:
>
>
> I am trying to master Dynamic versus Static CALLs within GnuCOBOL.
>
> My compile script, below, is used for two situations, static and dynamic. I
> comment out the appropriate lines as needed to test each scenario.
>
> My CALLing program, source below, also has a variety of conditions that I
> comment out as needed to test the next variation.
>
> The CALLed program, source below, OPENs EXTEND a log file and writes two
> lines to it when it executes. This is the only evidence that it ran.
>
> Each compile command compiles clean. The result of each test run is noted
> against the actual CALL that generated that result in the source code.
> Currently all are commented out. Please believe me, I did run each
> instance. The execution sequence is to set up the calls in the source, set
> up the compile script to match that, run the compile, verify that it is
> clean and then run the result with "./calls" and look into the log file.
>
> It is evident that I can get the CALL to work. It is also evident that I do
> not understand what is wrong with the other attempts. I want to understand
> where I have gone wrong. Thank you for your assistance. I am willing to do
> whatever else may be needed to make this more clear or to cover instances
> of which I have not thought.
>
> #####################################################################
> This is the compile script.
> #!/bin/bash
> #! /home/james/cobolsandbox/contributions/compile-calls.sh
>    rm -v calls
> #! rm -v called  #! Leave this behind to test some Static calls
>
> echo "*>--------------------------------------------------------"
> #! Static
> #! This method works
> cobc -free -Xref -v -W -T calls.lst   -x -o calls     calls.cbl called.cbl
>
> #! Dynamic
> #! This method fails
> #! libcob: module 'called' not found
> #!cobc -free -Xref -v -W -T calls.lst   -x -o calls     calls.cbl
> #!echo "*>--------------------------------------------------------"
> #!cobc -free -Xref -v -W -T called.lst  -x -o called    called.cbl
>
> echo "*>--------------------------------------------------------"
>
> ls -alF call*
> #####################################################################
> This is the source of the program that CALLs
> *>      $ SET SOURCEFORMAT "FREE"
> *>------------------------------------------------
> IDENTIFICATION DIVISION.
> PROGRAM-ID.  calls.
>
> ENVIRONMENT DIVISION.
> CONFIGURATION SECTION.
>
> REPOSITORY.
>     FUNCTION ALL INTRINSIC.
>
> INPUT-OUTPUT SECTION.
> FILE-CONTROL.
>
> *>------------------------------------------------
> DATA DIVISION.
> FILE SECTION.
>
> *>------------------------------------------------
> WORKING-STORAGE SECTION.
> *>------------------------------------------------
> 01  WS-Pgm-To-Call-Full.
>     05                        PIC X(39) VALUE
>         "/home/james/cobolsandbox/contributions/".
>     05  WS-Pgm-To-Call        PIC X(10) VALUE "called    ".
> 01  WS-Pgm-To-Call-NoPath     PIC X(10) VALUE "called  ".
> 01  WS-Pgm-To-Call-Short      PIC X(10) VALUE "./called  ".
>
> *>------------------------------------------------
> PROCEDURE DIVISION.
> *>------------------------------------------------
> 000-Main.
>
> *> Static
> *>    CALL "./called"                           END-CALL.  *> THIS WORKS
> *>    CALL "called"                             END-CALL.  *> THIS WORKS
> *>    CALL WS-Pgm-To-Call-Full                  END-CALL.  *> THIS WORKS
> *>    CALL WS-Pgm-To-Call-Short                 END-CALL.  *> THIS WORKS
> *>    CALL WS-Pgm-To-Call-NoPath                END-CALL.  *> THIS WORKS
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call-Short  END-CALL.  *> THIS WORKS IF
> called exists in current directory!
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call-Short  END-CALL.  *> sh: 1:
> ./called: not found
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call-NoPath END-CALL.  *> sh: 1:
> called: not found
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call        END-CALL.  *> sh: 1:
> called: not found
> *>    CALL "SYSTEM" USING "called"              END-CALL.  *> sh: 1:
> called: not found
>
> *> Dynamic
> *>    CALL "./called"                           END-CALL.  *> libcob:
> module 'called' not found
> *>    CALL "called"                             END-CALL.  *> libcob:
> module 'called' not found
> *>    CALL WS-Pgm-To-Call-Full                  END-CALL.  *> libcob:
> module 'called' not found
> *>    CALL WS-Pgm-To-Call-Short                 END-CALL.  *> libcob:
> module 'called' not found
> *>    CALL WS-Pgm-To-Call-NoPath                END-CALL.  *> libcob:
> module 'called' not found
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call        END-CALL.  *> sh: 1:
> called: not found
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call-NoPath END-CALL.  *> sh: 1:
> called: not found
> *>    CALL "SYSTEM" USING WS-Pgm-To-Call-Short  END-CALL.  *> THIS WORKS
> *>    CALL "SYSTEM" USING "called"              END-CALL.  *> sh: 1:
> called: not found
>
> GOBACK.
>
> *>------------------------------------------------
> END PROGRAM calls.
> #####################################################################
> This is the source of the program to be CALLed
> *>>      $ SET SOURCEFORMAT "FREE"
> IDENTIFICATION DIVISION.
> PROGRAM-ID.  called.
>
> ENVIRONMENT DIVISION.
> CONFIGURATION SECTION.
>
> REPOSITORY.
>     FUNCTION ALL INTRINSIC.
>
> INPUT-OUTPUT SECTION.
> FILE-CONTROL.
>     SELECT Log-File
>         ASSIGN DISK "./logs/main.log"
>         FILE STATUS IS WS-StatusLOG
>         ORGANIZATION LINE SEQUENTIAL
>         SHARING ALL.
>
> DATA DIVISION.
> FILE SECTION.
> FD  Log-File.
> 01  Log-File-Printline          PIC X(80).
>
> WORKING-STORAGE SECTION.
> 01  WS-Pgm-ID                   PIC X(10) VALUE "called".
>
> 01  WS-StatusLOG                PIC X(02).
>
> 01  WS-Log-Line-1.
>     05  Pgm-ID                  PIC X(10) VALUE SPACE.
>     05                          PIC X(01) VALUE SPACE.
>     05  Msg                     PIC X(49) VALUE SPACE.
>
> PROCEDURE DIVISION.
> 000-Main.
>     MOVE WS-Pgm-ID TO Pgm-ID      OF WS-Log-Line-1.
>     MOVE "Begin job" TO Msg       OF WS-Log-Line-1.
>     OPEN EXTEND Log-file.
>     WRITE Log-File-Printline
>       FROM WS-Log-Line-1
>       AFTER ADVANCING 1
>     END-WRITE.
>
>     MOVE "End job"   TO Msg       OF WS-Log-Line-1.
>     WRITE Log-File-Printline
>       FROM WS-Log-Line-1
>       AFTER ADVANCING 1
>     END-WRITE.
>     CLOSE Log-File.
>     GOBACK.
>
> END PROGRAM called.
>
>
Hello, James.

Another long one.

Do you mind using a forum?  I'm not a huge fan of long conversations
using the bug tracking mailing list (or any mailing list, to be honest)
and we may have lots to discuss, with some back and forths.

https://sourceforge.net/p/open-cobol/discussion/

We've set that up to allow Anonymous posting, so you won't need to
create a SourceForge account if you don't want to (I will say there are
many benefits if you do), but a moderator needs to notice and approve
the messages from anon before it shows up for everyone.

https://sourceforge.net/user/registration

####

To a little bit of the questions.

You need to keep in mind that CALL uses linker symbol names, whether
static or dynamic.  This is completely different from external programs
in the file system.

I'm utterly surprised that CALL "./called" actually worked, doesn't
here, but I may have missed a step in the quick testing...  (I tried
trunk and it does work, the dot-slash is stripped off - more on that in
a bit).

GnuCOBOL has a STATIC modifier for the CALL statement.  I rarely used
it, because older versions of cobc had a tough time syncing the call
frames for the experiments I run, due to lack of C headers during a
compile.  That is a much improved situation now, and I'm starting to use
CALL STATIC "func" more often; but an old dog, new trick.

CALL "subprog"

is a dynamic lookup, and requires a library search path at run-time. 
LD_LIBRARY_PATH and friends.  The ON EXCEPTION phrase of CALL can be
used to test for not found.

CALL "subprog" ON EXCEPTION DISPLAY "no linkage to subprog" END-CALL

CALL STATIC "subprog"

includes the object code in the binary, so no need for run-time
searching, and no chance of firing an ON EXCEPTION clause.  We actually
made that an error, and I'm protesting...  it should be a warning,
otherwise you need to gut a lot more code to run quick tests between
STATIC and normal CALL, and so what if the exception never fires (while
developing).

CALL "SYTEM" USING "called" is not a static or dynamic call really. 
It's an internal libcob service that invokes a shell.  The arguments
will be purely filesystem names, not link symbol (C function) names.

Your sample, the called.cob has a program-id of "called", so the C
linker name is "called".  This just happens to match the name on the
file system for "called", the program on disk.

We also have helpers in libcob during dynamic lookup.  If GnuCOBOL is
looking for a symbol it will try module.so (an external filename) and
look for a symbol "module".  (libcob will look for "called" inside a
file named "called.so", which your script sometimes creates when not
using cobc -x).

Try reading, man nm.   nm is a program to display function names within
object files.

So, many, details, to go over.  I'd really prefer using the SourceForge
discussion groups, James.  :-)

The version of cobc I use day to day is old now, the
gnu-cobol-builtin-script branch.  It does not allow CALL "./called" to
work, there is no symbol "./called".

Version from trunk, does work with "./called".  I'm not sure I like
that, but I can see how the "./" part is ignored during the search for
the dynamic symbol.


So there are a few things in play here.

Quotes below are just for effect, there are no double-quotes in any of
the "name" examples

External filename.  Given "name.cob", cobc can generate a "name" file
(for -x), a "name.so" shared object file (for -m), a "name.o" file for
-c (just an object file) and some others like C source or assembly.

Within "name", there will be a symbol called "main", which is a defacto
standard entry point.  There will also be a symbol spelled "name" inside
the "name" file.  In your sample case, that would be "called" inside
"called.so".

Symbol names never have file system paths included (or file type
extensions).  They are strings in a table in a binary object file, (ELF
format is pretty much all I ever bump into using GNU/Linux).

Forget about using CALL "SYSTEM" for now, that has nothing to do with
link time or run-time binary function names.  The program-id is not
necessarily the same thing as the external file system name.  CALL
"SYSTEM" is just invoking a shell and asking to it to look up and run a
program (usually via PATH).

Come on to the forum, James, and I/we can run you through some
examples.  It's hard to get head round, really, as there are like five
things, all similar, but different and they can all have the same
"name".  :-)

If you don't like forums we can continue here, James.  But I spent quite
a few tens of hours figuring out a syntax highlighter for the FAQ, and
it just happens to also be used by SourceForge, so I get to puff chest
when I see the COBOL listings in colour in the forums.  ;-)

In short

CALL "called"  will look for called.so in the run time dynamic linker
search path and look for a symbol "called" inside that file.

CALL STATIC "called" is static linkage, and cobc will need to know where
the symbol is at compile time (usually by just adding the filename that
holds that program-id to a cobc command, but these can also come from
within libraries.

CALL "SYSTEM" is a red herring, ignore for now, it has nothing to do
with linkage, but with shells and command line processing.

libcob tries to help, it seems it now strips off "./" from CALL symbols
(Boo, but I can see it helping, so it's more of a shock that will go
away over time).  libcob run-time will look in current dynamic link
cache for the CALL symbol, then look in libraries, then look in a shared
object file (with the same name as used by CALL) for the symbol, and it
might even be a builtin stock library system service like in the case of
CALL "SYSTEM" or CALL "CBL_GC_HOSTED".  (Use cobc --list-system to see
the list of available system routines)

I'll admit to not being up on all the new features of CALL STATIC that
Simon and team have added to trunk, so I'm looking forward to discussing
this more, James.  I'm a few years behind in maintaining the FAQ, and
kinda still favour my old scripting build when I run cobc now-a-days, so
missing out on all the technical goodies and improvements that are being
added in GC 3 and 4.  I have catching up to do, and if we discuss this
on the forum, it'll give me a leg up on those efforts.

Cheers,
Brian




reply via email to

[Prev in Thread] Current Thread [Next in Thread]