Discussion:
[H390-MVS] Calling assembler module from C (JCC)
mike.grossmann@ymail.com [H390-MVS]
2018-10-18 17:34:44 UTC
Permalink
Hello,

I need some help with the following.

A module in the LPA (IKJCT441) I want to call in C. My rough approach would be loading the address via CVT->TSVT.

Then I think I need somehow a function pointer. I've never done anything like this under MVS and C before. Under z/OS there are pragma instructions for linkage.

Can someone give me a hint or two?

Thank u
/mig
Mike Rayborn mikerayborn@gmail.com [H390-MVS]
2018-10-18 22:35:08 UTC
Permalink
I tried replying via the Yahoo web site but that doesn't seem to be
working.  In any case, I think the following sample may work for you.  I
don't use the JCC compiler, so I can't say for sure it will work,
although I can't think of any reason it wouldn't.


typedef struct ikjct441_plist IKJCT441;

struct ikjct441_plist {
    int         *ecode;
    const char  **name;
    int         *namelen;
    char        **value;
    int         *vallen;
    void        *token;
    void        *ect;
    int         *retcode;
    IKJCT441    *next;
};

/* ECODE values */
#define ECODE_TSVERETR    1
#define ECODE_TSVEUPDT    2
#define ECODE_TSVELOC     3
#define ECODE_TSVERSVD    4
#define ECODE_TSVNOIMP    18

int ikjct441(int ecode, const char *name, char *value, int value_size)
{
    int         rc       = 0;
    int         namelen  = name ? strlen(name) : 0;
    void        *token   = (void*)0;
    void        *ectnull = (void*)0xFFFFFFFF;
    unsigned    *psa     = (unsigned *)0;
    unsigned    *cvt     = (unsigned *)psa[16/4];
    unsigned    *tvt     = (unsigned *)cvt[156/4];
    int         (*ep)(int *, const char**, int *, char **, int *, void
*, void *, int *, IKJCT441 *)
                         = (void*)tvt[40/4];
    IKJCT441    plist;

    /* construct the parameter list */
    plist.ecode     = &ecode;
    plist.retcode   = &rc;
    plist.name      = &name;
    plist.namelen   = &namelen;
    plist.value     = &value;
    plist.vallen    = &value_size;
    plist.token     = &token;
    plist.ect       = &ectnull;
    plist.retcode   = &rc;
    plist.next      = (IKJCT441*)0;

    /* call IKJCT441 via function pointer 'ep' */
    ep(plist.ecode, plist.name, plist.namelen, plist.value,
plist.vallen, plist.token, plist.ect, plist.retcode, plist.next);

    /* return IKJCT441 retcode value (rc) */
    return rc;
}
Post by ***@ymail.com [H390-MVS]
Hello,
I need some help with the following.
A module in the LPA (IKJCT441) I want to call in C. My rough approach
would be loading the address via CVT->TSVT.
Then I think I need somehow a function pointer. I've never done
anything like this under MVS and C before. Under z/OS there are pragma
instructions for linkage.
Can someone give me a hint or two?
Thank u
/mig
mikerayborn@gmail.com [H390-MVS]
2018-10-18 21:36:34 UTC
Permalink
I don't use JCC so this may not work (although I don't see why it wouldn't). Try something like this:

typedef struct ikjct441_plist IKJCT441;


struct ikjct441_plist {
int *ecode;
const char **name;
int *namelen;
char **value;
int *vallen;
void *ect;
int *retcode;
IKJCT441 *next;
};


int ikjct441(int ecode, const char *name, char *value, int value_size)
{
int rc = 0;
int namelen = name ? strlen(name) : 0;
void *ectnull = (void*)0xFFFFFFFF;
unsigned *psa = (unsigned *)0;
unsigned *cvt = (unsigned *)psa[16/4];
unsigned *tvt = (unsigned *)cvt[156/4];
int (*ep)(int *, const char**, int *, char **, int *, void *, int *, IKJCT441 *)
= (void*)tvt[40/4];
IKJCT441 plist;


/* construct the parameter list */
plist.ecode = &ecode;
plist.retcode = &rc;
plist.name = &name;
plist.namelen = &namelen;
plist.value = &value;
plist.vallen = &value_size;
plist.ect = ectnull;
plist.retcode = &rc;
plist.next = (IKJCT441*)0;


ep(plist.ecode, plist.name, plist.namelen, plist.value, plist.vallen, plist.ect, plist.retcode, plist.next);


return rc;
}
Mike Großmann mike.grossmann@ymail.com [H390-MVS]
2018-10-19 13:38:05 UTC
Permalink
Thanks for pointing me in the right direction. Unfortunately, I noticed that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector table) in the CVT.. Is there another control block where I can find the address of a LPA module?
best regardsMike
Am Freitag, 19. Oktober 2018, 00:44:01 MESZ hat ***@gmail.com [H390-MVS] <H390-***@yahoogroups.com> Folgendes geschrieben:

 
I don't use JCC so this may not work (although I don't see why it wouldn't)..  Try something like this:

typedef struct ikjct441_plist IKJCT441;
struct ikjct441_plist {    int         *ecode;    const char  **name;    int         *namelen;    char        **value;    int         *vallen;    void        *ect;    int         *retcode;    IKJCT441    *next;};
int ikjct441(int ecode, const char *name, char *value, int value_size){    int         rc       = 0;    int         namelen  = name ? strlen(name) : 0;    void        *ectnull = (void*)0xFFFFFFFF;    unsigned    *psa     = (unsigned *)0;    unsigned    *cvt     = (unsigned *)psa[16/4];    unsigned    *tvt     = (unsigned *)cvt[156/4];    int         (*ep)(int *, const char**, int *, char **, int *, void *, int *, IKJCT441 *)                         = (void*)tvt[40/4];    IKJCT441    plist;
    /* construct the parameter list */    plist.ecode     = &ecode;    plist.retcode   = &rc;    plist.name      = &name;    plist.namelen   = &namelen;    plist.value     = &value;    plist.vallen    = &value_size;    plist.ect       = ectnull;    plist.retcode   = &rc;    plist.next      = (IKJCT441*)0;
    ep(plist.ecode, plist.name, plist.namelen, plist.value, plist..vallen, plist.ect, plist.retcode, plist.next);
    return rc;}

#yiv1120483746 #yiv1120483746 -- #yiv1120483746ygrp-mkp {border:1px solid #d8d8d8;font-family:Arial;margin:10px 0;padding:0 10px;}#yiv1120483746 #yiv1120483746ygrp-mkp hr {border:1px solid #d8d8d8;}#yiv1120483746 #yiv1120483746ygrp-mkp #yiv1120483746hd {color:#628c2a;font-size:85%;font-weight:700;line-height:122%;margin:10px 0;}#yiv1120483746 #yiv1120483746ygrp-mkp #yiv1120483746ads {margin-bottom:10px;}#yiv1120483746 #yiv1120483746ygrp-mkp .yiv1120483746ad {padding:0 0;}#yiv1120483746 #yiv1120483746ygrp-mkp .yiv1120483746ad p {margin:0;}#yiv1120483746 #yiv1120483746ygrp-mkp .yiv1120483746ad a {color:#0000ff;text-decoration:none;}#yiv1120483746 #yiv1120483746ygrp-sponsor #yiv1120483746ygrp-lc {font-family:Arial;}#yiv1120483746 #yiv1120483746ygrp-sponsor #yiv1120483746ygrp-lc #yiv1120483746hd {margin:10px 0px;font-weight:700;font-size:78%;line-height:122%;}#yiv1120483746 #yiv1120483746ygrp-sponsor #yiv1120483746ygrp-lc .yiv1120483746ad {margin-bottom:10px;padding:0 0;}#yiv1120483746 #yiv1120483746actions {font-family:Verdana;font-size:11px;padding:10px 0;}#yiv1120483746 #yiv1120483746activity {background-color:#e0ecee;float:left;font-family:Verdana;font-size:10px;padding:10px;}#yiv1120483746 #yiv1120483746activity span {font-weight:700;}#yiv1120483746 #yiv1120483746activity span:first-child {text-transform:uppercase;}#yiv1120483746 #yiv1120483746activity span a {color:#5085b6;text-decoration:none;}#yiv1120483746 #yiv1120483746activity span span {color:#ff7900;}#yiv1120483746 #yiv1120483746activity span .yiv1120483746underline {text-decoration:underline;}#yiv1120483746 .yiv1120483746attach {clear:both;display:table;font-family:Arial;font-size:12px;padding:10px 0;width:400px;}#yiv1120483746 .yiv1120483746attach div a {text-decoration:none;}#yiv1120483746 .yiv1120483746attach img {border:none;padding-right:5px;}#yiv1120483746 .yiv1120483746attach label {display:block;margin-bottom:5px;}#yiv1120483746 .yiv1120483746attach label a {text-decoration:none;}#yiv1120483746 blockquote {margin:0 0 0 4px;}#yiv1120483746 .yiv1120483746bold {font-family:Arial;font-size:13px;font-weight:700;}#yiv1120483746 .yiv1120483746bold a {text-decoration:none;}#yiv1120483746 dd.yiv1120483746last p a {font-family:Verdana;font-weight:700;}#yiv1120483746 dd.yiv1120483746last p span {margin-right:10px;font-family:Verdana;font-weight:700;}#yiv1120483746 dd.yiv1120483746last p span.yiv1120483746yshortcuts {margin-right:0;}#yiv1120483746 div.yiv1120483746attach-table div div a {text-decoration:none;}#yiv1120483746 div.yiv1120483746attach-table {width:400px;}#yiv1120483746 div.yiv1120483746file-title a, #yiv1120483746 div.yiv1120483746file-title a:active, #yiv1120483746 div.yiv1120483746file-title a:hover, #yiv1120483746 div.yiv1120483746file-title a:visited {text-decoration:none;}#yiv1120483746 div.yiv1120483746photo-title a, #yiv1120483746 div.yiv1120483746photo-title a:active, #yiv1120483746 div.yiv1120483746photo-title a:hover, #yiv1120483746 div.yiv1120483746photo-title a:visited {text-decoration:none;}#yiv1120483746 div#yiv1120483746ygrp-mlmsg #yiv1120483746ygrp-msg p a span.yiv1120483746yshortcuts {font-family:Verdana;font-size:10px;font-weight:normal;}#yiv1120483746 .yiv1120483746green {color:#628c2a;}#yiv1120483746 .yiv1120483746MsoNormal {margin:0 0 0 0;}#yiv1120483746 o {font-size:0;}#yiv1120483746 #yiv1120483746photos div {float:left;width:72px;}#yiv1120483746 #yiv1120483746photos div div {border:1px solid #666666;min-height:62px;overflow:hidden;width:62px;}#yiv1120483746 #yiv1120483746photos div label {color:#666666;font-size:10px;overflow:hidden;text-align:center;white-space:nowrap;width:64px;}#yiv1120483746 #yiv1120483746reco-category {font-size:77%;}#yiv1120483746 #yiv1120483746reco-desc {font-size:77%;}#yiv1120483746 .yiv1120483746replbq {margin:4px;}#yiv1120483746 #yiv1120483746ygrp-actbar div a:first-child {margin-right:2px;padding-right:5px;}#yiv1120483746 #yiv1120483746ygrp-mlmsg {font-size:13px;font-family:Arial, helvetica, clean, sans-serif;}#yiv1120483746 #yiv1120483746ygrp-mlmsg table {font-size:inherit;font:100%;}#yiv1120483746 #yiv1120483746ygrp-mlmsg select, #yiv1120483746 input, #yiv1120483746 textarea {font:99% Arial, Helvetica, clean, sans-serif;}#yiv1120483746 #yiv1120483746ygrp-mlmsg pre, #yiv1120483746 code {font:115% monospace;}#yiv1120483746 #yiv1120483746ygrp-mlmsg * {line-height:1.22em;}#yiv1120483746 #yiv1120483746ygrp-mlmsg #yiv1120483746logo {padding-bottom:10px;}#yiv1120483746 #yiv1120483746ygrp-msg p a {font-family:Verdana;}#yiv1120483746 #yiv1120483746ygrp-msg p#yiv1120483746attach-count span {color:#1E66AE;font-weight:700;}#yiv1120483746 #yiv1120483746ygrp-reco #yiv1120483746reco-head {color:#ff7900;font-weight:700;}#yiv1120483746 #yiv1120483746ygrp-reco {margin-bottom:20px;padding:0px;}#yiv1120483746 #yiv1120483746ygrp-sponsor #yiv1120483746ov li a {font-size:130%;text-decoration:none;}#yiv1120483746 #yiv1120483746ygrp-sponsor #yiv1120483746ov li {font-size:77%;list-style-type:square;padding:6px 0;}#yiv1120483746 #yiv1120483746ygrp-sponsor #yiv1120483746ov ul {margin:0;padding:0 0 0 8px;}#yiv1120483746 #yiv1120483746ygrp-text {font-family:Georgia;}#yiv1120483746 #yiv1120483746ygrp-text p {margin:0 0 1em 0;}#yiv1120483746 #yiv1120483746ygrp-text tt {font-size:120%;}#yiv1120483746 #yiv1120483746ygrp-vital ul li:last-child {border-right:none !important;}#yiv1120483746
Gerhard Postpischil gerhardp@charter.net [H390-MVS]
2018-10-19 16:11:05 UTC
Permalink
Post by Mike Großmann ***@ymail.com [H390-MVS]
Thanks for pointing me in the right direction. Unfortunately, I noticed
that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector table) in
the CVT.
Is there another control block where I can find the address of a LPA module?
I'm attaching my subroutine to locate modules. It's in assembler with
local macros (in cbttape file 861), but you should be able to find and
chase the two chains you need. It was downloaded (FB, 80, 23440) with
IND$FILE in text mode. Let me know if you'd like a listing instead.

If you only need to invoke a single module, you could use the LINK macro
and service instead:

LA R1,parameterlist
LINK EP=IKJCT441

If you call this service many times, you could use a LOAD macro once,
use the returned address for the calls, and then a DELETE when you are
finished with it.

Gerhard Postpischil
Bradford, VT


---
This email has been checked for viruses by AVG.
https://www.avg.com
Rob Osattin rosattin@earthlink.net [H390-MVS]
2018-10-19 15:45:42 UTC
Permalink
Can you issue a LOAD to find its entry point?

Rob Osattin
Post by Mike Großmann ***@ymail.com [H390-MVS]
Thanks for pointing me in the right direction. Unfortunately, I noticed that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector table) in the CVT.
Is there another control block where I can find the address of a LPA module?
best regards
Mike
typedef struct ikjct441_plist IKJCT441;
struct ikjct441_plist {
int *ecode;
const char **name;
int *namelen;
char **value;
int *vallen;
void *ect;
int *retcode;
IKJCT441 *next;
};
int ikjct441(int ecode, const char *name, char *value, int value_size)
{
int rc = 0;
int namelen = name ? strlen(name) : 0;
void *ectnull = (void*)0xFFFFFFFF;
unsigned *psa = (unsigned *)0;
unsigned *cvt = (unsigned *)psa[16/4];
unsigned *tvt = (unsigned *)cvt[156/4];
int (*ep)(int *, const char**, int *, char **, int *, void *, int *, IKJCT441 *)
= (void*)tvt[40/4];
IKJCT441 plist;
/* construct the parameter list */
plist.ecode = &ecode;
plist.retcode = &rc;
plist.name = &name;
plist.namelen = &namelen;
plist.value = &value;
plist.vallen = &value_size;
plist.ect = ectnull;
plist.retcode = &rc;
plist.next = (IKJCT441*)0;
ep(plist.ecode, plist.name, plist.namelen, plist.value, plist.vallen, plist.ect, plist.retcode, plist.next);
return rc;
}
Gerhard Postpischil gerhardp@charter.net [H390-MVS]
2018-10-19 16:43:57 UTC
Permalink
On 10/19/2018 9:38 AM, Mike Großmann ***@ymail.com [H390-MVS]
wrote:> Thanks for pointing me in the right direction. Unfortunately, I
noticed > that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector
table) in > the CVT.

I should have checked first - on MVS 3.8 there is no version of IKJCT441.

Gerhard Postpischil
Bradford, VT

---
This email has been checked for viruses by AVG.
https://www.avg.com
Mike Großmann mike.grossmann@ymail.com [H390-MVS]
2018-10-19 17:01:56 UTC
Permalink
Hi Gerhard,

thank u for helping me out. For MVS3.8 there is a user mod for IKJCT441.
I’m trying to implement the module search by my self in C.
So what possible could help was the source of the CSVQUERY macro.
But unfortunately it is not present in MVS 3.8.

What i have done so far. I got the address of the LPDIR from the CVT.
There is a list of LPDE’s with all the informations i need. Hopefully. :)

Thanks and best regards
Mike
Post by Gerhard Postpischil ***@charter.net [H390-MVS]
wrote:> Thanks for pointing me in the right direction. Unfortunately, I
noticed > that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector
table) in > the CVT.
I should have checked first - on MVS 3.8 there is no version of IKJCT441.
Gerhard Postpischil
Bradford, VT
---
This email has been checked for viruses by AVG.
https://www.avg.com <https://www.avg.com/>
jimruddy1953@yahoo.com [H390-MVS]
2018-10-19 19:32:33 UTC
Permalink
Hi Mike,


Gerhard's routine should work once you have Greg Price's usermod installed (and you have IPLed with CLPA specified in parmlib).


Jim
winkelmann@id.ethz.ch [H390-MVS]
2018-10-19 20:22:46 UTC
Permalink
Hi Mike


coming a bit late to that discussion, so, sorry if I'm missing something. But why don't you simply use LOAD or LINK, as Gerhard suggested? A very small assembler routine will do this for you, just similar to the examples I mentioned off list yesterday.



Cheers
JÃŒrgen

---In H390-***@yahoogroups.com, <***@...> wrote :


Hi Gerhard,

thank u for helping me out. For MVS3.8 there is a user mod for IKJCT441.
I’m trying to implement the module search by my self in C.
So what possible could help was the source of the CSVQUERY macro.
But unfortunately it is not present in MVS 3.8.


What i have done so far. I got the address of the LPDIR from the CVT.
There is a list of LPDE’s with all the informations i need. Hopefully. :)


Thanks and best regards
Mike




Am 19.10.2018 um 18:43 schrieb Gerhard Postpischil ***@... mailto:***@... [H390-MVS] <H390-***@yahoogroups.com mailto:H390-***@yahoogroups.com>:

On 10/19/2018 9:38 AM, Mike Großmann ***@... mailto:***@... [H390-MVS]
wrote:> Thanks for pointing me in the right direction. Unfortunately, I
noticed > that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector
table) in > the CVT.

I should have checked first - on MVS 3.8 there is no version of IKJCT441.

Gerhard Postpischil
Bradford, VT

---
This email has been checked for viruses by AVG.
https://www.avg.com https://www.avg.com/
Mike Großmann mike.grossmann@ymail.com [H390-MVS]
2018-10-19 20:41:30 UTC
Permalink
Hi JÃŒrgen,

I thought to myself that the variant proposed by IBM is more performant. IBM writes in their examples that you should get the entry point of the module loaded into the LPA from a control block. I would have thought, LOAD and LINK leads to bottlenecks, if it is called very frequently. Maybe this is my mistake?

I could determine the address of the module in the meantime.


regards
mike
Post by ***@yahoo.com [H390-MVS]
Hi Mike
coming a bit late to that discussion, so, sorry if I'm missing something. But why don't you simply use LOAD or LINK, as Gerhard suggested? A very small assembler routine will do this for you, just similar to the examples I mentioned off list yesterday.
Cheers
JÃŒrgen
Hi Gerhard,
thank u for helping me out. For MVS3.8 there is a user mod for IKJCT441.
I’m trying to implement the module search by my self in C.
So what possible could help was the source of the CSVQUERY macro.
But unfortunately it is not present in MVS 3.8.
What i have done so far. I got the address of the LPDIR from the CVT.
There is a list of LPDE’s with all the informations i need. Hopefully. :)
Thanks and best regards
Mike
Post by Gerhard Postpischil ***@charter.net [H390-MVS]
wrote:> Thanks for pointing me in the right direction. Unfortunately, I
noticed > that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector
table) in > the CVT.
I should have checked first - on MVS 3.8 there is no version of IKJCT441..
Gerhard Postpischil
Bradford, VT
---
This email has been checked for viruses by AVG.
https://www.avg.com <https://www.avg.com/>
jimruddy1953@yahoo.com [H390-MVS]
2018-10-20 00:00:43 UTC
Permalink
Hi Mike,


IIRC, if a module is in LPA, it is already in memory and LOAD will find it quickly - much different cost than reading into memory from dasd.


Btw, what is the big picture of what you are working on - it has me intrigued.


Jim
pricgren pricgren@yahoo.com [H390-MVS]
2018-10-20 03:18:36 UTC
Permalink
I imagine it was an early release of OS/VS2 where they put pointers in
the CVT to often used TSO routines like IKJGETL, IKJPUTL, IKJPARS, etc. 
And then when TSO/E came along they had lots more callable service
routines for folks to use so they gave TSO its own vector table (the
TSVT) and added just a single field to the CVT (CVTTVT) to point to it,
thereby minimising further CVT clutter from TSO.  All good stuff.

So many/most/all of these routines are resident in LPA.  Most of the
time they are in PLPA but there is nothing wrong with having a modified
version to try out in MLPA.  But that's okay because the address placed
in the CVT and/or TSVT (when it exists) is the active copy that the
system would get for you if you were doing a normal module invocation
via a normal program management macro such as LINK or LOAD, so the
control block pointer will be "correct" for this IPL.

https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.ikjb700/ikjb700_When_to_use_the_CALLTSSR_.htm
lists some of the TSO service routines that you can call these days in
z/OS, in this case with the CALLTSSR macro.  The macro checks the
control block pointer and uses it as a branch target if non-zero, or if
zero issues a LINK to invoke the routine.  After all, local site admin
may have decided that they do not want to waste common storage on TSO
service routines, and therefore moved them to somewhere in the linklist.

Authors of programs that invoke system-supplied routines may like to
have their programs find the routine to invoke with minimum overhead and
so will search the active LPA CDE chain, the PLPA directory, perhaps
even the JPA, and then do a BLDL to see if it is around anywhere before
attempting to invoke it.  (Note that current systems do not create a CDE
for the LPAQ for "active" PLPA modules, but use the chain only for MLPA,
FLPA and what could be called the DLPA "pre-Q" Q (my term).)

So, for example, when you issue a TSO command under REVIEW/RFE, rather
than create an S806 abend if the command does not exist, the module is
first searched for to see if it exists. If it does not exist then the
command is assumed to be for a CLIST.

I guess it is one thing to say whether a program of a given name is
anywhere to be found - but it is another thing to say which copy the
system would use when a program of that name is found in multiple
places.  The order of precedence is published, but rather than try to
mimic it, the advice for z/OS is to just issue the LOAD request with an
ERRET to handle errors such as "program not found".  These days, the OS
assumes that if you have an ERRET then you do not need an abend WTO
message.  For MVS 3.8, you will get the abend WTO message but the ERRET
can still be used to prevent abnormal task termination.

In my view a "decent" 3GL for the MVS environment needs a way to be able
to make a general call to a program specified by its name. PL/I has
FETCH (these days, anyway), and COBOL has its "dynamic links" (I've
heard) and C?  Well, don't ask me, I can barely spell C.

So, usermod ZP60038 supplies a version of IKJCT441 for MVS 3.8 which
ends up being link edited into the whole TSO I/O routine morass. (Check
out that JCLIN!  And then there's the SYSGEN support to be updated...) 
I envisaged callers simply issuing a LINK macro to invoke it, with a
LOAD-BALR-DELETE combo being equally valid, of course.  But if you want
to check the whole, JPA, MLPA, PLPA, linklist thing, I'm not going to
stop you.

In REVIEW I just search the LPAQ "manually" because I expect that's what
the system would have to do (I should check that one day).  To search
the PLPA directory the system has a hashing routine which should make it
much more efficient than the full sequential search - as if that matters
on you own herc box.

The code in REVIEW is very much like:
*               REGS 0 AND 1 - CONTAIN NAME
*               REG 3        - CVT
*               REGS 7 8 9   - WORK REGS
*               REG 14       - RETURN - BAD RETURN 4(14)
*               REG 15       - ENTRY POINT
*               REG 0        - POINTS TO LPDE AFTER GOOD RETURN
         SPACE
TSOPLPA  LM    R0,R1,BLDLNAME
         STM   R14,R12,12(R13)
         L     R3,CVTPTR(,0)               POINT TO THE CVT
         L     R15,CVTLPDSR-CVT(,R3)       GET ROUTINE ENTRY POINT
         BASR  R14,R15                     CALL IEAVVMSR
         B     TSOPLPAX                    FOUND IN PLPA
         LM    R14,R12,12(R13)             NOT IN PLPA, DO BLDL
         ...
TSOPLPAX LM    R14,R12,12(R13)

Last time I pasted code it was a scrambled mess, so apologies if the
result is the same this time.

Code like that works from MVS 3.8 (actually, I bet it works on 3.7 and
maybe even earlier) to at least z/OS 2.3 where support for RMODE=64 was
added and LPDE control blocks grew by 8 bytes.  In z/OS 2.2 LPDEs were
the same size as they are in MVS 3.8.  Naturally, you need to know the
LPDE size if you are stepping through the PLPA directory sequentially.


Cheers,
Greg
Mike Großmann mike.grossmann@ymail.com [H390-MVS]
2018-10-20 06:31:22 UTC
Permalink
In about 1986 IBM introduced the TSVT. In all IBM examples of how to address IKJCT441, the entry point is fetched via the TSVT.
But all my colleagues and friend telling me to use LOAD. I am confused. :)

What does the big picture look like? We're trying to extend BREXX to support TSO variables.

In the meantime I've figured out the entry point iteration via LPDE. Now I only have a few hurdles to overcome in C. :)

Many thanks and many greetings
by a junior mainframer

Translated with www.DeepL.com/Translator
Post by pricgren ***@yahoo.com [H390-MVS]
I imagine it was an early release of OS/VS2 where they put pointers in
the CVT to often used TSO routines like IKJGETL, IKJPUTL, IKJPARS, etc.
And then when TSO/E came along they had lots more callable service
routines for folks to use so they gave TSO its own vector table (the
TSVT) and added just a single field to the CVT (CVTTVT) to point to it,
thereby minimising further CVT clutter from TSO. All good stuff.
So many/most/all of these routines are resident in LPA. Most of the
time they are in PLPA but there is nothing wrong with having a modified
version to try out in MLPA. But that's okay because the address placed
in the CVT and/or TSVT (when it exists) is the active copy that the
system would get for you if you were doing a normal module invocation
via a normal program management macro such as LINK or LOAD, so the
control block pointer will be "correct" for this IPL.
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.ikjb700/ikjb700_When_to_use_the_CALLTSSR_.htm <https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.ikjb700/ikjb700_When_to_use_the_CALLTSSR_.htm>
lists some of the TSO service routines that you can call these days in
z/OS, in this case with the CALLTSSR macro. The macro checks the
control block pointer and uses it as a branch target if non-zero, or if
zero issues a LINK to invoke the routine. After all, local site admin
may have decided that they do not want to waste common storage on TSO
service routines, and therefore moved them to somewhere in the linklist.
Authors of programs that invoke system-supplied routines may like to
have their programs find the routine to invoke with minimum overhead and
so will search the active LPA CDE chain, the PLPA directory, perhaps
even the JPA, and then do a BLDL to see if it is around anywhere before
attempting to invoke it. (Note that current systems do not create a CDE
for the LPAQ for "active" PLPA modules, but use the chain only for MLPA,
FLPA and what could be called the DLPA "pre-Q" Q (my term).)
So, for example, when you issue a TSO command under REVIEW/RFE, rather
than create an S806 abend if the command does not exist, the module is
first searched for to see if it exists. If it does not exist then the
command is assumed to be for a CLIST.
I guess it is one thing to say whether a program of a given name is
anywhere to be found - but it is another thing to say which copy the
system would use when a program of that name is found in multiple
places. The order of precedence is published, but rather than try to
mimic it, the advice for z/OS is to just issue the LOAD request with an
ERRET to handle errors such as "program not found". These days, the OS
assumes that if you have an ERRET then you do not need an abend WTO
message. For MVS 3.8, you will get the abend WTO message but the ERRET
can still be used to prevent abnormal task termination.
In my view a "decent" 3GL for the MVS environment needs a way to be able
to make a general call to a program specified by its name. PL/I has
FETCH (these days, anyway), and COBOL has its "dynamic links" (I've
heard) and C? Well, don't ask me, I can barely spell C.
So, usermod ZP60038 supplies a version of IKJCT441 for MVS 3.8 which
ends up being link edited into the whole TSO I/O routine morass. (Check
out that JCLIN! And then there's the SYSGEN support to be updated....)
I envisaged callers simply issuing a LINK macro to invoke it, with a
LOAD-BALR-DELETE combo being equally valid, of course. But if you want
to check the whole, JPA, MLPA, PLPA, linklist thing, I'm not going to
stop you.
In REVIEW I just search the LPAQ "manually" because I expect that's what
the system would have to do (I should check that one day). To search
the PLPA directory the system has a hashing routine which should make it
much more efficient than the full sequential search - as if that matters
on you own herc box.
* REGS 0 AND 1 - CONTAIN NAME
* REG 3 - CVT
* REGS 7 8 9 - WORK REGS
* REG 14 - RETURN - BAD RETURN 4(14)
* REG 15 - ENTRY POINT
* REG 0 - POINTS TO LPDE AFTER GOOD RETURN
SPACE
TSOPLPA LM R0,R1,BLDLNAME
STM R14,R12,12(R13)
L R3,CVTPTR(,0) POINT TO THE CVT
L R15,CVTLPDSR-CVT(,R3) GET ROUTINE ENTRY POINT
BASR R14,R15 CALL IEAVVMSR
B TSOPLPAX FOUND IN PLPA
LM R14,R12,12(R13) NOT IN PLPA, DO BLDL
...
TSOPLPAX LM R14,R12,12(R13)
Last time I pasted code it was a scrambled mess, so apologies if the
result is the same this time.
Code like that works from MVS 3.8 (actually, I bet it works on 3.7 and
maybe even earlier) to at least z/OS 2.3 where support for RMODE=64 was
added and LPDE control blocks grew by 8 bytes. In z/OS 2.2 LPDEs were
the same size as they are in MVS 3.8. Naturally, you need to know the
LPDE size if you are stepping through the PLPA directory sequentially.
Cheers,
Greg
pricgren pricgren@yahoo.com [H390-MVS]
2018-10-21 13:06:49 UTC
Permalink
Post by Mike Großmann ***@ymail.com [H390-MVS]
In about 1986 IBM introduced the TSVT. In all IBM examples of how to
address IKJCT441, the entry point is fetched via the TSVT.
But all my colleagues and friend telling me to use LOAD. I am
confused. :)
The coded examples in the IBM book issue a LINK macro if the address in
the TSVT is zero.  Given that you have no TSVT, I'd say the IBM coded
examples indicate that you should issue a LINK.  But if you really want
to get the address from the TSVT you could make such a control block and
set a routine address into it.  After all, who's going to stop you doing
that?  If you find the address via the LPDE in the PLPA directory, does
that mean you do not support using MLPA?
Post by Mike Großmann ***@ymail.com [H390-MVS]
What does the big picture look like? We're trying to extend BREXX to support TSO variables.
Does that mean you are wishing to allow programs call a IKJCT441-like
routine to access and update BREXX variables?  If so, you will have to
provide the IKJCT441-like routine.

IBM's routine of that name supports interactions with both CLIST and
REXX variables, so presumably any "master" entry point will have to be
able to determine if the caller is wishing to interact with BREXX or
CLIST variables, and branch to the relevant code.

You certainly would not want to use any existing CLIST oriented routine
for your IKJCT441-like functions, though you may (or may not) wish to
cater for invoking another routine to perform those functions if your
routine determines that there is no relevant active environment for it
to interact with.

The IKJCT441 routine that I wrote was really to fill a functionality gap
in interacting with CLIST variables so that it could become possible for
ISPF dialog CLISTs to work by allowing CLIST variables to function as
ISPF variables.  I thought I may as well use the format of IBM's
parameter list to minimise surprises for other potential exploiters, and
reduce the documentation that I had to produce.  I did not think the
creation of a TSVT just to house a single pointer was a worthwhile
endeavour.

I ship most of my mods as SMP usermods to make them easy (or at least to
have a well defined process) to install and uninstall.  You are probably
best to run without this usermod and develop your own thing until it
functions to your satisfaction, and then look at accommodating CLIST
support later on if you are interested in doing so.  You might choose to
shoehorn in (parts of) my humble offering, or replace it with something
else which may even be better.

Cheers,
Greg
W Mainframe mainframew@yahoo.com [H390-MVS]
2018-10-21 14:00:26 UTC
Permalink
IKJCT441 is useful and powerful, but it only has effect for CLIST. In BREXX I needed to understand the logic of assign/retrieve variable info. I have functions like rxsetvar and rxgetvar, this is good to extend my brexx hist commands, for example, I have my personal EXECIO and some other small utilities.Unfortunately BREXX has no REXXSAA standard routines to do this. The rexx Regina interpreter uses it.
Dan



Sent from Yahoo Mail for iPhone


On Sunday, October 21, 2018, 10:06 AM, pricgren ***@yahoo.com [H390-MVS] <H390-***@yahoogroups.com> wrote:

 
Post by Mike Großmann ***@ymail.com [H390-MVS]
In about 1986 IBM introduced the TSVT. In all IBM examples of how to
address IKJCT441, the entry point is fetched via the TSVT.
But all my colleagues and friend telling me to use LOAD. I am
confused. :)
The coded examples in the IBM book issue a LINK macro if the address in
the TSVT is zero.  Given that you have no TSVT, I'd say the IBM coded
examples indicate that you should issue a LINK.  But if you really want
to get the address from the TSVT you could make such a control block and
set a routine address into it.  After all, who's going to stop you doing
that?  If you find the address via the LPDE in the PLPA directory, does
that mean you do not support using MLPA?
Post by Mike Großmann ***@ymail.com [H390-MVS]
What does the big picture look like? We're trying to extend BREXX to support TSO variables.
Does that mean you are wishing to allow programs call a IKJCT441-like
routine to access and update BREXX variables?  If so, you will have to
provide the IKJCT441-like routine.

IBM's routine of that name supports interactions with both CLIST and
REXX variables, so presumably any "master" entry point will have to be
able to determine if the caller is wishing to interact with BREXX or
CLIST variables, and branch to the relevant code.

You certainly would not want to use any existing CLIST oriented routine
for your IKJCT441-like functions, though you may (or may not) wish to
cater for invoking another routine to perform those functions if your
routine determines that there is no relevant active environment for it
to interact with.

The IKJCT441 routine that I wrote was really to fill a functionality gap
in interacting with CLIST variables so that it could become possible for
ISPF dialog CLISTs to work by allowing CLIST variables to function as
ISPF variables.  I thought I may as well use the format of IBM's
parameter list to minimise surprises for other potential exploiters, and
reduce the documentation that I had to produce.  I did not think the
creation of a TSVT just to house a single pointer was a worthwhile
endeavour.

I ship most of my mods as SMP usermods to make them easy (or at least to
have a well defined process) to install and uninstall.  You are probably
best to run without this usermod and develop your own thing until it
functions to your satisfaction, and then look at accommodating CLIST
support later on if you are interested in doing so.  You might choose to
shoehorn in (parts of) my humble offering, or replace it with something
else which may even be better.

Cheers,
Greg


#yiv0319754205 #yiv0319754205 -- #yiv0319754205ygrp-mkp {border:1px solid #d8d8d8;font-family:Arial;margin:10px 0;padding:0 10px;}#yiv0319754205 #yiv0319754205ygrp-mkp hr {border:1px solid #d8d8d8;}#yiv0319754205 #yiv0319754205ygrp-mkp #yiv0319754205hd {color:#628c2a;font-size:85%;font-weight:700;line-height:122%;margin:10px 0;}#yiv0319754205 #yiv0319754205ygrp-mkp #yiv0319754205ads {margin-bottom:10px;}#yiv0319754205 #yiv0319754205ygrp-mkp .yiv0319754205ad {padding:0 0;}#yiv0319754205 #yiv0319754205ygrp-mkp .yiv0319754205ad p {margin:0;}#yiv0319754205 #yiv0319754205ygrp-mkp .yiv0319754205ad a {color:#0000ff;text-decoration:none;}#yiv0319754205 #yiv0319754205ygrp-sponsor #yiv0319754205ygrp-lc {font-family:Arial;}#yiv0319754205 #yiv0319754205ygrp-sponsor #yiv0319754205ygrp-lc #yiv0319754205hd {margin:10px 0px;font-weight:700;font-size:78%;line-height:122%;}#yiv0319754205 #yiv0319754205ygrp-sponsor #yiv0319754205ygrp-lc .yiv0319754205ad {margin-bottom:10px;padding:0 0;}#yiv0319754205 #yiv0319754205actions {font-family:Verdana;font-size:11px;padding:10px 0;}#yiv0319754205 #yiv0319754205activity {background-color:#e0ecee;float:left;font-family:Verdana;font-size:10px;padding:10px;}#yiv0319754205 #yiv0319754205activity span {font-weight:700;}#yiv0319754205 #yiv0319754205activity span:first-child {text-transform:uppercase;}#yiv0319754205 #yiv0319754205activity span a {color:#5085b6;text-decoration:none;}#yiv0319754205 #yiv0319754205activity span span {color:#ff7900;}#yiv0319754205 #yiv0319754205activity span .yiv0319754205underline {text-decoration:underline;}#yiv0319754205 .yiv0319754205attach {clear:both;display:table;font-family:Arial;font-size:12px;padding:10px 0;width:400px;}#yiv0319754205 .yiv0319754205attach div a {text-decoration:none;}#yiv0319754205 .yiv0319754205attach img {border:none;padding-right:5px;}#yiv0319754205 .yiv0319754205attach label {display:block;margin-bottom:5px;}#yiv0319754205 .yiv0319754205attach label a {text-decoration:none;}#yiv0319754205 blockquote {margin:0 0 0 4px;}#yiv0319754205 .yiv0319754205bold {font-family:Arial;font-size:13px;font-weight:700;}#yiv0319754205 .yiv0319754205bold a {text-decoration:none;}#yiv0319754205 dd.yiv0319754205last p a {font-family:Verdana;font-weight:700;}#yiv0319754205 dd.yiv0319754205last p span {margin-right:10px;font-family:Verdana;font-weight:700;}#yiv0319754205 dd.yiv0319754205last p span.yiv0319754205yshortcuts {margin-right:0;}#yiv0319754205 div.yiv0319754205attach-table div div a {text-decoration:none;}#yiv0319754205 div.yiv0319754205attach-table {width:400px;}#yiv0319754205 div.yiv0319754205file-title a, #yiv0319754205 div.yiv0319754205file-title a:active, #yiv0319754205 div.yiv0319754205file-title a:hover, #yiv0319754205 div.yiv0319754205file-title a:visited {text-decoration:none;}#yiv0319754205 div.yiv0319754205photo-title a, #yiv0319754205 div.yiv0319754205photo-title a:active, #yiv0319754205 div.yiv0319754205photo-title a:hover, #yiv0319754205 div.yiv0319754205photo-title a:visited {text-decoration:none;}#yiv0319754205 div#yiv0319754205ygrp-mlmsg #yiv0319754205ygrp-msg p a span.yiv0319754205yshortcuts {font-family:Verdana;font-size:10px;font-weight:normal;}#yiv0319754205 .yiv0319754205green {color:#628c2a;}#yiv0319754205 .yiv0319754205MsoNormal {margin:0 0 0 0;}#yiv0319754205 o {font-size:0;}#yiv0319754205 #yiv0319754205photos div {float:left;width:72px;}#yiv0319754205 #yiv0319754205photos div div {border:1px solid #666666;min-height:62px;overflow:hidden;width:62px;}#yiv0319754205 #yiv0319754205photos div label {color:#666666;font-size:10px;overflow:hidden;text-align:center;white-space:nowrap;width:64px;}#yiv0319754205 #yiv0319754205reco-category {font-size:77%;}#yiv0319754205 #yiv0319754205reco-desc {font-size:77%;}#yiv0319754205 .yiv0319754205replbq {margin:4px;}#yiv0319754205 #yiv0319754205ygrp-actbar div a:first-child {margin-right:2px;padding-right:5px;}#yiv0319754205 #yiv0319754205ygrp-mlmsg {font-size:13px;font-family:Arial, helvetica, clean, sans-serif;}#yiv0319754205 #yiv0319754205ygrp-mlmsg table {font-size:inherit;font:100%;}#yiv0319754205 #yiv0319754205ygrp-mlmsg select, #yiv0319754205 input, #yiv0319754205 textarea {font:99% Arial, Helvetica, clean, sans-serif;}#yiv0319754205 #yiv0319754205ygrp-mlmsg pre, #yiv0319754205 code {font:115% monospace;}#yiv0319754205 #yiv0319754205ygrp-mlmsg * {line-height:1.22em;}#yiv0319754205 #yiv0319754205ygrp-mlmsg #yiv0319754205logo {padding-bottom:10px;}#yiv0319754205 #yiv0319754205ygrp-msg p a {font-family:Verdana;}#yiv0319754205 #yiv0319754205ygrp-msg p#yiv0319754205attach-count span {color:#1E66AE;font-weight:700;}#yiv0319754205 #yiv0319754205ygrp-reco #yiv0319754205reco-head {color:#ff7900;font-weight:700;}#yiv0319754205 #yiv0319754205ygrp-reco {margin-bottom:20px;padding:0px;}#yiv0319754205 #yiv0319754205ygrp-sponsor #yiv0319754205ov li a {font-size:130%;text-decoration:none;}#yiv0319754205 #yiv0319754205ygrp-sponsor #yiv0319754205ov li {font-size:77%;list-style-type:square;padding:6px 0;}#yiv0319754205 #yiv0319754205ygrp-sponsor #yiv0319754205ov ul {margin:0;padding:0 0 0 8px;}#yiv0319754205 #yiv0319754205ygrp-text {font-family:Georgia;}#yiv0319754205 #yiv0319754205ygrp-text p {margin:0 0 1em 0;}#yiv0319754205 #yiv0319754205ygrp-text tt {font-size:120%;}#yiv0319754205 #yiv0319754205ygrp-vital ul li:last-child {border-right:none !important;}#yiv0319754205
Tony Harminc tharminc@gmail.com [H390-MVS]
2018-10-19 23:17:06 UTC
Permalink
Post by Mike Großmann ***@ymail.com [H390-MVS]
Thanks for pointing me in the right direction. Unfortunately, I noticed
that on MVS3.8j there is no CVTTVT entry (TSVT - TSO vector table) in the
CVT.
Post by Mike Großmann ***@ymail.com [H390-MVS]
Is there another control block where I can find the address of a LPA
module?

There is a routine IEAQCDSR that will find the CDE for an LPA module. This
has been around since the earliest days of MVS, and still works today on
z/OS, but I don't know if it was ever a supported interface.

There are two adjacent CVT fields
CVTQCDSR DC V(IEAQCDSR) - CDE SEARCH ROUTINE ADDRESS (OS/VS2)
CVTQLPAQ DC V(IEAQLPAQ) - ADDRESS OF POINTER TO MOST RECENT ENTRY
* ON LINK PACK AREA CDE QUEUE (OS/VS2)
and the call to IEAQCDSR looks like:

* INPUTS: R8 - HEAD OF LPAQ IN CVT
* R9 - @OF 8 BYTE FLD W/ NAME OF CDE TO FIND
*
* OUTPUTS:
* IF CDE FOUND;
* RETURN TO R14 WITH R11 -> CDE
* IF NOT FOUND;
* RETURN TO R14+4

In assembler it would be:
L R3,CVTPTR @CVT
LA R9,MODNAME @Module Name (8 bytes, blank padded)
L R8,CVTQLPAQ Head of LPAQ
L R15,CVTQCDSR @(IEAQCDSR)
BASR R14,R15 Call
B FOUND +0 - found it - R11 -> CDE
B NOTFOUND +4 - not found

This may be tricky to call from C, because of the very non standard input,
output, and return conventions. And of course there is no locking, so while
anyone can call it, the system can in theory be updating it at the same
time, though this is unlikely after IPL time.

Tony H.
Mike Großmann mike.grossmann@ymail.com [H390-MVS]
2018-10-23 19:43:00 UTC
Permalink
Post by Mike Rayborn ***@gmail.com [H390-MVS]
typedef struct ikjct441_plist IKJCT441;
struct ikjct441_plist {
int *ecode;
const char **name;
int *namelen;
char **value;
int *vallen;
void *ect;
int *retcode;
IKJCT441 *next;
};
int ikjct441(int ecode, const char *name, char *value, int value_size)
{
int rc = 0;
int namelen = name ? strlen(name) : 0;
void *ectnull = (void*)0xFFFFFFFF;
unsigned *psa = (unsigned *)0;
unsigned *cvt = (unsigned *)psa[16/4];
unsigned *tvt = (unsigned *)cvt[156/4];
int (*ep)(int *, const char**, int *, char **, int *, void *, int *, IKJCT441 *)
= (void*)tvt[40/4];
IKJCT441 plist;
/* construct the parameter list */
plist.ecode = &ecode;
plist.retcode = &rc;
plist.name = &name;
plist.namelen = &namelen;
plist.value = &value;
plist.vallen = &value_size;
plist.ect = ectnull;
plist.retcode = &rc;
plist.next = (IKJCT441*)0;
ep(plist.ecode, plist.name, plist.namelen, plist.value, plist.vallen, plist.ect, plist.retcode, plist.next);
return rc;
}
Loading...