I am wondering if there is a way that I can call from my Rexx code to a
COBOL (or BAL if necessary) program and be able to pass data back and forth?
This COBOL program would be used to execute some calls to our DBMS based on
data areas passed in from Rexx, and would then return other data areas back
to the Rexx.
If this can be done, can you point me to samples or to documentation on it?
Specifically, my questions are how to build dynamic data areas in Rexx and
get them into the program, and then what would the program need to do to
populate other data areas/variables when exiting the call so I can get them
in the Rexx program.
Also I would welcome other considerations for this process - the COBOL
program could be called many, many times, depending on the data needed and
returned for processing. The reason I am basing the root program in Rexx is
for the extensive string handling and datatype conversions that are not as
robust in other languages.
Thanks for your input and your direction!
*don*
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
I have a very basic example of how to call a COBOL program from REXX and pass it a couple of values. The COBOL program changes one of the values and passes it back to REXX. I'll send it to you offlist as an email attachment.
Dave Salt
SimpList(tm) - try it; you'll get it!
http://www.mackinney.com/products/program-development/simplist.html
> Date: Thu, 17 Mar 2011 13:17:41 -0400
> From: dej...@GMAIL.COM
> Subject: Rexx calling COBOL - how?
> To: TSO-...@VM.MARIST.EDU
What you want to do can be done in several ways.
* From a REXX exec running under TSO, you can issue the
TSO CALL command, but only pass a single halfword prefixed
string that can't be modified
* From a REXX exec, you can issue a REXX CALL command passing
up to 20 expressions; the called program receives a pointer
to an EFPL which contains pairs of a(string) / len(string);
called program can return a value of a fixed length
* From a REXX exec use one of the these approaches:
+ ADDRESS LINK or ADDRESS ATTACH pass zero or one string,
called program receives a pair of pointers to string
and the length; called program cannot update string
+ ADDRESS LINKMVS or ADDRESS ATTCHMVS passing list of
REXX variables, called program receives pointer to a
list of pointers to halfword prefixed strings; called
program can update any of the passed values (some restrictions)
+ ADDRESS LINKPGM or ADDRESS ATTCHPGM passing list of
REXX variables, called program receives pointer to
list of pointers to strings (no lengths); call program
can change value(s), but not length(s)
* A called compiled program can use the IKJCT441 service
to access and update the values of REXX variables
<ad>
Our two day course, "Introduction to TSO and REXX APIs"
includes these techniques, and many others, using
examples and labs in Assembler, COBOL, PL/I, and C (each
student chooses their own language to work with).
Details at:
http://www.trainersfriend.com/TSO_Clist_REXX_Dialog_Mgr/a780descrpt.htm
</ad>
--
Kind regards,
-Steve Comstock
The Trainer's Friend, Inc.
303-393-8716
http://www.trainersfriend.com
* To get a good Return on your Investment, first make an investment!
+ Training your people is an excellent investment
* Try our new tool for calculating your Return On Investment
for training dollars at
http://www.trainersfriend.com/ROI/roi.html
Don, I'll point out the perhaps not so obvious drawback of using Rexx to call something that is called "many, many times": Rexx has no concept of remembering a load module was called once already and using a "LOADed" copy for subsequent calls (assuming a reentrant or at least serially reusable module). Every Rexx call (or LINK or ATTACH) will fetch the called module again from STEPLIB or wherever, and this can be a substantial performance penalty.
Peter
--
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.
-- gil
Since the first cobol module has not yet terminated, the environment
stays intack when the called cobol module returns to the Rexx driver.
then use rex to call additional cobol programs.
I can't get you many details, as I have been retired for 9 years, but
this is the way I solved the overhead issue for my previous employeer.
I know this works when using the "Language Environment" languages - and
I beleive that all of the language processors are now of the "LE" varity.
When an LE environment is created, the"Call, Load, etc" mechanisms are
trapped by the Language environemnt and "LE" makes a determination of
"is it already loaded, and is it reusable/reentrant" and if not then
allows a normal LOAD or CAll to occur.
The trick is in using COBOL to CALL the initial rexx module... (The
first LE module loaded is considered the language environment controller)
As soon as that module terminates, it cleans up the environment. So the
trick is to not let a "master cobol" program terminate after each call
from rexx.
No simplier way than to have cobol call rexx, which then calls cobol.
Something to watch out for, is where the cobol load modules must reside
to be found....
LE is going to load modules from TASKLIB, then STEPLIB, and finally
from the System SYSLIB libraries.
If your environment is a TSO session, you aren't going to be able to
define STEPLIB (System Programmer types don't like it)
and so TASKLIB has to be utilized.
A TASKLIB can be created from an Assembly language program using the
ATTACH macro.
When I was supporting TSO, I provided both a callable module and a
command processor to create a tasklib with one or more libraries.
Lets say that the callable assembler program was "DOTLIB"... it would
allow a parm to be used to specify the list of libraries
to be searched for the main module and any support modules, and the
second parm would call a Dummy cobol program
that used a single parm to specify the rexx module to be initally invoked.
The rexx module is written normally, and calls cobol "subroutines" to do
whatever...
when the rexx modules does its final exit, it returns to the dummy cobol
program who exits (and cleans up after itself, releasing all previously
loaded cobol "subprograms") who returns to the assembler module that
quits normally. (A detach is automatic when the assemble module
terminates - but I actually coded an explicit detach to be on the "safe
side"...
hope this helps.
/s/ Bill Turner, wb4alm
On 03/17/2011 02:27 PM, Farley, Peter x23353 wrote:
>> -----Original Message-----
>> From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On Behalf
>> Of Donald Johnson
>> Sent: Thursday, March 17, 2011 1:18 PM
>> To: TSO-...@vm.marist.edu
>> Subject: Rexx calling COBOL - how?
> <Snipped>
>> Also I would welcome other considerations for this process - the COBOL
>> program could be called many, many times, depending on the data needed and
>> returned for processing.
> Don, I'll point out the perhaps not so obvious drawback of using Rexx to call something that is called "many, many times": Rexx has no concept of remembering a load module was called once already and using a "LOADed" copy for subsequent calls (assuming a reentrant or at least serially reusable module). Every Rexx call (or LINK or ATTACH) will fetch the called module again from STEPLIB or wherever, and this can be a substantial performance penalty.
>
> Peter
> --
>
----------------------------------------------------------------------
/s/ Bill Turner, wb4alm
Did you search Google for this? I too wanted to do this a short while
ago and I put
rexx cobol data
into Google and found http://ibmmainframes.com/about46420-0.html which
worked perfectly. It also contains suggestions of another useful
Google search to get more information.
I can totally recommend doing a quick search on Google using the "key"
words of your query before bothering to type a long post here and
waiting for replies.
Peter
--
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.
> Don, I'll point out the perhaps not so obvious drawback of using Rexx to
> call something that is called "many, many times": Rexx has no concept of
> remembering a load module was called once already and using a "LOADed"
> copy for subsequent calls (assuming a reentrant or at least serially
> reusable module). Every Rexx call (or LINK or ATTACH) will fetch the
> called module again from STEPLIB or wherever, and this can be a
> substantial performance penalty.
If so, one might get around that with REXX invoking a small (assembler,
preferably) routine which resides in LPA (so presumably would bever get
reloaded), and have that in turn LOAD once and subsequently LINK/ATTACH the
COBOL program.
--
Jeremy C B Nicoll - my opinions are my own.
- - -
Remember that the first "LE" language program will "create" an LE
environment... There is no requirement that all "lower level" programs
must also be "LE" language programs, because if there were, COBOL would
never be able to call an assembler language program who might then call
a FORTRAN program or a PLI program or another COBOL program based upon a
logic decision...
One of the reasons for "LE" in the first place was to keep the
subroutine support libraries returning the same answers, regardless of
the language that a calling program was written in. (A classic error of
concern was in calculating date differences, and in Trig math support -
every language used their own techniques, and as a result often returned
different results.)
(From an IBM support point of view, LE also meant that they also did not
have to have support programmers who know how to create "cosine" values
for every variation of COBOL (of which there were 3 versions each, of 6
varieties, at that time), and also every variation of PL/I and every
variation of FORTRAN, etc. - (Sure sounds like a massive way to save
money, doesn't it?)
- - -
When an upper level program is COBOL (or any other LE language) than the
created LE environment is available to any "lower level" program if they
need a valid "LE" environment, and if it is not needed, no harm is done
- it just exists.
The "2nd level" Rexx program at that point is just like any other
assembler language program, and since it does not REQUIRE LE it does not
even recognize that one exists. Since -ALL- Cobol programs REQUIRE the
LE environment, they must check to see if one exists, and if it doesn't,
they MUST create one and then delete it upon termination.
- - -
The technique I have outlined was used for many years by some major
corporate critical projects --- and to my knowledge, the technique is
still in use.
I don't have my notes any more, but I know that program performance
testing showed this to be a very effective way of minimizing the
overhead of calling a cobol module multiple times from either assembler
or Rexx or ....
If you were to do it the "normal way" by just having REXX call the cobol
module(s), as soon as COBOL got control, it would look around for an LE
environment, and not finding any, would create one. The cobol program
would then run, and upon termination would look to see if it was
the highest "LE" program in the calling chain. Since it would determine
that it was, it would then knockdown the "LE" environment.
Upon the next invocation of a cobol program, the process would be
started all over.
In a COBOL calling REXX, who then calls the additional cobol modules
environment. The upperlevel COBOL creates the LE environment,
calls rexx, who then calls the COBOL subprogram. The subprogram look
around for an LE environment, and FINDs one (albet a couple
of calling levels above itself. Since the environment DOES exist, it
doesn't have to create one, and can then make use of internal LE
functionality.
As I understand it, one of those functionalities is a fastpath calling
mechanism that keeps track of programs already called or loaded at least
once....
/s/ Bill Turner, wb4alm
/s/ Bill Turner, wb4alm
-- gil
Even easier. The CAA is anchored off the TCB.
> -- gil
--
Don Poitras - SAS Development - SAS Institute Inc. - SAS Campus Drive
sas...@sas.com (919) 531-5637 Cary, NC 27513
But my original point is, I think, still somewhat valid. Because Rexx is *NOT* LE, then each CALL/LINK from Rexx will issue a z/OS LINK to call the program and then z/OS will reduce the use count to zero on return from the LINKed to routine. Unless you are very lucky, that program storage is now gone, and the program called by Rexx will be loaded into storage again on the next CALL/LINK from Rexx.
I realize that the additional overhead of enclave initialization is large, but program fetch from STEPLIB/JOBLIB is not very fast either, so for a COBOL routine called from Rexx "many, many times" as proposed by the OP, there will still be a large overhead for every CALL/LINK from Rexx, though not as large as if enclave initialization was needed.
I am sure that your method reduces the Rexx CALL/LINK overhead by a lot, but the "load and call" subroutine suggested by Paul may also be needed together with your technique to truly reduce the Rexx CALL/LINK overhead to a negligible level. Paul's technique could presumably also be set up as a Rexx function package rather than an LPA module, allowing ordinary (non-systems) programmers to use it.
Actually, a generic setup like the one you suggested (COBOL program to call any Rexx with arbitrary input argument string) combined with Paul's idea implemented as a Rexx function package would make a lovely CBT contribution.
Peter
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On Behalf
> Of Bill Turner, WB4ALM
> Sent: Saturday, March 19, 2011 8:53 PM
> To: TSO-...@vm.marist.edu
> Subject: Re: Rexx calling COBOL - how?
>
More precisely, I suggested separating the "load" from the "call".
The sequence I envision is:
LOAD
LINK
LINK
...
DELETE
> together with your technique to truly reduce the Rexx CALL/LINK overhead to a negligible level. Paul's technique could presumably also be set up as a Rexx function package rather than an LPA module, allowing ordinary (non-systems) programmers to use it.
>
Non-systems programmers can use LPA modules. And I believe that
Rexx function packages can reside in LPA (they're load modules,
aren't they?)
> Actually, a generic setup like the one you suggested (COBOL program to call any Rexx with arbitrary input argument string) combined with Paul's idea implemented as a Rexx function package would make a lovely CBT contribution.
>
I believe the COBOL program (could be LE-enabled assembler?)
is necessary only to anchor the LE environment. Outside COBOL,
what restrictions exist on input argument strings?
-- gil
I do agree with your suggested call sequence, that makes sense.
As for argument strings, I suppose it depends on the calling environment. 100 char PARM limit from JCL, I think 32K for TSO (totally unsure about that limit), unknown limit from the shell?
The program could always be written to take in a file with the Rexx name and parameters, that wouldn't be too bad. I could live with it, anyway.
I suppose it could also be an LE-enabled assembler main program. No reason not to except for shops that can't/don't want to support any new assembler code any more because there are so few of us left who know it.
Peter
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On Behalf
> Of Paul Gilmartin
> Sent: Monday, March 21, 2011 5:15 PM
> To: TSO-...@vm.marist.edu
> Subject: Re: Rexx calling COBOL - how?
>
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.
:>On Mar 21, 2011, at 16:26, Farley, Peter x23353 wrote:
:>> Sorry, in the shops where I have worked non-systems-programmers do not generally have any authority to put modules into the LPA. That's what I meant by that. An application programmer needs to be able to test things without any authorized assistance. An application programmer can surely use LPA modules, but can NOT cause them to be loaded into LPA.
:>Ah, the conventional sequence:
:>o Programmer tests with STEPLIB.
:>o After successful test, programmer submits request to install
:> in LPA.
Why would application code be placed in LPA?
:>o Request is denied.
As it should be.
--
Binyamin Dissen <bdi...@dissensoftware.com>
http://www.dissensoftware.com
Should you use the mailblocks package and expect a response from me,
you should preauthorize the dissensoftware.com domain.
I very rarely bother responding to challenge/response systems,
especially those from irresponsible companies.