Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How does COBOL detect a recursive call?

654 views
Skip to first unread message

John McKown

unread,
Aug 9, 2016, 10:41:09 AM8/9/16
to
This is a kind of curiosity question. Unless a COBOL program is compiled
with the THREAD option and the RECURSIVE clause on the PROGRAM-ID, the
program cannot CALL itself. I have also found out that if you use an ENTRY
statement and the compile NAME(ALIAS), you cannot do a CALL of the alias
from the "main" program either. E.g. if you have a PROGRAM-ID. A. and an
ENTRY 'B', then you cannot CALL 'B' while running A. I am thinking this
must be in some way related to the fact that 'A' and 'B' share the same
WORKING-STORAGE area. But I was just wondering if anybody knows how this is
implemented. Of course, it is probably likely to change between releases,
so it's not something I could depend on.

Why the interest? Because while talking with Chuck Hardee about having an
LE condition handler in the same source member (as an ENTRY) as the main
COBOL routine, we found that the run-unit will abend with a U4087-2 and
some messages about recursive invocation. So as a test, I compiled a sample
which got the U4087-2 with the THREAD option and RECURSIVE clause, and that
ran successfully. However the THREAD option comes with some possibley nasty
side restrictions. In particular, no INITIAL clause in the PROGRAM-ID
sentence and, worse, no use of SORT / MERGE verbs.

--
Klein bottle for rent -- inquire within.

Maranatha! <><
John McKown

----------------------------------------------------------------------
For IBM-MAIN subscribe / signoff / archive access instructions,
send email to list...@listserv.ua.edu with the message: INFO IBM-MAIN

John McKown

unread,
Aug 9, 2016, 10:59:22 AM8/9/16
to
On Tue, Aug 9, 2016 at 9:40 AM, John McKown <john.arch...@gmail.com>
wrote:

> This is a kind of curiosity question. Unless a COBOL program is compiled
> with the THREAD option and the RECURSIVE clause on the PROGRAM-ID, the
> program cannot CALL itself. I have also found out that if you use an ENTRY
> statement and the compile NAME(ALIAS), you cannot do a CALL of the alias
> from the "main" program either. E.g. if you have a PROGRAM-ID. A. and an
> ENTRY 'B', then you cannot CALL 'B' while running A. I am thinking this
> must be in some way related to the fact that 'A' and 'B' share the same
> WORKING-STORAGE area. But I was just wondering if anybody knows how this is
> implemented. Of course, it is probably likely to change between releases,
> so it's not something I could depend on.
>
> Why the interest? Because while talking with Chuck Hardee about having an
> LE condition handler in the same source member (as an ENTRY) as the main
> COBOL routine, we found that the run-unit will abend with a U4087-2 and
> some messages about recursive invocation. So as a test, I compiled a sample
> which got the U4087-2 with the THREAD option and RECURSIVE clause, and that
> ran successfully. However the THREAD option comes with some possibley nasty
> side restrictions. In particular, no INITIAL clause in the PROGRAM-ID
> sentence and, worse, no use of SORT / MERGE verbs.
>

​Well, here I am talking to myself again. At least I'm not, yet, into the 3
way arguments with myself. But it turns out that I misread the manual.
RECURSIVE is required on the PROGRAM-ID if THREAD is used, but not vice
versa. So it appears that all I really need is the RECURSIVE clause on the
PROGRAM-ID and not the THREAD compile option. But I'm still mildly curious
about how COBOL detects recursion, if you know off-hand.​

Bill Woodger

unread,
Aug 9, 2016, 12:26:07 PM8/9/16
to
Conceptually, it sets a flag at the start of execution, and resets it when the GOBACK (or other way to get out of a program) is processed.

Prior to setting the flag it tests to see if it is still (already) set. If so, the program has been entered recursively, either directly or by CALLing (or otherwise transferring control to) a program which in turn CALLs the original.

Mike Schwab

unread,
Aug 9, 2016, 12:28:48 PM8/9/16
to
http://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/com.ibm.zos.v2r1.ieab100/reus.htm
When you link edit, you indicate the re-usability of the program.
When the program runs, it reuses the same program if re-entrant. Each
use has a different set of registers and working storage.
Serially reusable can be self modifying (storing into load module
areas), but can be reused after completing. Needs a new copy for a
simultaneous use.
None means the program must be reloaded from disk for every use.

When you run a program, the LOAD macro examines the directory and
loads as appropriate.
http://www.longpelaexpertise.com/ezine/ReentrantBeginners.php



On Tue, Aug 9, 2016 at 9:59 AM, John McKown
--
Mike A Schwab, Springfield IL USA
Where do Forest Rangers go to get away from it all?

Hardee, Chuck

unread,
Aug 9, 2016, 12:37:40 PM8/9/16
to
Okay, let's run with this one.

If program A has an entry, B, and the program is compiled with NAME(ALIAS), when the program is linked, there will be an entry for A and an entry for B as an ALIAS of A.

When A is executed, a statement in the program says SET XXXX TO ENTRY B where XXXX is defined as PROCEDURE-POINTER.

Does a separate copy of the load module get loaded as B when this SET statement is executed or does the runtime simply gain access to the entry point B within the currently loaded version of A?

If a separate copy of the load module is loaded as B, where is the recursion?
If a separate copy of the load module is not loaded, I can see the recursion.

C-

Charles (Chuck) Hardee
Senior Systems Engineer/Database Administration
EAS Information Technology

Thermo Fisher Scientific
300 Industry Drive | Pittsburgh, PA 15275
Phone +1 (724) 517-2633 | Mobile +1 (412) 877-2809 | FAX: +1 (412) 490-9230
Chuck....@ThermoFisher.com | www.thermofisher.com

WORLDWIDE CONFIDENTIALITY NOTE: Dissemination, distribution or copying of this e-mail or the information herein by anyone other than the intended recipient, or an employee or agent of a system responsible for delivering the message to the intended recipient, is prohibited. If you are not the intended recipient, please inform the sender and delete all copies.

Bill Woodger

unread,
Aug 9, 2016, 1:03:25 PM8/9/16
to
Well, the SET ... TO ENTRY ... definitely loads (with the assumption that the module is not already in memory, in which case it just gives you the entry-point address). At least ordinarily. I don't know about the ENTRY which is in the same program. An ENTRY in a different program (with an ALIAS) should just act like any other module.

As to why it then wouldn't work... I guess it (the COBOL compiler) is being too clever, and it knows that your ENTRY is in the same program. Or, for the SET knows it is in the same program... or both... or something else.

As I mentioned before, it is an interesting situation, but I can't see application beyond that - even if you work out how to get it going - with V3.4.x, there's not necessarily a guarantee that it will do the same thing with V5+. It is neither documented as working, nor documented as not working. That's a pretty wide grey area. If your site is the only one doing this, you're not going to get a fix for V8 that just happens to have come along and broken whatever you work out (if you work something out).

Have you a cast-iron reason for sticking with the ENTRY/ALIAS over the two-program approach?

John McKown

unread,
Aug 9, 2016, 1:08:11 PM8/9/16
to
On Tue, Aug 9, 2016 at 11:28 AM, Mike Schwab <mike.a...@gmail.com>
wrote:

> http://www.ibm.com/support/knowledgecenter/SSLTBW_2.1.0/
> com.ibm.zos.v2r1.ieab100/reus.htm
> When you link edit, you indicate the re-usability of the program.
> When the program runs, it reuses the same program if re-entrant. Each
> use has a different set of registers and working storage.
> Serially reusable can be self modifying (storing into load module
> areas), but can be reused after completing. Needs a new copy for a
> simultaneous use.
> None means the program must be reloaded from disk for every use.
>
> When you run a program, the LOAD macro examines the directory and
> loads as appropriate.
> http://www.longpelaexpertise.com/ezine/ReentrantBeginners.php
>
>
​That explains why my version of the program does what it does. I compile
my COBOL with the RENT compiler option, and use RENT,REUS on the link. So,
at least in my case, everything makes sense. I'm a bit OCD about trying to
make all my code RENT,REUS. My main way to think of this is "would this
still run correctly if it were burned into ROM?" I try to make the answer
to that YES.​

Bill Woodger

unread,
Aug 9, 2016, 5:24:03 PM8/9/16
to
Reading your post rather than going from the title, the U4087 2 is Language Environment abend for when an registered abend-handler has been entered a subsequent time before processing of the original abend has completed - the handler written in COBOL failed, and was entered again to process the failure.

Can you show the IGZ message number that you got, please?

John McKown

unread,
Aug 9, 2016, 5:36:10 PM8/9/16
to
On Tue, Aug 9, 2016 at 4:23 PM, Bill Woodger <bill.w...@gmail.com> wrote:

> Reading your post rather than going from the title, the U4087 2 is
> Language Environment abend for when an registered abend-handler has been
> entered a subsequent time before processing of the original abend has
> completed - the handler written in COBOL failed, and was entered again to
> process the failure.
>
> Can you show the IGZ message number that you got, please?
>
>
​16.33.31 JOB19047 +CEE0374C CONDITION=CEE0001S TOKEN=00030001 59C3C5C5
00000001 048
048 WHILE RUNNING PROGRAM CBLHDLR2 WHICH STARTS AT
0B200A18
048 AT THE TIME OF INTERRUPT
048 PSW 00080000 800180D6
048 GPR 0-3 00027330 00027118 0B292AC4 0B29226C
048 GPR 4-7 00027128 0B29226C 00047488 00027118
048 GPR 8-B 00000002 0B292118 00047038 8B21DDE0
048 GPR C-F 00021B88 00027150 800180D6 8514E450
16.33.31 JOB19047 +CEE0374C CONDITION=IGZ0064S TOKEN=00030040 59C9C7E9
00000002 049
049 WHILE RUNNING PROGRAM IGZCMSG WHICH STARTS AT
8B26C058
049 AT THE TIME OF INTERRUPT
049 PSW 00080000 800180D6
049 GPR 0-3 0002AB60 0002A820 0002A820 00017038
049 GPR 4-7 00017038 0002A850 00017038 0002A810
049 GPR 8-B 00012A80 0B292118 00047038 8514F008
049 GPR C-F 00021B88 0002AB60 800180D6 8514E450

The latter message repeats 10 times, with the 00000002 at the end of the
first line incrementing by 1 each time until == 0000000B. Followed by:

16.33.31 JOB19047 IEA995I SYMPTOM DUMP OUTPUT 059
059 USER COMPLETION CODE=4087 REASON CODE=00000002
059 TIME=16.33.31 SEQ=29342 CPU=0000 ASID=0051
059 PSW AT TIME OF ERROR 078D1000 85108CEC ILC 2 INTC
0D
059 NO ACTIVE MODULE FOUND
059 NAME=UNKNOWN
059 DATA AT PSW 05108CE6 - 00181610 0A0DA7F4 001C1811
059 GR 0: 84000000 1: 84000FF7
059 2: 00000002 3: 00017038
059 4: 05141E78 5: 05141FF0
059 6: 00020340 7: 000207F0
059 8: 80000000 9: 00050FA6
059 A: 00000001 B: 85108C18
059 C: 00021B88 D: 0004EFA8
059 E: 8001804A F: 00000002
059 END OF SYMPTOM DUMP
16.33.31 JOB19047 IEF450I TSH009A1 CBLHDLR2 - ABEND=S000 U4087
REASON=00000002 060
​



--
Klein bottle for rent -- inquire within.

Maranatha! <><
John McKown

Bill Woodger

unread,
Aug 9, 2016, 6:25:38 PM8/9/16
to
Thanks :-)

Looks like your LE has about 10 levels of "depth". The handler is getting invoked, and then itself abending/raising a condition, so it gets invoked again, and does the same thing - until LE runs out of patience that was defined for it.

The IGZMSG is the module which informs of a run-time problem. You earlier mentioned a COBOL message about recursion? IGZMSG would cause the message to be output, and I was wondering if it was a 15S or a 64S IGZ message.

Basically, the handler has been entered twice. The first time presumably the intended one - and then again. Then it hits the "invalid recursion" problem, and just keeps triggering the handler.

I can't see that the initial use of the handler could trigger the "recursive" problem, because it should be an entirely separate executable from the "main" program.

With RECURSIVE on the PROGRAM-ID, the handler will be entered twice still (I'm assuming) but since there is no code to deal with the second condition, it will be ignored by the handler.

To confirm that the ENTRY is not actually being used recursively, that it is in a separate executable (only worth checking because if it isn't, this problem would be caused) I'd REDEFINES the PROCEDURE-POINTER as PIC X(9) and DISPLAY it after the SET. Before that SET I'd put another SET ... ENTRY ... to the "main" program-name, and again DISPLAY that. The two addresses DISPLAYed should not be close together (address of the ENTRY should be further away than the address of the PROGRAM-ID, by at least the length of the program in its entirety).

Given that that checks out, I'd DISPLAY the information in the handler, and see how much appears. If two conditions are being presented, knowledge of the second condition will be useful.

Does your program on Git work, or exhibit the problem? If it doesn't exhibit the problem, what needs to be done to it to do so?

Bill Woodger

unread,
Aug 9, 2016, 6:52:15 PM8/9/16
to
OK, it is the RENT or REUS (either will do) on the link-edit/bindering.

Without RENT/REUS you get a new executable for free. With RENT/REUS you get to "share" the original program, but it is necessarily a "recursive" use, so you get the "IGZ0064S A recursive call to active program..." message. Which is why IBM say you must CANCEL before the CALL to the ENTRY, which you can't do if the CALL is to an ENTRY in the same program. PROGRAM-ID ... IS RECURSIVE "gets around" the IGZ0064S, so there won't be a second condition, which causes another, and another. So LE will be happy.

So, you've discovered a way to nearly get a CALL to an ENTRY point with an ALIAS to work like it used to :-)

However, there is overhead. The recursive CALL will share WORKING-STORAGE, but pretty much everything else will be initialised on each CALL, and then all thrown away on each GOBACK (since it is not actually recursing). For a one-shot use, this will not matter.

Safe to use? Well, understanding how it works/doesn't work wasn't easy for me :-)

Here's an example of the generated code from the COBOL compiler showing the recursion checking:

ICM 2,15,336(9) IPCB=1+16
L 11,40(0,12) PBL=1
BC 8,210(0,11) GN=6(0002E6)
L 3,92(0,9) TGTFIXD+92
L 15,244(0,3) V(IGZCMSG )
LA 1,206(0,10) PGMLIT AT +202
BASR 14,15

PGMLIT AT +202 is X'40', which is the 64 for the IGZ message.

There is similar code generated for an ENTRY.

And here's the code from the GOBACK clearing up to say things will be OK for another CALL:

L 3,336(0,9) IPCB=1+16
S 3,0(0,12) SYSLIT AT +0
ST 3,336(0,9) IPCB=1+16

Peter Hunkeler

unread,
Aug 10, 2016, 1:17:17 AM8/10/16
to


> I'm a bit OCD about trying to make all my code RENT,REUS. My main way to think of this is "would this still run correctly if it were burned into ROM?" I try to make the answer to that YES.​


Put all your RENT modules into an APF authorized load library. No AC(1) required! The code will be loaded into subpool 252 key 0 storage. It will blow up with S0C4-4 if not really reentrant.


--
Peter Hunkeler

Hardee, Chuck

unread,
Aug 10, 2016, 5:36:45 AM8/10/16
to
Bob,

Since John is working with a stripped down copy of my program I resurrected the copy of the program with my debugging displays in it where I had already coded the displays for the two addresses you asked about.

Displaying the main entry point address, that is, the name of the program as coded in the PROGRAM-ID clause, the address displayed is 11E00A10.
Displaying the program name as coded on the ENTRY statement, the address displayed is 11E02C78.
The difference between these two address is x'2268'.
According to the linkage map, the offset to the ENTRY statement name is x'2268'.

So, it appears that the runtime is getting the address of the code that is within the initially loaded module, not a fresh copy.

So, looking at the link output, it was reported that the module was linked as:
RENT YES
REUS YES

So, it is definitely a recursive call.

Chuck

Charles (Chuck) Hardee
Senior Systems Engineer/Database Administration
EAS Information Technology

Thermo Fisher Scientific
300 Industry Drive | Pittsburgh, PA 15275
Phone +1 (724) 517-2633 | Mobile +1 (412) 877-2809 | FAX: +1 (412) 490-9230
Chuck....@ThermoFisher.com | www.thermofisher.com

WORLDWIDE CONFIDENTIALITY NOTE: Dissemination, distribution or copying of this e-mail or the information herein by anyone other than the intended recipient, or an employee or agent of a system responsible for delivering the message to the intended recipient, is prohibited. If you are not the intended recipient, please inform the sender and delete all copies.

-----Original Message-----

Bill Woodger

unread,
Aug 10, 2016, 6:50:03 AM8/10/16
to
Hi Chuck,

Thanks. Yes, I was able to recreate the issue after making the post with the questions in.

RENT,REUS or REUS or RENT, ie any combinaton, on the linkediting/bindering causes no new executable to be loaeded in this case, so tha ALIASed ENTRY is in the same executable as the CALL.

This causes COBOL to notice that the program has been entered again, before control has left the program (entered a subsequent time, prior to a GOBACK). This causes the IGZ0064S message to be attempted, which causes the handler (ENTRY) to be entered again, which causes (attempts) the IGZ message again, until LE reaches its defined limit for the number of "nested" conditions it is supposed to be able to deal with (user option).

Making the program RECURSIVE (PROGR-ID. xxxx IS RECURSIVE) effectively removes the COBOL check that the program has been subsequently re-entered before a GOBACK has been processed, so that handler is not entered a second time.

So, you have a situation which "works", or more than one. Without RENT or REUS on the linkedit/bindering, you should get a new executable for the SET for the ENTRY and not have a problem with IGZ0064S.

With RENT or REUS and using PROGRAM-ID .... IS RECURSIVE you should not have a problem, as long as you bear in mind that you are now "sharing" the WORKING-STORAGE, and that there are special-registers which you are not sharing.

The IBM-recommended way to use the ENTRY for a dynamic CALL is to use CANCEL for the PROGRAM-ID to be able to use the ENTRY and for the ENTRY to be able to use the PROGRAM-ID (or another ENTRY). You can't do the CANCEL from *within* the program, so that is out.

There are at least two ways that a CALL to an ENTRY within the same program *should* be able to be made to work, even though there is no documentation for the CALL to an ENTRY within the same program, and I've never heard of it being done on the Mainframe, those outline above.

I'd personally feel exposed with "we can kind of get it working, it is not straightforward to understand, and isn't documented by IBM".

Note, I've reproduced with an "ordinary" CALL to a an ENTRY, not with an ENTRY which is established as a handler.

I'd do it as two programs, unless there is an absolute, paramount, overriding reason to do it as one program. It is difficult for me to imagine what that reason may be.

You currently have the "already needs a CBL/PROCESS/PARM for NAME(ALIAS), now also needs IS RECURSIVE or not to use RENT or REUS on the linkedit/binder".

John McKown

unread,
Aug 10, 2016, 9:10:03 AM8/10/16
to
On Wed, Aug 10, 2016 at 12:16 AM, Peter Hunkeler <ph...@gmx.ch> wrote:

>
>
> > I'm a bit OCD about trying to make all my code RENT,REUS. My main way to
> think of this is "would this still run correctly if it were burned into
> ROM?" I try to make the answer to that YES.​
>
>
> Put all your RENT modules into an APF authorized load library. No AC(1)
> required! The code will be loaded into subpool 252 key 0 storage. It will
> blow up with S0C4-4 if not really reentrant.
>

​That would work. And _I_ can do it, being the senior z/OS sysprog & senior
RACF person (and secondary tape librarian and programmer mentor and ... )
However, in a properly audited shop​, this would likely cause a "conniption
fit" with the auditors. If I am reading the z/OS 2.2 manual correctly, if
you do a "SETPROG REFPROT" command, then all modules which are loaded,
regardless of origin, which are marked REUS(REFR) will be loaded into key 0
storage.
ref:
https://www.ibm.com/support/knowledgecenter/SSLTBW_2.2.0/com.ibm.zos.v2r2.ieab100/reus.htm
<quote>

REFRThe module is refreshable. It can be replaced by a new copy during
execution without changing the sequence or results of processing. A
refreshable module cannot be modified during execution.

A module can only be refreshable if all the control sections within it are
refreshable. The refreshable attribute is negated if any input modules are
not refreshable. Refreshable modules are also reenterable and serially
reusable.

The refreshable attribute can be specified for any nonmodifiable module.

If REFRPROT has been specified on the SETPROG command or in parmlib member
PROGxx, the module is protected from modification by placing it in key 0,
non-fetch protected storage, and page protecting the whole pages. Note that
debuggers, such as TSO TEST and UNIX debugging environments, will override
REFRPROT protection for particular TCBs so that they can modify module
storage in order to set breakpoints.

<quote>


>
>
> --
> Peter Hunkeler
>
>
--
Klein bottle for rent -- inquire within.

Maranatha! <><
John McKown

John McKown

unread,
Aug 10, 2016, 9:16:47 AM8/10/16
to
On Tue, Aug 9, 2016 at 5:52 PM, Bill Woodger <bill.w...@gmail.com> wrote:

> OK, it is the RENT or REUS (either will do) on the link-edit/bindering.
>
> Without RENT/REUS you get a new executable for free. With RENT/REUS you
> get to "share" the original program, but it is necessarily a "recursive"
> use, so you get the "IGZ0064S A recursive call to active program..."
> message. Which is why IBM say you must CANCEL before the CALL to the ENTRY,
> which you can't do if the CALL is to an ENTRY in the same program.
> PROGRAM-ID ... IS RECURSIVE "gets around" the IGZ0064S, so there won't be a
> second condition, which causes another, and another. So LE will be happy.
>

​Ah, so my OCD about making everything RENT/REFR has risen up to bite me in
the butt.​



>
> So, you've discovered a way to nearly get a CALL to an ENTRY point with an
> ALIAS to work like it used to :-)
>
> However, there is overhead. The recursive CALL will share WORKING-STORAGE,
> but pretty much everything else will be initialised on each CALL, and then
> all thrown away on each GOBACK (since it is not actually recursing). For a
> one-shot use, this will not matter.
>
> Safe to use? Well, understanding how it works/doesn't work wasn't easy for
> me :-)
>
> Here's an example of the generated code from the COBOL compiler showing
> the recursion checking:
>
> ICM 2,15,336(9) IPCB=1+16
> L 11,40(0,12) PBL=1
> BC 8,210(0,11) GN=6(0002E6)
> L 3,92(0,9) TGTFIXD+92
> L 15,244(0,3) V(IGZCMSG )
> LA 1,206(0,10) PGMLIT AT +202
> BASR 14,15
>
> PGMLIT AT +202 is X'40', which is the 64 for the IGZ message.
>
> There is similar code generated for an ENTRY.
>
> And here's the code from the GOBACK clearing up to say things will be OK
> for another CALL:
>
> L 3,336(0,9) IPCB=1+16
> S 3,0(0,12) SYSLIT AT +0
> ST 3,336(0,9) IPCB=1+16
>
>
>
​I really appreciate the time and effort you've taken to look into this and
explain it to me. I now know enough to be really dangerous! :-)​



--
Klein bottle for rent -- inquire within.

Maranatha! <><
John McKown

Hardee, Chuck

unread,
Aug 10, 2016, 9:17:26 AM8/10/16
to
The wherefores of using a main program and an ENTRY versus 2 programs is a political battle I am not prepared or willing to fight.
When initially assigned this project I was hoping that my Systems status within the company would grant me some carte blanche in how I engineered the solution but, alas, I was mistaken.

Suffice it to say, until/unless I find a technical problem to warrant the multiple program construct, or even the multiple programs per member construct, I am stuck with using the COBOL language verbs as they have been engineered. If, and when, they fail to function, I will have the ammunition I need to push for one of the other programming constructs.

I do appreciate all of your narratives of what was occurring.

Chuck

Charles (Chuck) Hardee
Senior Systems Engineer/Database Administration
EAS Information Technology

Thermo Fisher Scientific
300 Industry Drive | Pittsburgh, PA 15275
Phone +1 (724) 517-2633 | Mobile +1 (412) 877-2809 | FAX: +1 (412) 490-9230
Chuck....@ThermoFisher.com | www.thermofisher.com

WORLDWIDE CONFIDENTIALITY NOTE: Dissemination, distribution or copying of this e-mail or the information herein by anyone other than the intended recipient, or an employee or agent of a system responsible for delivering the message to the intended recipient, is prohibited. If you are not the intended recipient, please inform the sender and delete all copies.


-----Original Message-----
From: IBM Mainframe Discussion List [mailto:IBM-...@LISTSERV.UA.EDU] On Behalf Of Bill Woodger
Sent: Wednesday, August 10, 2016 6:50 AM
To: IBM-...@LISTSERV.UA.EDU
Subject: How does COBOL detect a recursive call?

Bill Woodger

unread,
Aug 10, 2016, 5:04:11 PM8/10/16
to
Thanks, Chuck. Tough sitch.

I think as definitive as you are going to get, in a documentary sense, is this, from the Programming Guide (doesn't matter which version):

"Calling alternate entry points

Static calls to alternate entry points work without restriction."

I made a static CALL to an ENTRY in the same program (without IS RECURSIVE on the PROGRAM-ID), and it failed with "IGZ0064S A recursive call to active program STAB48 in compilation unit STAB48 was attempted." (Note that the message reports for the PROGRAM-ID name, not the ENTRY name).

Since this does not work "without restriction" for an ENTRY then I conclude that a CALL to an ENTRY within the same program is not valid, although not explicitly documented as either valid nor invalid.

With the static CALL, using IS RECURSIVE does prevent the IGZ0064S, but that would count as a "restriction" to my mind - "must use IS RECURSIVE if CALLing an ENTRY in the from the same program which contains the ENTRY".

I think I've convinced myself that although it can be made to work, after a fashion, (IS RECURSIVE) it is not designed to work, so may break when the compiler changes.

And with all those little things it needs to get it to approximately work, when someone misses one or more of those in the future they are going to waste a lot of time working out what has happened, and how to fix it, and why.

That's as close as I can get to what I think you want :-) Good luck!

John McKown

unread,
Aug 10, 2016, 7:47:07 PM8/10/16
to
On Wed, Aug 10, 2016 at 4:04 PM, Bill Woodger <bill.w...@gmail.com>
wrote:

> Thanks, Chuck. Tough sitch.
>
> I think as definitive as you are going to get, in a documentary sense, is
> this, from the Programming Guide (doesn't matter which version):
>
> "Calling alternate entry points
>
> Static calls to alternate entry points work without restriction."
>
> I made a static CALL to an ENTRY in the same program (without IS RECURSIVE
> on the PROGRAM-ID), and it failed with "IGZ0064S A recursive call to active
> program STAB48 in compilation unit STAB48 was attempted." (Note that the
> message reports for the PROGRAM-ID name, not the ENTRY name).
>
> Since this does not work "without restriction" for an ENTRY then I
> conclude that a CALL to an ENTRY within the same program is not valid,
> although not explicitly documented as either valid nor invalid.
>
> With the static CALL, using IS RECURSIVE does prevent the IGZ0064S, but
> that would count as a "restriction" to my mind - "must use IS RECURSIVE if
> CALLing an ENTRY in the from the same program which contains the ENTRY".
>
> I think I've convinced myself that although it can be made to work, after
> a fashion, (IS RECURSIVE) it is not designed to work, so may break when the
> compiler changes.
>
> And with all those little things it needs to get it to approximately work,
> when someone misses one or more of those in the future they are going to
> waste a lot of time working out what has happened, and how to fix it, and
> why.
>

​Hum, I would guess this will be a case of "20 lines of code and 200 lines
of comments (excluding cursing)"​



>
> That's as close as I can get to what I think you want :-) Good luck!
>
> ----------------------------------------------------------------------
> For IBM-MAIN subscribe / signoff / archive access instructions,
> send email to list...@listserv.ua.edu with the message: INFO IBM-MAIN
>



--
Klein bottle for rent -- inquire within.

Maranatha! <><
John McKown

Bill Woodger

unread,
Aug 11, 2016, 1:48:51 AM8/11/16
to
On Thursday, 11 August 2016 01:47:07 UTC+2, John McKown wrote:
...>
> ​Hum, I would guess this will be a case of "20 lines of code and 200 lines
> of comments (excluding cursing)"​
>
>
>
> >

Excluding cursing, and including recursing.

Any IT management who chooses that route over TwoSimpleProgramsWithNothingButOrdinaryCodeCompile/LinkProcessingAndOrdinaryRunTime. is... well, choose your own ending.

Remember, there is Frank's suggestion to have the two programs in one source and compile them together, like they have some deep affinity just through proximity, that may serve the "do it the way I say" people.

One COBOL program doing two things (and being shoe-horned with a blow-torch to do so) vs two programs *with identical, as in identical, really the same, except for no ENTRY* (Ok, not really identical, but you know what I mean) code. That's surely easy, even for a CS Grad?

John McKown

unread,
Aug 11, 2016, 8:07:13 AM8/11/16
to
On Thu, Aug 11, 2016 at 12:48 AM, Bill Woodger <bill.w...@gmail.com>
wrote:

> On Thursday, 11 August 2016 01:47:07 UTC+2, John McKown wrote:
> ...>
> > ​Hum, I would guess this will be a case of "20 lines of code and 200
> lines
> > of comments (excluding cursing)"​
> >
> >
> >
> > >
>
> Excluding cursing, and including recursing.
>
> Any IT management who chooses that route over
> TwoSimpleProgramsWithNothingButOrdinaryCodeCompile/
> LinkProcessingAndOrdinaryRunTime. is... well, choose your own ending.
>
> Remember, there is Frank's suggestion to have the two programs in one
> source and compile them together, like they have some deep affinity just
> through proximity, that may serve the "do it the way I say" people.
>

​Hum, that wouldn't work here. ​I'm fairly sure the CA-Endevor will barf up
its lungs if you try to put two source modules, which create two load
modules / program objects, into a single source member. It wouldn't be able
to 1:1 track an executable and associated source member.



>
> One COBOL program doing two things (and being shoe-horned with a
> blow-torch to do so) vs two programs *with identical, as in identical,
> really the same, except for no ENTRY* (Ok, not really identical, but you
> know what I mean) code. That's surely easy, even for a CS Grad?
>

--
Klein bottle for rent -- inquire within.

Maranatha! <><
John McKown

Bill Woodger

unread,
Aug 11, 2016, 10:25:19 AM8/11/16
to
Yes, I'd not suggest compiling two separate programs as a single source, except for the idea that they (the Manglerment) seem to want it done in one "program". I'd kind of hope it doesn't fit into their procedures either - even though it is as "logically equivalent" to the ENTRY idea as it is the separate programs idea.

A twisted, prone to misunderstanding, way with ENTRY to make one program out of two vs two programs in one source vs two separate programs in two separate sources. The two-programs-in-one-source I'd see (in this case) as a another stepping-stone to the abandonment of the idea to be complicated.

I'd prefer it to be horribly simple. One program to do one thing. A second program to do the other thing.

PROGRAM-ID...
...
ENTRY

vs

PROGRAM-ID...
PROGRAM-ID...

vs

PROGRAM-ID...

PROGRAM-ID...

Other than the additional "boilerplate" the difference in having the two programs (however it is done) is just no ENTRY statement.

Frank Swarbrick

unread,
Aug 11, 2016, 11:09:44 AM8/11/16
to
Actually, unless you use PROCESS NAME on the second (and later) modules you will in the end have only a single executable (named after the member containing the source) that statically links the "secondary" programs.

________________________________
From: IBM Mainframe Discussion List <IBM-...@LISTSERV.UA.EDU> on behalf of John McKown <john.arch...@GMAIL.COM>
Sent: Thursday, August 11, 2016 6:07 AM
To: IBM-...@LISTSERV.UA.EDU
Subject: Re: How does COBOL detect a recursive call?

Farley, Peter x23353

unread,
Aug 11, 2016, 12:16:48 PM8/11/16
to
John,

Using the COBOL "nested programs" approach (as opposed to an ENTRY) does not result in more than one load module / program object, only one. Any competent source management system should handle that setup. We do that here with no issue (though we are not an Endeavor shop).

And the nested program does have access to the main program's WORKING-STORAGE items declared as GLOBAL, so they can share data too.

The question is whether or not the LE condition handler actually requires a directory entry in the PDS/E for the entry point of the condition handler code. If the "SET procedure-pointer" operation results in an address acceptable to the LE register-condition-handler operation, then there should be no issue at all.

Peter

-----Original Message-----
From: IBM Mainframe Discussion List [mailto:IBM-...@LISTSERV.UA.EDU] On Behalf Of John McKown
Sent: Thursday, August 11, 2016 8:07 AM
To: IBM-...@LISTSERV.UA.EDU
Subject: Re: How does COBOL detect a recursive call?

<Snipped>
> Excluding cursing, and including recursing.
>
> Any IT management who chooses that route over
> TwoSimpleProgramsWithNothingButOrdinaryCodeCompile/
> LinkProcessingAndOrdinaryRunTime. is... well, choose your own ending.
>
> Remember, there is Frank's suggestion to have the two programs in one
> source and compile them together, like they have some deep affinity
> just through proximity, that may serve the "do it the way I say" people.
>

​Hum, that wouldn't work here. ​I'm fairly sure the CA-Endevor will barf up its lungs if you try to put two source modules, which create two load modules / program objects, into a single source member. It wouldn't be able to 1:1 track an executable and associated source member.
--


This message and any attachments are intended only for the use of the addressee and may contain information that is privileged and confidential. If the reader of the message is not the intended recipient or an authorized representative of the intended recipient, you are hereby notified that any dissemination of this communication is strictly prohibited. If you have received this communication in error, please notify us immediately by e-mail and delete the message and any attachments from your system.

Frank Swarbrick

unread,
Aug 11, 2016, 2:59:04 PM8/11/16
to
Firstly, my recommendation was not COBOL nested programs, but rather was two individual COBOL programs stored in the same member and compiled in the same compile step.


Anyway, I've not tried recently, but I don't believe that you can point an ENTRY or procedure-pointer to a nested COBOL subprogram.

________________________________
From: IBM Mainframe Discussion List <IBM-...@LISTSERV.UA.EDU> on behalf of Farley, Peter x23353 <Peter....@BROADRIDGE.COM>
Sent: Thursday, August 11, 2016 10:16 AM

Bill Woodger

unread,
Aug 11, 2016, 3:19:06 PM8/11/16
to
Yes, it is documented that a contained/nested program cannot have an ENTRY, and, separately that a contained/nested program cannot be used for an LE Condition Handler.

Victor Gil

unread,
Aug 17, 2016, 11:04:37 AM8/17/16
to
Chuck,

Just another weird suggestion which may [or may not] work in your case - why can't the very SAME entry point also serve as the error handler?

I mean, it is being called with a parameter list, so by parsing the input parameters can't it determine the exact reason for call?

And if it's for the error handling - just take another path?

HTH,
-Victor-


======================================================
The wherefores of using a main program and an ENTRY versus 2 programs is a political battle I am not prepared or willing to fight.
When initially assigned this project I was hoping that my Systems status within the company would grant me some carte blanche in how I engineered the solution but, alas, I was mistaken.

Suffice it to say, until/unless I find a technical problem to warrant the multiple program construct, or even the multiple programs per member construct, I am stuck with using the COBOL language verbs as they have been engineered. If, and when, they fail to function, I will have the ammunition I need to push for one of the other programming constructs.

I do appreciate all of your narratives of what was occurring.

Chuck

Charles (Chuck) Hardee
Senior Systems Engineer/Database Administration
EAS Information Technology

Thermo Fisher Scientific
300 Industry Drive | Pittsburgh, PA 15275
Phone +1 (724) 517-2633 | Mobile +1 (412) 877-2809 | FAX: +1 (412) 490-9230
Chuck....@ThermoFisher.com | www.thermofisher.com

WORLDWIDE CONFIDENTIALITY NOTE: Dissemination, distribution or copying of this e-mail or the information herein by anyone other than the intended recipient, or an employee or agent of a system responsible for delivering the message to the intended recipient, is prohibited. If you are not the intended recipient, please inform the sender and delete all copies.



Bill Woodger

unread,
Aug 17, 2016, 12:42:13 PM8/17/16
to
That, Victor, could still require "IS RECURSIVE" on the PROGRAM-ID to avoid the abend with the IGZ0064S message (because the "handler" is invoked from the same program), depending the linkedit/binder RENT/REUS values. So it doesn't make it any simpler at the level of the mechanics.

Also, when entered as a "handler", you have no choice about what appears as "parameters", so arranging something distinguishable may be an issue.

Generally, a program which previously used ENTRY statements would be rewritten with "control data" in the USING if it shared WORKING-STORAGE, and as two programs if there was no sharing of WORKING-STORAGE (why did it use an ENTRY in the first place?).
0 new messages