In PDS/Startool it is possible to get the member list of a PDS or PDSE
LOADLIB and see the Link Date as a column in the member list. This is
extremely convenient and is also a sortable column. The PDS/Startool ATTR and
HISTORY commands can also be used from REXX to get this same data when more
logic is needed. Again, extremely convenient when needed.
When I am unlucky enough to be stuck doing work in a shop where they do not
have any tools like PDS/Startool (only TSO/ISPF and no vendor products
with no options to suggest or recommend), I periodically (like now) need to
see the link date on all the modules in a PDS LOADLIB. The STATS(YES)
option of LMMLIST and LMMFIND do not provide the Link Date on Load Modules.
I am not concerned with PDSE's at this point only PDS's. Does anyone have
a REXX technique and/or sample code for finding and translating the link
date to a readable format for all members in a PDS LOADLIB?
Thanks,
Rob
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
Run AMBLIST with this input
LISTIDR TITLE=('IMSP.SYSTEM.V10.DBDLIB',43),DDN=LOADLIB
The output is routed to a temporary dataset which is then scanned for
module link date. My scan routing is written in Pascal, but this could
be changed to a REXX scan.
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
Thanks,
Rob
In a message dated 1/19/2011 10:03:54 A.M. US Mountain Standard Time,
This works with source PDS, never tried it with a LOADLIB.
Allocate the PDS (will not work with PDSE) as DSORG=PS,LRECL=256,BLKSIZE=256,BUFNO=60
It opens the directory. I do not know if the date is in the directory or
only inside the load modules.
David Speake
As for a native REXX exec to read the linkdate. I've never seen one. The problem
here is that the linkdate does not appear in the PDS/PDSE directory information.
So for a native REXX utility you would be reading a record for every member in
the file. Reading the directory is simple and fast to read a record from every
member would be slow.
Hope this helps.
Richard Rozentals
________________________________
From: Robert Zenuk <Robz...@AOL.COM>
To: TSO-...@VM.MARIST.EDU
Sent: Wed, January 19, 2011 1:24:16 PM
Subject: Re: [TSO-REXX] Link Date in a PDS
It seems unlikely to me that anything you can write in REXX will
outperform AMBLIST for this function. The various dates are not stored
in the PDS[E] directory, so you will have to read a good portion of
each module. The Binder API is the official tool for this, and you can
call a number of its informational routines directly from REXX, but
with poor performance because of continual reloading of the API
module.
Tony H.
Thanks anyway...
Rob
In a message dated 1/19/2011 12:07:22 P.M. US Mountain Standard Time,
r_roz...@YAHOO.COM writes:
The other option is the CBT utility(Free utility) called PDS. If the
customer
site you're at will allow you to install it that is. The PDS utility will
extract the linkdate and display it just like the star tool. You can find
the
utility at the CBT site: www.cbttape.org
As for a native REXX exec to read the linkdate. I've never seen one. The
problem
here is that the linkdate does not appear in the PDS/PDSE directory
information.
So for a native REXX utility you would be reading a record for every
member in
the file. Reading the directory is simple and fast to read a record from
every
member would be slow.
Hope this helps.
Richard Rozentals
________________________________
From: Robert Zenuk <Robz...@AOL.COM>
To: TSO-...@VM.MARIST.EDU
Sent: Wed, January 19, 2011 1:24:16 PM
Subject: Re: [TSO-REXX] Link Date in a PDS
It is definitely an option, but AMBLIST is very slow for large PDS's.
Thanks,
Rob
Regards
----------------------------------------------------------------------
I am saying use the CBT PDS tool (the free one).
Richard Rozentals
________________________________
From: Robert Zenuk <Robz...@AOL.COM>
To: TSO-...@VM.MARIST.EDU
Sent: Wed, January 19, 2011 5:09:17 PM
And my JCL
//jobcard...
//LINKDATE EXEC PGM=IKJEFT01,
// PARM='ISPSTART CMD(%LINKDATE your.LOADLIB)'
//SYSEXEC DD DSN=your.EXEC,DISP=SHR
//ISPPLIB DD DSN=your.ISPPLIB,DISP=SHR
//ISPSLIB DD DSN=your.ISPSLIB,DISP=SHR
//ISPMLIB DD DSN=your.ISPMLIB,DISP=SHR
//ISPTLIB DD DDNAME=ISPTABL
// DD DSN=your.ISPTLIB,DISP=SHR
//ISPTABL DD LIKE=your.ISPTLIB,UNIT=VIO,DSORG=PO
//ISPPROF DD LIKE=your.ISPTLIB,UNIT=VIO,DSORG=PO
//ISPLOG DD SYSOUT=*,RECFM=VA,LRECL=125
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY
Rob
In a message dated 1/19/2011 1:21:33 P.M. US Mountain Standard Time,
Charles....@OA.MO.GOV writes:
Rob, Here's a rexx example I wrote in 2005. The initial exec just worked
with a PDS. A few years later I update it for PDS/E's. (There's also
some code that does DB2 timestamp checking, but it requires some set-up before
invoking the routine, so just ignore that.) As far as I know, it's worked
well in our shop.
Here's the basic steps that I followed...
1. Build a list of members
2. Read each member line by line and search for the linkage editor eye
catcher. In a PDS it's in a fixed position. With a PDS/E you have to use a
rexx POS() to find it. (At least that's what my research indicated.)
3. Once the eye catcher is found, parse out the date/time and format it.
To invoke: CALL @LINKDTE pdsname memberpattern 'LINK'
/*-------------------------------------------------------- REXX ----- */
/* FUNC NAME = @LINKDATE */
/* */
/* */
/* DESCRIPTION = ROUTINE TO LIST MEMBERS OF A PDS AND OPTIONALLY */
/* READ THE LOAD MEMBERS TO GET THE LINK EDIT DATE/TIME*/
/* */
/* LINK OPTION IS NOT SUPPORTED FOR PDSE'S */
/* (NOW SUPPORTS PDSE LOAD MODULES. SEE 07.2008 UPDATE)*/
/* */
/* INPUT = DNAME - PDS TO READ MEMBERS FROM */
/* MFILTER - MEMBER NAME/WILDCARD NAME USED TO FILER */
/* LIST OF MEMBERS */
/* OPTION1 - VALUE OF 'LINK' INDICATES LINK EDIT DATE- */
/* TIME ARE RETURNED. ALL OTHER VALUES */
/* RETURN A LIST OF MEMBERS. CALLING ROUTINE*/
/* MUST ENSURE THAT THIS IS A LOAD LIBRARY */
/* OPTION2 - NOT USED AT THIS TIME. */
/* */
/* OUTPUT = FOR NON-ZERO RETURN CODES: */
/* RC ERROR-MESSAGE */
/* FOR ZERO RETURN CODES: */
/* RC MEM1 DATE1 TIME1 ; MEM2 DATE2 TIME2 ; .... */
/* */
/* THE FIRST WORD WILL ALWAYS BE A NUMBERIC RETURN CODE*/
/* MEMBER INFORMATION IS SEPARATED BY ';' AND MUST BE */
/* PARSED BY THE CALLING ROUTINE. */
/* */
/* */
/* AUTHOR = CHARLES WILLIAMS */
/* */
/* CREATE DATE = 01.25.2005 */
/* */
/* CHANGE ACTIVITY */
/* 07.01.2008 ADDED SUPPORT FOR PDSE LOAD LIBRARIES */
/*--------------------------------------------------------------------*/
ADDRESS ISPEXEC
ARG DNAME MFILTER OPTION1 OPTION2
RETRC=''
RETURNVAL=''
MEMBER=''
RCX = LISTDSI("'"DNAME"'")
IF SYSDSSMS='PROGRAM_LIBRARY' THEN
PDSE='Y'
ELSE
PDSE='N'
"LMINIT DATAID(FRMID) DATASET('"DNAME"') ENQ(SHR)"
IF RC>0 THEN DO
RETURNVAL=RC 'LMINIT'
SIGNAL RETURN3
END
"LMOPEN DATAID("FRMID") OPTION(INPUT)"
IF RC>0 THEN DO
RETURNVAL=RC 'LMOPEN'
SIGNAL RETURN2
END
"LMMLIST DATAID("FRMID") OPTION(LIST) MEMBER(MEMBER)",
"STATS(NO) PATTERN("MFILTER")"
IF RC>0 THEN DO
RETURNVAL=RC 'MEMBER(S) NOT FOUND'
SIGNAL RETURN1
END
DO FOREVER
RETURNVAL=RETURNVAL||';' MEMBER
IF OPTION1='LINK' | OPTION1='LINKDB2' THEN DO
"LMMFIND DATAID("FRMID") MEMBER("MEMBER")"
CALL READ_MEMBER
END
"LMMLIST DATAID("FRMID") OPTION(LIST) MEMBER(MEMBER)",
"STATS(NO) PATTERN("MFILTER")"
IF RC>0 THEN DO
RETURNVAL='0' STRIP(RETURNVAL,'BOTH',';')
LEAVE
END
END /*DO I=1*/
RETURN1:
"LMCLOSE DATAID("FRMID")"
RETURN2:
"LMFREE DATAID("FRMID")"
RETURN3:
RETURN RETURNVAL
READ_MEMBER:
/*SINCE EACH LOAD MODULE COULD BE BOUND TO MULTIPLE COLLECTIONS*/
/*THE TEMPTOKN TABLE COULD HAVE MULTIPLE ENTIRES PER MEMBER. */
/*DATA ATTRIBUTES ARE LOADED INTO AN ARRAY SO MULTIPLE SEARCHES*/
/*CAN BE DONE FOR TIMESTAMP MATCHES. */
HDATE=''; HTIME='' /*LINK DATE/TIME*/
COLLID.=''
LOADTOKN.=''
DBRMLIB.=''
BINDTIME.=''
TSMATCH.=' ' /*TIMESTAMP MATCH FLAG*/
EOFFLAG=0
CNT1=0
TOKNFND=0
FINDDATE='Y' /*ALWAYS FIND LINK EDIT DATE*/
IF OPTION1='LINKDB2' THEN DO /*IF DB2 REQUEST AND WE HAVE DB2*/
HMEMBER=MEMBER /*LOAD INTO ARRAYS. */
"TBVCLEAR TEMPTOKN"
MEMBER=HMEMBER
"TBTOP TEMPTOKN"
"TBSARG TEMPTOKN NAMECOND(MEMBER,EQ)"
DO FOREVER
"TBSCAN TEMPTOKN"
IF RC = 8 THEN LEAVE
CNT1=CNT1+1
COLLID.CNT1=COLLID ; LOADTOKN.CNT1=LOADTOKN
DBRMLIB.CNT1=DBRMLIB ; BINDTIME.CNT1=BINDTIME
END
IF CNT1>0 THEN DO /*TO ATTEMPT TO FIND TOKEN. */
FINDTOKN='Y'
TSMATCH.='NO ' /*TIMESTAMP MATCH FLAG*/
END
ELSE DO
FINDTOKN='N'
END
END
ELSE DO
FINDTOKN='N'
END
DO UNTIL (EOFFLAG >= 8) | (FINDDATE='N' & TOKNFND=CNT1)
"LMGET DATAID("FRMID") MODE(INVAR) DATALOC(LINEIN)",
"MAXLEN(32760) DATALEN(DL)"
EOFFLAG=RC
IF EOFFLAG = 0 THEN DO
IF FINDDATE='Y' THEN DO
CALL GET_LINK_DATE
END /*IF FINDDATE='Y' THEN DO*/
IF FINDTOKN='Y' THEN DO
DO I=1 TO CNT1 /*CHECK LINE FOR ALL TOKENS*/
IF POS(X2C(LOADTOKN.I),LINEIN) > 0 THEN DO
TSMATCH.I='YES' /*TIMESTAMP MATCH ARRAY*/
END
END /*DO I=1*/
END /*IF FINDTOKN='Y' THEN DO*/
END
END /*END DO UNTIL*/
IF HDATE='' THEN HDATE='????-??-??'
IF HTIME='' THEN HTIME='??.??.??'
RETURNVAL=RETURNVAL HDATE HTIME LEFT(COLLID.1,10) LEFT(TSMATCH.1,6),
LEFT(DBRMLIB.1,40) BINDTIME.1
IF CNT1>1 THEN DO
MEMOUT='. '
HDATE='. '
HTIME= '. '
DO I=2 TO CNT1
RETURNVAL=RETURNVAL||';'||MEMOUT HDATE HTIME LEFT(COLLID.I,10),
LEFT(TSMATCH.I,6) LEFT(DBRMLIB.I,40) BINDTIME.I
END /*DO I=2*/
END
RETURN
GET_LINK_DATE:
/* THE FOLLOWING SHOWS LINKAGE EDITOR EYE CATCHER AND FORMAT OF DATE/
TIME INFORMATION FOR A PDS AND PDSE. PDS WILL STORE THIS IN A FIXED
LOCATION. PDSE WILL BE VARIABLE SO A POS() FUNCTION IS USED TO FIND
THE EYECATCHER. */
/* /* PDS PDSE */
/* LINEIN='
5695PMB01 Ü " ©>
' 5695PMB01 .....?. .. */ */
/* */
/* /* ----+----1----+----2----+ ----+----1----+----2----+ */
/* 810FFFFDDCFF4000170533 FFFFDDCFF40020260402 */
/* 05256957420101346F144F 569574201013028F153F */ */
IF PDSE='Y' THEN DO
LINKPOS= POS('5695PMB01',LINEIN)
IF LINKPOS > 0 THEN DO
HDATE=SUBSTR(LINEIN,LINKPOS+13,3)
HTIME=SUBSTR(LINEIN,LINKPOS+16,4)
END
ELSE DO
RETURN /*THIS LINE DOES NOT CONTAIN THE EYE CATCHER*/
END
END /*IF PDSE='Y'..*/
ELSE DO
/****** PDS ******/
LED=SUBSTR(LINEIN,4,9)
LED44=SUBSTR(LINEIN,4,4)
IF LED44='5695' |,
LED='566528408' | LED='5752SC104' | LED='5741SC104' THEN DO
HDATE=SUBSTR(LINEIN,16,3)
HTIME=SUBSTR(LINEIN,19,4)
END
ELSE DO
RETURN /*THIS LINE DOES NOT CONTAIN THE EYE CATCHER*/
END
END /*IF PDSE='Y'...ELSE DO...*/
HDATE=STRIP(C2X(HDATE),'T','F')
HDATE=DATE('S',HDATE,'J') /*CHANGE FROM YYDDD TO CCYYMMDD */
PARSE VAR HDATE CCYY 5 MM 7 DD
HDATE=CCYY||'-'||MM||'-'||DD
HTIME=STRIP(C2X(HTIME),'T','F')
IF HTIME='40404040' THEN HTIME='??.??.??'
ELSE DO
HTIME=SUBSTR(HTIME,2,6)
PARSE VAR HTIME 1 HH 3 MM 5 SS
HTIME=HH||'.'||MM||'.'||SS
END
FINDDATE='N' /*DATE FOUND, SET FLAG TO STOP LOOKING*/
RETURN
-----Original Message-----
From: ISPF discussion list [mailto:ISP...@LISTSERV.ND.EDU] On Behalf Of
Jeff Byrum
Sent: Wednesday, January 19, 2011 12:42 PM
To: ISP...@LISTSERV.ND.EDU
Subject: Re: Link Date in a PDS
Rob, not sure whether "PDS/Startool" meant "the cbttape.org tool PDS *or*
the Startool product", but if not, the cbttape.org tool called PDS does
support the ATTR command also (don't remember which file number). Installing
that may not be an option for you either.
-----Original Message-----
From: ISPF discussion list [mailto:ISP...@LISTSERV.ND.EDU] On Behalf Of
Rob Zenuk
Sent: Wednesday, January 19, 2011 11:47 AM
To: ISP...@LISTSERV.ND.EDU
Subject: Link Date in a PDS
Sorry for the cross-post.
In PDS/Startool it is possible to get the member list of a PDS or PDSE
LOADLIB and see the Link Date as a column in the member list. This is
extremely convenient and is also a sortable column. The PDS/Startool
ATTR and
HISTORY commands can also be used from REXX to get this same data when
more
logic is needed. Again, extremely convenient when needed.
When I am unlucky enough to be stuck doing work in a shop where they do
not
have any tools like PDS/Startool (only TSO/ISPF and no vendor products
with no options to suggest or recommend), I periodically (like now) need
to
see the link date on all the modules in a PDS LOADLIB. The STATS(YES)
option of LMMLIST and LMMFIND do not provide the Link Date on Load
Modules.
I am not concerned with PDSE's at this point only PDS's. Does anyone
> If anyone else needs this, here is my quick and dirty version of the
> code.
I'm surprised (though it's been years since I did any of this) that that
works without
address ispexec "control errors return"
being issued first - so that any non-zero rc from ispf services gets
returned to the exec for processing rather than causing the exec to be
cancelled.
And you'd surely want to check the rc from the LMINIT and LMGET ?
--
Jeremy C B Nicoll - my opinions are my own.
I'm not sure why you say amblist is slow - possibly running on-line
but run as a batch job it should respond quick as a flash. It must out
perform any other i/o method as it runs directly against the disk
ignoring the file and members doesn't it?
I've used several own versions of the on-line member list and they're
simple enough to write - I can mail you one that displays the first
two lines of the members instead of the stats if you need a model. To
run against amblist output should be a doddle - if I were in an mvs
shop I'd run one up for you for fun, but am without gainful employment
at the moment.
I tried your REXX variation but I'm having problems.
First, I'm using standard zOS 1.12 naming conventions.
So I'm not sure I have the right substitutions for the run.
My JCL is
//LINKDATE EXEC PGM=IKJEFT01,
// PARM='ISPSTART CMD(%LINKDATE SYS2.LINKLIB2)'
//SYSEXEC DD DSN=SYS2#.REXX.SOURCE,DISP=SHR
//ISPPLIB DD DSN=Z1BA.ISP.SISPPENU,DISP=SHR
//ISPSLIB DD DSN=Z1BA.ISP.SISPSENU,DISP=SHR
//ISPMLIB DD DSN=Z1BA.ISP.SISPMENU,DISP=SHR
//ISPTLIB DD DDNAME=ISPTABL
// DD DSN=Z1BA.ISP.SISPTENU,DISP=SHR
//ISPTABL DD LIKE=Z1BA.ISP.SISPTENU,UNIT=VIOX,DSORG=PO
//ISPPROF DD LIKE=Z1BA.ISP.SISPTENU,UNIT=VIOX,DSORG=PO
//ISPLOG DD SYSOUT=*,RECFM=VA,LRECL=125
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY
/*EOF
I had to add
otherwise nop;
to the bottom of the select statement group to make REXX happy.
I'm now hung up on the following.
31 +++ ldate = translate('1234-56-78',date('S',ldate,'J'),'12345678')
IRX0040I Error running LINKDATE, line 31: Incorrect call to routine
ISPD117
The initially invoked CLIST ended with a return code = 20040
DUDLEY.SYSTEM#1.JOB05622.D0000101.? was preallocated (no free was
done).
READY
END
Any suggestions anyone ???
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
>
> //jobcard...
> //LINKDATE EXEC PGM=IKJEFT01,
> // PARM='ISPSTART CMD(%LINKDATE your.LOADLIB)'
> //SYSEXEC DD DSN=your.EXEC,DISP=SHR
> //ISPPLIB DD DSN=your.ISPPLIB,DISP=SHR
> //ISPSLIB DD DSN=your.ISPSLIB,DISP=SHR
> //ISPMLIB DD DSN=your.ISPMLIB,DISP=SHR
> //ISPTLIB DD DDNAME=ISPTABL
> // DD DSN=your.ISPTLIB,DISP=SHR
> //ISPTABL DD LIKE=your.ISPTLIB,UNIT=VIO,DSORG=PO
> //ISPPROF DD LIKE=your.ISPTLIB,UNIT=VIO,DSORG=PO
> //ISPLOG DD SYSOUT=*,RECFM=VA,LRECL=125
> //SYSTSPRT DD SYSOUT=*
> //SYSTSIN DD DUMMY
>
>
> Rob
----------------------------------------------------------------------
> Hi Rob !
>
> I tried your REXX variation but I'm having problems.
>
> First, I'm using standard zOS 1.12 naming conventions.
> So I'm not sure I have the right substitutions for the run.
>
> My JCL is
> //LINKDATE EXEC PGM=IKJEFT01,
> // PARM='ISPSTART CMD(%LINKDATE SYS2.LINKLIB2)'
> //SYSEXEC DD DSN=SYS2#.REXX.SOURCE,DISP=SHR
> //ISPPLIB DD DSN=Z1BA.ISP.SISPPENU,DISP=SHR
> //ISPSLIB DD DSN=Z1BA.ISP.SISPSENU,DISP=SHR
> //ISPMLIB DD DSN=Z1BA.ISP.SISPMENU,DISP=SHR
> //ISPTLIB DD DDNAME=ISPTABL
> // DD DSN=Z1BA.ISP.SISPTENU,DISP=SHR
> //ISPTABL DD LIKE=Z1BA.ISP.SISPTENU,UNIT=VIOX,DSORG=PO
> //ISPPROF DD LIKE=Z1BA.ISP.SISPTENU,UNIT=VIOX,DSORG=PO
> //ISPLOG DD SYSOUT=*,RECFM=VA,LRECL=125
> //SYSTSPRT DD SYSOUT=*
> //SYSTSIN DD DUMMY
> /*EOF
Is "Z1BA" a system or user HLQ?
Things like ISPSLIB need to be allocated to whereever your sysprogs have
installed ispf itself.
ISPTLIB & ISPPROF & ISPTABL need to start with a personal dataset; for batch
ispf that can be a temporary file.
It used to be the case, and maybe still is, that ispf would enqueue on the
first dataset in the ISPTLIB concatenation for some personal things so that
MUST be a personal dataset not a system one.
--
Jeremy C B Nicoll - my opinions are my own.
----------------------------------------------------------------------
Right, Z1BA is a HLQ.
After some hacking the code executes for me now and produces results,
although I'm still getting a REXX syntax error on
ldate = translate('1234-56-78',date('S',ldate,'J'),'12345678')
If I comment out that statement I get reasonable output.
Regards
Lorne
On 1/20/2011 3:18 PM, Jeremy Nicoll - ls tsrx wrote:
>
> Is "Z1BA" a system or user HLQ?
>
> Things like ISPSLIB need to be allocated to whereever your sysprogs have
> installed ispf itself.
>
> ISPTLIB& ISPPROF& ISPTABL need to start with a personal dataset; for batch
> ispf that can be a temporary file.
>
> It used to be the case, and maybe still is, that ispf would enqueue on the
> first dataset in the ISPTLIB concatenation for some personal things so that
> MUST be a personal dataset not a system one.
----------------------------------------------------------------------
ldate = translate('1234-56-78',date('S'),'12345678')
Tony
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf
Of Lorne Dudley
Sent: Thursday, January 20, 2011 3:29 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: Link Date in a PDS
Thanks, I just figured out the problem.
The code should be
ldate = substr(data,ec+13,3) /* not ec+12 */
This picks up the low-order year byte of the two byte packed decimal
year. The date function wants 'J' dates in yyddd format, not yyyyddd.
Regards
Lorne
On 1/20/2011 3:43 PM, Vitonis, Tony wrote:
> The DATE function doesn't take that many arguments. Perhaps you want
> just this?:
>
> ldate = translate('1234-56-78',date('S'),'12345678')
>
> Tony
>
----------------------------------------------------------------------
> Hi Jeremy !
>
> Right, Z1BA is a HLQ.
Obviously, but I asked if it was a /system/ one or a /user/ one, at your
site.
--
Jeremy C B Nicoll - my opinions are my own.
----------------------------------------------------------------------
On 1/20/2011 3:52 PM, Jeremy Nicoll - ls tsrx wrote:
> Lorne Dudley<dud...@QUEENSU.CA> wrote:
>
>> Hi Jeremy !
>>
>> Right, Z1BA is a HLQ.
>
> Obviously, but I asked if it was a /system/ one or a /user/ one, at your
> site.
----------------------------------------------------------------------
I'm missing valid members that appear in the AMBLIST method.
The modified code is listed below.
The problem is that AMBLIST reports the LINK dates for 513 members,
while the REXX routine below only lists 105 members for the same library.
$AJ140 reported below does have the string 5695DF108 within, followed by
the packed decimal date field at the appropriate offset, so it would
appear that the REXX code is not offering up the member for examination ???
The earliest dates reported by both AMBLIST and the REXX code go back to
1985.
Does anyone have any suggestions for code change or trouble-shooting
suggestions ???
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
-----------------------------------
Beginning members reported by the AMBLIST method shown below.
The first member reported by the REXX code is ABENDX.
AMBLIST reports on 512 members.
REXX code reports on only 105 members. (Missed the first 18 members.)
$AJ140 2003/10/16
$AJ210 2001/04/19
$AJ210#X 2001/04/19
$AJ210#1 2001/04/19
$AJ210X 2001/04/19
$AJ270 1999/11/09
$AJ270#X 1999/11/16
$AJ270X 1999/11/08
$AJ3 1991/12/24
$AJ390#0 1997/10/24
$AJ390X 1997/10/22
$AJ4 1990/10/09
$AJ430 1996/06/06
$AJ430X 1996/06/05
$AJ520 1997/12/04
$DA210#1 2003/02/26
$DA270#1 1999/11/09
$DN210#1 2001/04/19
ABENDX 1995/03/28 <--- first member reported by REXX
------------------------------------
//LINKDATE EXEC PGM=IKJEFT01,
// PARM='ISPSTART CMD(%LINKDATE SYS2.LINKLIB2)'
//SYSEXEC DD DSN=SYS2#.REXX.SOURCE,DISP=SHR
//ISPPLIB DD DSN=Z1BA.ISP.SISPPENU,DISP=SHR
//ISPSLIB DD DSN=Z1BA.ISP.SISPSENU,DISP=SHR
//ISPMLIB DD DSN=Z1BA.ISP.SISPMENU,DISP=SHR
//ISPTLIB DD DDNAME=ISPTABL
// DD DSN=Z1BA.ISP.SISPTENU,DISP=SHR
//ISPTABL DD LIKE=Z1BA.ISP.SISPTENU,UNIT=VIOX,DSORG=PO
//ISPPROF DD LIKE=Z1BA.ISP.SISPTENU,UNIT=VIOX,DSORG=PO
//ISPLOG DD SYSOUT=*,RECFM=VA,LRECL=125
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD DUMMY
/*EOF
------------------------------------
/* rexx - LINKDATE list members in a LOADLIB PDS and their link dates */
arg dsn pat
if pat = '' then pat = '*'
count = 0
loadcount = 0
ec = 0
eczero = 0
address ISPEXEC "LMINIT DATAID(PDS) DATASET('"dsn"') ENQ(SHR)"
address ISPEXEC "LMOPEN DATAID("pds")"
do forever
address ISPEXEC "LMMLIST DATAID("pds") OPTION(LIST) STATS(NO)",
"MEMBER(MEM) PATTERN("pat")"
if RC <> 0 then leave
loadmem = mem
address ISPEXEC "LMMFIND DATAID("pds") MEMBER("loadmem") STATS(NO)"
address ISPEXEC "LMGET DATAID("pds") MODE(MULTX) MAXLEN(2000)",
"DATALOC(DATA) DATALEN(LEN)"
select
when pos('5695PMB01',data) <> 0 then ec = pos('5695PMB01',data)
when pos('5695DF108',data) <> 0 then ec = pos('5695DF108',data)
when pos('566528408',data) <> 0 then ec = pos('566528408',data)
/* 566529508 added */
when pos('566529508',data) <> 0 then ec = pos('566529508',data)
when pos('5752SC104',data) <> 0 then ec = pos('5752SC104',data)
when pos('5741SC104',data) <> 0 then ec = pos('5741SC104',data)
/* otherwise nop; */
otherwise eczero = eczero + 1 ;
end
if ec > 0 then
do
ldate = substr(data,ec+13,3)
/* layout at ec+12 , packed decimal, is yyyydddF */
ldate = strip(c2x(ldate),'T','F')
ldate = translate('1234-56-78',date('S',ldate,'J'),'12345678')
say left(loadmem,8) ldate
loadcount = loadcount + 1
/* reset ec */
ec = 0
end
count = count + 1
end
address ISPEXEC "LMMLIST DATAID("pds") OPTION(FREE)"
address ISPEXEC "LMCLOSE DATAID("pds")"
address ISPEXEC "LMFREE DATAID("pds")"
say loadcount 'load modules in' count 'members in' dsn
say 'eczero = ' || eczero
------------------------------------
I am running this on a z/OS 1.11 system and the oldest module in this PDS
goes back to 1983 (1983-10-05 to be exact). As I was debugging it, I was
trying to identify all the eyecatchers necessary, so I intentionally left off
the otherwise clause to allow it to fail if an eyecatcher was not found.
I then browsed the module to determine the eyecatcher and browsed in hex
to confirm the offset was the same. I assumed (bad) going back to 1983 was
sufficient and would handle most cases. I was able to use PDS (Startool
version) in my shop to confirm the link dates matched my REXX EXEC's
output... It worked in my shop and the shop I was writing it for, so I assumed it
worked and I sent it. Sorry if it caused any confusion or heart ache.
If the eyecatcher is not found, the ec (eyecatcher position) is zero and
there is no reason to try and process the module. However, if the
eyecatcher is found but in the wrong place, the substr will extract something that
is not a date and the translate(date()) will fail. I report the number of
load modules (loadcount) and the number of members (count). When I finally
had loadcount = count for my 33,287 member PDS, I assumed I had found all
the valid eyecatchers back to 1983... Apparently not...
In a debug version I was doing a say '===>' mem for the member right after
the LMGET so I could see when a member was being "dropped". If my total
line count wasn't double my member count, I searched for the member missing
the details. In the beginning, I wasn't initializing "ec" so the
substr(data,ec+12,3) would just fail for bad arithmetic... This made it blindingly
obvious where to look (the member right after the last good one printed).
Why you had to change the offset from 12 to 13 confuses me... None of our
modules contain the date in yyyydddF format. They are all yydddF
Rob
In a message dated 1/20/2011 9:22:18 P.M. US Mountain Standard Time,
The things that he is looking for, like "5695PMB01" could be, more or less, anywhere in the member, including splitted in 2 lines-
The Rexx doesn't work if so.
Also checking for date that is 404040 is missing
/Lasse
-----Ursprungligt meddelande-----
Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r Lorne Dudley
Skickat: den 21 januari 2011 05:22
Till: TSO-...@VM.MARIST.EDU
�mne: Re: [TSO-REXX] Link Date in a PDS
Thanks for the tip. I modified the code to the following.
address ISPEXEC "LMMLIST DATAID("pds") OPTION(LIST) STATS(NO)",
"MEMBER(MEM) PATTERN("pat")"
say 'mem=' || mem || ' RC=' RC
if RC <> 0 then leave
loadmem = mem
address ISPEXEC "LMMFIND DATAID("pds") MEMBER("loadmem") STATS(NO)
/* address ISPEXEC "LMGET DATAID("pds") MODE(MULTX) MAXLEN(2000)", */
address ISPEXEC "LMGET DATAID("pds") MODE(MULTX) MAXLEN(31000)",
"DATALOC(DATA) DATALEN(LEN)"
say 'len=' || len
All of the "missing" modules are reported, with RC=0.
The len = 28686 for the missing modules, while the reported modules seem
to have lengths of 4098, 8096, 16392, 28686.
I changed the code back to
ldate = substr(data,ec+13,3)
because the Julian date wanted yyddd format, but for some reason
your original code was
ldate = substr(data,ec+12,3)
So I have no idea why the offsets are different between our two
installations.
Since your code, with MAXLEN(2000) reported on 28686 modules I don't
know what's going on here. I have no experience with ISPEXEC calls.
My "missing" $AJ140 module has this string at approx. 3580 bytes into
the 2nd browse line of the module.
Ø.5695DF108 .....¤...|..×
80FFFFCCFFF4012029010400B
00569546108020038F140F00F
Does LMGET read only one record ???
Any suggestions ?
Regards
Lorne
_http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/ISPZSG70/2.33?SH
ELF=ISPZPM70&DT=20080610213539_
(http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/ISPZSG70/2.33?SHELF=ISPZPM70&DT=20080610213539)
So, LMGET MODE(MULTX) reads multiple records to create a "segment". In
MULTX mode, MAXLEN is the maximum number of bytes to be stored from each
record read, to make up the segment that will be stored in the data location
variable.
Rob
In a message dated 1/21/2011 10:38:50 A.M. US Mountain Standard Time,
I think I am going to give up on this method.
I previously reported that the identifier was on the 2nd line. WRONG.
Also, it's a PDSE, so maybe that accounts for the different offset for
the hexadecimal date.
I find the identifier 5695DF108 at approx. line 23 position 3580 of 4096
chunks in browse mode. That would make it about 22 x 4096 + 3580
= 93692 into the module, much to big for the
address ISPEXEC "LMGET DATAID("pds") MODE(MULTX) MAXLEN(31000)
(maximum allowed is 32K)
So looks like I would have to do multiple LMGETs for the entire load
module before I do the scan for the identifier.
Thanks for the interesting code anyway.
Regards
Lorne
On 1/21/2011 2:01 PM, Robert Zenuk wrote:
>
> From the ISPF Services manual:
>
> When MODE(MULTX) is used, the read operation occurs in segments (rather
> than in single records), with each segment comprising multiple records. Each
> record is prefixed by a 2-byte binary integer field containing its length.
> The maximum size of each segment returned is 32 000 bytes. LMGET returns
> data to the dataloc-var in this format:
>
> _http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/ISPZSG70/2.33?SH
> ELF=ISPZPM70&DT=20080610213539_
> (http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/ISPZSG70/2.33?SHELF=ISPZPM70&DT=20080610213539)
> So, LMGET MODE(MULTX) reads multiple records to create a "segment". In
> MULTX mode, MAXLEN is the maximum number of bytes to be stored from each
> record read, to make up the segment that will be stored in the data location
> variable.
----------------------------------------------------------------------
I altered the original REXX to get the link date from a particular module from a member list displayed in 3.4. If anyone wants...
Paulo Caze
-----Mensagem original-----
De: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] Em nome de Lorne Dudley
Enviada em: sexta-feira, 21 de janeiro de 2011 15:39
Para: TSO-...@vm.marist.edu
Assunto: Re: [TSO-REXX] Link Date in a PDS
Hi Rob !
Any suggestions ?
Regards
Lorne
"Esta mensagem e uma correspondência reservada e sua divulgação, distribuição, reprodução ou qualquer forma de utilização depende de autorização, sujeitando-se o responsável a medidas judiciais. O remetente utiliza o correio eletrônico no exercício do seu trabalho ou em razão dele, eximindo esta instituição de qualquer responsabilidade por utilização indevida. Se você a recebeu por engano, favor eliminá-la."
"This message is a reserved correspondence and its disclosure, distribution, reproduction or any other form of use shall depend upon proper authorization, and the recipient responsible for such disclosure, distribution, reproduction or use shall be subject to legal actions. The sender uses the electronic mail in the exercise of his/her work or by virtue thereof, and the institution accepts no liability for its undue use. If you have received this e-mail by mistake, please delete it."
Rob
In a message dated 1/21/2011 1:36:53 P.M. US Mountain Standard Time,
dud...@QUEENSU.CA writes:
Hi Rob !
I think I am going to give up on this method.
I previously reported that the identifier was on the 2nd line. WRONG.
Also, it's a PDSE, so maybe that accounts for the different offset for
the hexadecimal date.
I find the identifier 5695DF108 at approx. line 23 position 3580 of 4096
chunks in browse mode. That would make it about 22 x 4096 + 3580
= 93692 into the module, much to big for the
address ISPEXEC "LMGET DATAID("pds") MODE(MULTX) MAXLEN(31000)
(maximum allowed is 32K)
So looks like I would have to do multiple LMGETs for the entire load
module before I do the scan for the identifier.
Thanks for the interesting code anyway.
Regards
Lorne
On 1/21/2011 2:01 PM, Robert Zenuk wrote:
>
> From the ISPF Services manual:
>
> When MODE(MULTX) is used, the read operation occurs in segments (rather
> than in single records), with each segment comprising multiple records.
Each
> record is prefixed by a 2-byte binary integer field containing its
length.
> The maximum size of each segment returned is 32 000 bytes. LMGET returns
> data to the dataloc-var in this format:
>
>
_http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/ISPZSG70/2.33?SH
> ELF=ISPZPM70&DT=20080610213539_
>
(http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/ISPZSG70/2.33?SHELF=ISPZPM70&DT=20080610213539)
> So, LMGET MODE(MULTX) reads multiple records to create a "segment". In
> MULTX mode, MAXLEN is the maximum number of bytes to be stored from each
> record read, to make up the segment that will be stored in the data
location
> variable.
----------------------------------------------------------------------
I've been hacking away at the code that Charles gave you too.
(I just noticed that it was at the bottom of your original post.)
I just got the basic code working for PDSE a few minutes ago.
It's not pretty. I'm now going to copy my PDSE into a PDS and see if I
can get that portion of the code working too.
One problem I encountered. I detected the eye catcher at the end of the
4096 byte record, with the packed date appearing in the next LMGET.
I did a crude bit of flag logic to pick that up on the next read.
Regards
Lorne
so why not let the appropriate program extract the date for you - use
amblist and parse the result!
000001
/*********************************************************************/
000002 /* REXX
*/
000003
/*********************************************************************/
000004 /* Purpose: Print the Link Date from a LOADLIB
*/
000005
/*-------------------------------------------------------------------*/
000006 /* Syntax: LINKDATE dsn mempat
*/
000007
/*-------------------------------------------------------------------*/
000008 /* Parms: DSN - Required DSN
*/
000009 /* MEMPAT - Optional member wildcard pattern
*/
000010 /*
*/
000011 /* Notes: Supports both PDS and PDSE LOADLIB's.
*/
000012 /* Based on original work by Charles Williams and assistance
*/
000013 /* from Lorne Dudley
*/
000014 /*
*/
000015 /* Can be used online (command line, 3.4 or TSO option 6)
*/
000016 /* Can be used in batch with the following JCL example
*/
000017 /*
*/
000018 /* //LINKDATE EXEC PGM=IKJEFT01,
*/
000019 /* // PARM='ISPSTART CMD(%LINKDATE your.loadlib)'
*/
000020 /* //SYSEXEC DD DSN=your.EXEC,DISP=SHR
*/
000021 /* //ISPPLIB DD DSN=your.ISPPLIB,DISP=SHR
*/
000022 /* //ISPSLIB DD DSN=your.ISPSLIB,DISP=SHR
*/
000023 /* //ISPMLIB DD DSN=your.ISPMLIB,DISP=SHR
*/
000024 /* //ISPTLIB DD DDNAME=ISPTABL
*/
000025 /* // DD DSN=your.ISPTLIB,DISP=SHR
*/
000026 /* //ISPTABL DD LIKE=your.ISPTLIB,UNIT=VIO,DSORG=PO
*/
000027 /* //ISPPROF DD LIKE=your.ISPTLIB,UNIT=VIO,DSORG=PO
*/
000028 /* //ISPLOG DD SYSOUT=*,RECFM=VA,LRECL=125
*/
000029 /* //SYSTSPRT DD SYSOUT=*
*/
000030 /* //SYSTSIN DD DUMMY
*/
000031 /*
*/
000032 /*
*/
000033
/*********************************************************************/
000034 /* Change Log
*/
000035 /*
*/
000036 /* Author Date Reason
*/
000037 /* -------- ---------
----------------------------------------- */
000038 /* R. Zenuk Jan 2011 Initial Creation
*/
000039 /*
*/
000040
/*********************************************************************/
000041 /* Accept parms
*/
000042
/*********************************************************************/
000043 arg dsn pat
000044 if pat = '' then pat = '*'
000045
/*********************************************************************/
000046 /* Strip quotes from DSN is provided (also for ISPF 3.4)
*/
000047
/*********************************************************************/
000048 dsn = strip(dsn,"B","'")
000049
/*********************************************************************/
000050 /* Set counters and default eyecatcher location
*/
000051
/*********************************************************************/
000052 ec = 0
000053 count = 0
000054 loadcount = 0
000055
/*********************************************************************/
000056 /* Establish ISPF Error control
*/
000057
/*********************************************************************/
000058 call ispcmd "CONTROL ERRORS RETURN"
000059
/*********************************************************************/
000060 /* Get DSN info to determine dataset type and set the date offset
*/
000061
/*********************************************************************/
000062 call ispcmd "DSINFO DATASET('"dsn"')"
000063 select
000064
/*********************************************************************/
000065 /* Exit RC=10 if this is not a LOADLIB (RECFM=U)
*/
000066
/*********************************************************************/
000067 when zdsrf <> 'U' then exit 10
000068
/*********************************************************************/
000069 /* PDSE - Set MAXLEN=4096 for LMGET MULTX and Date OFFSET=13
*/
000070
/*********************************************************************/
000071 when zdsdsnt = 'LIBRARY' then
000072 do
000073 mlen = 4096
000074 offset = 13
000075 end
000076
/*********************************************************************/
000077 /* PDS - Set MAXLEN=2000 for LMGET MULTX and Date OFFSET=12
*/
000078
/*********************************************************************/
000079 when zdsdsnt = 'PDS' then
000080 do
000081 mlen = 2000
000082 offset = 12
000083 end
000084
/*********************************************************************/
000085 /* Exit RC=20 for all other dataset types
*/
000086
/*********************************************************************/
000087 otherwise exit 20
000088 end
000089
/*********************************************************************/
000090 /* LMINIT and LMOPEN the dataset
*/
000091
/*********************************************************************/
000092 call ispcmd "LMINIT DATAID(PDS) DATASET('"dsn"') ENQ(SHR)"
000093 call ispcmd "LMOPEN DATAID("pds")"
000094
/*********************************************************************/
000095 /* Loop through all the members
*/
000096
/*********************************************************************/
000097 do forever
000098 address ISPEXEC "LMMLIST DATAID("pds") OPTION(LIST) STATS(NO)",
000099 "MEMBER(MEM) PATTERN("pat")"
000100 if RC <> 0 then leave
000101
/*********************************************************************/
000102 /* LMFIND each member on behalf of the LMGET
*/
000103
/*********************************************************************/
000104 loadmem = mem
000105 call ispcmd "LMMFIND DATAID("pds") MEMBER("loadmem") STATS(NO)"
000106
/*********************************************************************/
000107 /* Process multiple records in a loop if needed
*/
000108
/*********************************************************************/
000109 do forever
000110
/*********************************************************************/
000111 /* LMGET using MULTX to grab multiple records with one request
*/
000112
/*********************************************************************/
000113 address ISPEXEC "LMGET DATAID("pds") MODE(MULTX)
MAXLEN("mlen")",
000114 "DATALOC(SEGDATA) DATALEN(LEN)"
000115 if RC > 8 then leave
000116
/*********************************************************************/
000117 /* Remove the length fields from the MULTX SEGDATA
*/
000118
/*********************************************************************/
000119 data = ''
000120 do while length(segdata) > 0
000121 data = data||substr(segdata,3,mlen)
000122 segdata = delstr(segdata,1,mlen+2)
000123 end
000124
/*********************************************************************/
000125 /* Look for known eyecatchers and save the position
*/
000126
/*********************************************************************/
000127 select
000128 when pos('5695PMB01',data) <> 0 then ec =
pos('5695PMB01',data)
000129 when pos('5695DF108',data) <> 0 then ec =
pos('5695DF108',data)
000130 when pos('566528408',data) <> 0 then ec =
pos('566528408',data)
000131 when pos('566529508',data) <> 0 then ec =
pos('566529508',data)
000132 when pos('5752SC104',data) <> 0 then ec =
pos('5752SC104',data)
000133 when pos('5741SC104',data) <> 0 then ec =
pos('5741SC104',data)
000134 otherwise iterate
000135 end
000136 leave
000137 end
000138
/*********************************************************************/
000139 /* If found, extract the date using the correct offset
*/
000140
/*********************************************************************/
000141 if ec > 0 then
000142 do
000143 ldate = substr(data,ec+offset,3)
000144 ldate = strip(c2x(ldate),'T','F')
000145 select
000146 /**************************************************************
*******/
000147 /* Process exceptions
*/
000148
/*********************************************************************/
000149 when ldate = '000000' then say left(loadmod,8) 'INVALID'
000150 when ldate = '404040' then say left(loadmod,8)
'????-??-??'
000151
/*********************************************************************/
000152 /* Process "normal" members
*/
000153
/*********************************************************************/
000154 otherwise
000155 do
000156 ldate = date('S',ldate,'J')
000157 ldate = translate('1234-56-78',ldate,'12345678')
000158 say left(loadmem,8) ldate
000159 end
000160 end
000161
/*********************************************************************/
000162 /* Maintain counters
*/
000163
/*********************************************************************/
000164 loadcount = loadcount + 1
000165 end
000166 count = count + 1
000167 end
000168
/*********************************************************************/
000169 /* Cleanup
*/
000170
/*********************************************************************/
000171 call ispcmd "LMMLIST DATAID("pds") OPTION(FREE)"
000172 call ispcmd "LMCLOSE DATAID("pds")"
000173 call ispcmd "LMFREE DATAID("pds")"
000174
/*********************************************************************/
000175 /* Stats
*/
000176
/*********************************************************************/
000177 say
000178 say loadcount 'load modules in' count 'members in' dsn zdsdsnt
000179 exit 0
000180
/*********************************************************************/
000181 /* Execute and error check ISPF commands
*/
000182
/*********************************************************************/
000183 ispcmd: arg ispcmd
000184 address ISPEXEC ispcmd
000185 ZISPFRC = RC
000186 if RC <> 0 then
000187 do
000188 say word(ispcmd,1) 'error RC='ZISPFRC zerrlm
000189 address ISPEXEC "VPUT (ZISPFRC)"
000190 exit zispfrc
000191 end
000192 else
000193 return
Rob
In a message dated 1/22/2011 9:52:41 P.M. US Mountain Standard Time,
dud...@QUEENSU.CA writes:
Hi Rob !
Here is a modification to your code.
I have some strange modules in my library that hung up the original
code. In one case it went into a permanent cpu loop on an invalid
module. In another case (PDSE) the record returned was truncated such
that the identifier matched, but the packed date field was off the end
of the LMGET data.
If you are interested I can provide a small transmit version of the
test library which exhibits the problems.
Regards
Lorne
----------------------------------------------------------------------------
/* rexx */
/* 2011-January-22, LAD. */
/* Original code from */
/* Charles Wiliams, Charles....@OA.MO.GOV */
/* Robert Zenuk , Robz...@AOL.COM */
arg dsn pat debug
if debug = 'DEBUG' then
debug = 1
else
debug = 0
if debug then say 'debug=' || debug
if pat = '' then pat = '*'
count = 0
loadcount = 0
ec = 0
call listdsi "'"dsn"'"
if sysdssms = 'PROGRAM_LIBRARY' then
do
offset = 13
dsorg = 'PDSE'
end
else
do
offset = 12
dsorg = 'PDS'
end
address ISPEXEC "LMINIT DATAID(PDS) DATASET('"dsn"') ENQ(SHR)"
address ISPEXEC "LMOPEN DATAID("pds")"
do forever
address ISPEXEC "LMMLIST DATAID("pds") OPTION(LIST) STATS(NO)",
"MEMBER(MEM) PATTERN("pat")"
if RC <> 0 then leave
loadmem = mem
address ISPEXEC "LMMFIND DATAID("pds") MEMBER("loadmem") STATS(NO) "
eof_flag = 0
do until (eof_flag >= 8)
/*do forever */
address ISPEXEC "LMGET DATAID("pds") MODE(MULTX) MAXLEN(31000)" ,
"DATALOC(DATA) DATALEN(LEN)"
eof_flag = RC
ec = 0 /* reset to prevent residue from previous LMGET */
select
when pos('5695PMB01',data) <> 0 then ec = pos('5695PMB01',data)
when pos('5695DF108',data) <> 0 then ec = pos('5695DF108',data)
when pos('566528408',data) <> 0 then ec = pos('566528408',data)
when pos('566529508',data) <> 0 then ec = pos('566529508',data)
when pos('5752SC104',data) <> 0 then ec = pos('5752SC104',data)
when pos('5741SC104',data) <> 0 then ec = pos('5741SC104',data)
otherwise iterate
end
leave
end /* of until (eof_flag >= 8) */
if ec > 0 then
do
if debug then say 'ec=' || ec || ' len=' || len || ' len-ec=' ||
len-ec|| ,
' offset=' || offset
ldate = substr(data,ec+offset,3)
ldate = strip(c2x(ldate),'T','F')
if debug then say 'ldate=' || ldate
if ldate = '000000' then
say left(loadmem,8) 'INVALID module'
else
if ldate = '404040' then
say left(loadmem,8) '????-??-?? record truncated'
else
do
ldate = translate('1234-56-78',date('S',ldate,'J'),'12345678')
say left(loadmem,8) ldate
end
loadcount = loadcount + 1
end
count = count + 1
end /* of do forever */
address ISPEXEC "LMMLIST DATAID("pds") OPTION(FREE)"
address ISPEXEC "LMCLOSE DATAID("pds")"
address ISPEXEC "LMFREE DATAID("pds")"
say loadcount 'load modules in' count 'members in' dsn ' (' dsorg ')'
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
-IPT- BROWSE GKFU.GEM.EXECLIB(AANM001) Line 00000000 Col 04081
Command ===> Scroll ===> CSR
----+----9----+----0----+----1----+----2----+----3----+----4----+----5----+----6
********************************* Top of Data **********************************
................
JìoØJì .Jìì0µ.ì.
DED FOR ADD.á0E©
©Q.m.Õ.`.ñì0å<}0
........C_WSA
................
................
....ERERL.......
............SDSD
0 .....!5695PMB0 the '1' is first in next line
...... .......Ø.
-----Ursprungligt meddelande-----
Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Robert Zenuk
Skickat: den 23 januari 2011 20:07
Till: TSO-...@VM.MARIST.EDU
Ämne: Re: [TSO-REXX] Link Date in a PDS
I think I found a bug: the "imbedded 2 byte length field" is apparently only
inserted when the dataset is a PDSE, not when it's a PDS.
I discovered that 2 bytes was missing every 2k in Your "segdata loop" below.
When I used the loop only for PDSE, not PDS, it worked ok.
A tip: I found that You can also search for x'1102', x'1115' and x'1182' as
the 2 byte prefix in front of the Eyecatcher. (It worked for me with x'11'
or x'15' as search argument (first byte).)
Here You have to (?) do a second check after You found the bytes above:
...
If Verify(Substr(data,ec,9), ,
'ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ0123456789') = 0
...
(This test if the EC is all uppercase alpha or numbers.)
You have to repeat this at least 2 times to be sure to get the EC.
(I got it always at the first or second try when tested.)
I do this if the known ECs is not found.
Found these EC here (in two big loadlibs):
Eye catcher count
--------- -----
360SED521 16
566528408 1391
566529508 1
5695DF108 9012
5695PMB01 14334
5741SC104 55
5742SC104 160
5752SC104 583
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Robert
> Zenuk
> Skickat: den 23 januari 2011 20:07
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] Link Date in a PDS
>
Attached are my mods to the original work done by Charles Williams and
Rob Zenuk.
This works on my largest library. Thomas, could you try on your large
library please.
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
----------------------------------------------------------------------
I had tried to communicate privately earlier and I have just
received this note today with a time stamp of 12:32am.
Recipient address: Robz...@AOL.COM
Reason: unable to deliver this message after 1 day
Regards
Lorne
Note that I haven't done any test on PDSEs as we don't have any
PDSE loadlibs (other than one or two with at most two members that
someone played with...).
�
Regards,
Thomas Berg
_________________________________________
Thomas Berg�� Specialist�� A M�� SWEDBANK
> -----Ursprungligt meddelande-----
> Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r Lorne
> Dudley
> Skickat: den 25 januari 2011 08:57
> Till: TSO-...@VM.MARIST.EDU
> �mne: Re: [TSO-REXX] Link Date in a PDS
-IPT- BROWSE GKFU.GEM.EXECLIB(AANM001) Line 00000000 Col 04081
Command ===> Scroll ===> CSR
----+----9----+----0----+----1----+----2----+----3----+----4----+----5----+----6
********************************* Top of Data **********************************
................
JìoØJì .Jìì0µ.ì.
DED FOR ADD.á0E©
©Q.m.Õ.`.ñì0å<}0
........C_WSA
................
................
....ERERL.......
............SDSD
0 .....!5695PMB0 the '1' is first in next line
...... .......Ø.
//Lasse
-----Ursprungligt meddelande-----
Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Thomas Berg
Skickat: den 25 januari 2011 11:50
Till: TSO-...@VM.MARIST.EDU
Ämne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
Did a test run. Worked flawlessly.
(As in my own version there were a handful of "modules" that was rather fishy in which it couldn't find any ec or date.)
Note that I haven't done any test on PDSEs as we don't have any PDSE loadlibs (other than one or two with at most two members that someone played with...).
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För
> Lorne Dudley
> Skickat: den 25 januari 2011 08:57
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] Link Date in a PDS
... (LMGET etc.)
doubledata = oldsegdata || segdata
oldsegdata = segdata
data = ''
do while length(doubledata) > 0
... etc.
... (iterate LMGET etc.)
�
Regards,
Thomas Berg
_________________________________________
Thomas Berg�� Specialist�� A M�� SWEDBANK
> -----Ursprungligt meddelande-----
> Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r H�glund
> Lars
> Skickat: den 25 januari 2011 13:48
> Till: TSO-...@VM.MARIST.EDU
> �mne: [TSO-REXX] SV: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
>
> We are using PDSe for everything, and as I stated before, the
> searchargument, like "5695PMB01" could be splitted into 2 lines in any
> form.
> Including hit on argument but data/time in the next row.
>
> -IPT- BROWSE GKFU.GEM.EXECLIB(AANM001) Line 00000000 Col
> 04081
> Command ===> Scroll ===>
> CSR
> ----+----9----+----0----+----1----+----2----+----3----+----4----+----5----
> +----6
> ********************************* Top of Data
> **********************************
> ................
> J�o�J�.J��0�.�.
> DED FOR ADD.�0E�
> �Q.m.�.`.��0�<}0
> ........C_WSA
> ................
> ................
> ....ERERL.......
> ............SDSD
> 0 .....!5695PMB0 the '1' is first in next line
> ...... .......�.
>
>
>
> //Lasse
>
>
> -----Ursprungligt meddelande-----
> Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r Thomas
> Berg
> Skickat: den 25 januari 2011 11:50
> Till: TSO-...@VM.MARIST.EDU
> �mne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
>
> Did a test run. Worked flawlessly.
> (As in my own version there were a handful of "modules" that was rather
> fishy in which it couldn't find any ec or date.)
>
> Note that I haven't done any test on PDSEs as we don't have any PDSE
> loadlibs (other than one or two with at most two members that someone
> played with...).
>
>
>
> Regards,
> Thomas Berg
> _________________________________________
> Thomas Berg�� Specialist�� A M�� SWEDBANK
>
>
>
> > -----Ursprungligt meddelande-----
> > Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r
> > Lorne Dudley
> > Skickat: den 25 januari 2011 08:57
> > Till: TSO-...@VM.MARIST.EDU
> > �mne: Re: [TSO-REXX] Link Date in a PDS
Thanks everyone, great collaborative development. It is nice when you can
get something tested in several shops and find all the things that may not
existing in your own shop.
Rob
In a message dated 1/25/2011 12:56:10 A.M. US Mountain Standard Time,
I missed your earlier comments on spanned eye-catchers.
Anything at our installation has complete eye-catchers.
Could you package up a small PDSE with about 5 members that exhibit the
problem at your installation ? Can you put it in TRANSMIT format and
place it at a FTP location that could be accessed ?
Thomas, I think the idea
... (LMGET etc.)
doubledata = oldsegdata || segdata
oldsegdata = segdata
will not work because it will exceed 32K.
I'm thinking something like
eye_catcher = substr(previous_data,length(previous_data) - 15,16) || ,
substr(current_data,1,16)
with suitable length and end-of-file logic checking might do the trick.
Does anyone have other ideas that would work ?
Why would that be a problem ?
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
----------------------------------------------------------------------
The following message to <karthick.i...@uk.ngrid.com> was
undeliverable.
The reason for the problem:
5.1.0 - Unknown address error 550-'5.7.1
<karthick.i...@uk.ngrid.com>... Delivery to recipient domain
@uk.ngrid.com from sender domain @QUEENSU.CA is not supported.'
I get this for every post I make to this list.
List owner --- if you see a lot of yes replies to this question could
you manually remove this person from the list ?
I was under the mistaken impression that variables were limited to 32K.
I now find this is not the case so I'll think about that variation.
Regards
Lorne
On 1/25/2011 12:25 PM, Thomas Berg wrote:
>> >
>> > Thomas, I think the idea
>> >
>> > ... (LMGET etc.)
>> > doubledata = oldsegdata || segdata
>> > oldsegdata = segdata
>> >
>> > will not work because it will exceed 32K.
>
> Why would that be a problem ?
----------------------------------------------------------------------
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Lorne
> Dudley
> Skickat: den 25 januari 2011 19:14
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
Rob
In a message dated 1/25/2011 10:16:14 A.M. US Mountain Standard Time,
dud...@QUEENSU.CA writes:
Hi Lars !
I missed your earlier comments on spanned eye-catchers.
Anything at our installation has complete eye-catchers.
Could you package up a small PDSE with about 5 members that exhibit the
problem at your installation ? Can you put it in TRANSMIT format and
place it at a FTP location that could be accessed ?
Thomas, I think the idea
... (LMGET etc.)
doubledata = oldsegdata || segdata
oldsegdata = segdata
will not work because it will exceed 32K.
I'm thinking something like
eye_catcher = substr(previous_data,length(previous_data) - 15,16) || ,
substr(current_data,1,16)
with suitable length and end-of-file logic checking might do the trick.
Does anyone have other ideas that would work ?
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
----------------------------------------------------------------------
> Does anyone have other ideas that would work ?
I realize you are asking about a specific and detailed problem here,
but speaking much more generally, I think this whole approach is wrong
for a number of reasons. The most significant is that the format of a
Program Object is not documented, not a Programming Interface, and can
change (and has done so) from one release to the next. IBM provides an
interface for retrieving information from Program Objects, and that
same interface will handle load modules in PDSs, Program Objects in
PDSEs or UNIX files, and even object modules in any of their supported
formats (traditional or GOFF). This is the Binder API IEWBIND (and its
"fast" version IEWBFDAT, and the C-friendly version iewbndd.so).
It is also the case that a number of programs that exploit the Binder
API are already available, some of them in source format, and it makes
sense to me to start with one of those, either as a model or as a
program to invoke..
If you have the CICS Interdependency Analyzer, the CSECT Scanner tool
from that product appears to produce a nice report on load modules,
including bind timestamps and CSECT language and timestamps.
Other commercial tools are GSF's PDS and load module related utilities
LINKMAP, LOADXREF, SCANPDS, etc. And there is lots of related free
stuff in CBT file 183 from GSF as well.
I understand well that installing 3rd party software, priced or not,
may not be acceptable. In that case I recommend calling the Binder
API(s), either directly from REXX, or for better performance, from
assembler or C.
Tony H.
I get them, so I imagine we all do. The message is misleading; I
didn't complain on the list because I imagined I was being rejected by
uk.ngrid.com because I send mail from the "wrong" SMPT server. Unless
you also do that, I say kick em off...
Tony H.
Thanks for the API idea.
Do you have any references that would give REXX model code showing
calls to the Binder API ? How about some IBM document references.
Does anyone else see
>> The following message to<karthick.i...@uk.ngrid.com> was
>> undeliverable.
>> The reason for the problem:
>> 5.1.0 - Unknown address error 550-'5.7.1
>> <karthick.i...@uk.ngrid.com>... Delivery to recipient domain
>> @uk.ngrid.com from sender domain @QUEENSU.CA is not supported.'
If so, please speak up so the list owner can take action.
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
> Is anyone else seeing this ?
>
> The following message to <karthick.i...@uk.ngrid.com> was
> undeliverable.
> The reason for the problem:
> 5.1.0 - Unknown address error 550-'5.7.1
> <karthick.i...@uk.ngrid.com>... Delivery to recipient domain
> @uk.ngrid.com from sender domain @QUEENSU.CA is not supported.'
>
> I get this for every post I make to this list.
Likewise.
--
Jeremy C B Nicoll - my opinions are my own.
Can you supply an example of this ?
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
> On 02/05/10 13:44, Tony Harminc wrote:
>>
>> Late reply, but just for the record, it is possible to invoke IEWBIND
>> directly from REXX using LINKPGM. It's certainly not designed to work
>> this way, and there are some calls that can't be done because of the
>> required data structures, but as far as I know you can do all the data
>> retrieval stuff this way.
--
Thanks
Arlen Stovall
IBM doesn't document calling the API from REXX, and I'm sure it's not
formally supported. I mentioned it to one of the Binder developers at a
conference a few years ago, and he was amazed that I got it to work at all.
And indeed it works only because *some* of the API calling argument lists
can be constructed in REXX - generally those that retrieve information only,
and I'm not quite sure if even all of those can be done. And there is every
reason to think that performance will not be good for more than trivial
work. Since the OP was looking for something to outperform AMBLIST, I don't
think this is a candidate. Really it's more a curiosity than something for
serious use, but it can be handy to whip up little tools from time to time.
Probably a better approach would be to provide a REXX function package or
the like to actually talk to IEWBIND. Maybe someone has done so.
What you have to do is make up the arguments to IEWBIND the way the IEWBIND
and IEWBUFF macros would, and then issue a REXX LINKPGM for each call. The
format of these arguments is documented in the MVS Program Management:
Advanced Facilities book, and there is a section 3.1.4 Invoking the binder
without the macros, which says "If you want to invoke the binder without
using the macros (for example, from nonassembler language programs), provide
the services and generate the code equivalent to that provided by the
macros." So it does seem that the documented argument lists are supported
even without the mapping and functional macros. For all this you do have to
be comfortable working with binary data in REXX. It's not hard, but it takes
a little discipline to avoid trouble. Everything you need is documented in
the Advanced Facilities book, and/or in the macros IEWBIND and IEWBUFF.
The sequence of calls to retrieve information is generally:
- STARTD start a Binder dialogue
- For each member:
- CREATEW Create a workmod
- INCLUDE include the module data (using DDNAME + MEMBERNAME or
DDNAME pointing to a UNIX path)
- Possibly BINDW to bind the workmod and resolve symbols
- GETD Get Data from one or more classes, according to what you want.
This can include the object text itself (which you can then process in
REXX), IDR_B for binder info, IDR_L for language translator
(compiler) info,
IDR_Z for AMASPZAP info, etc. etc.
- DELETEW delete the workmod (unless you want to change it!)
- ENDD end the Binder dialogue.
I can't post the entire ready-to-go thing, but this should give the idea. I
have a procedure to do the actual invocations of IEWBIND something like
this:
iewbind: Procedure Expose dtoken wtoken member. loadlib
function = Arg(1)
module = Arg(2)
/* basic constants */
h0 = d2c(0,2) /* H'0' */
f0 = d2c(0,4) /* F'0' */
fd0 = d2c(0,8) /* FD'0' */
fm1 = d2c(-1,4) /* F'-1' */
Select
When function = "STARTD" then Do
funcver = '00010004'x
retcode = f0
rsncode = f0
dtoken = fd0
filelist = f0
exitlist = f0
optlist = f0
If loadlib then
parms = h0
else
parms = d2c(6,2) || "LET=12" /* allow incomplete modules if objlib etc.
*/
Address LINKPGM "IEWBIND" ,
"funcver retcode rsncode dtoken" ,
"filelist exitlist optlist parms"
If RC <> 0 then Call dorc "STARTD"
End
with a separate WHEN for each function.
For those functions that take a buffer, such as GETD, I call a routine
iewbuff from within my iewbind to initialize the buffer:
When function = "B_IDRB" then Do
iewbidb = iewbuff('IDB',10, 1) /* Initialize a 10 entry buffer */
retcode = f0
rsncode = f0
funcver = '003D0001'x
class = d2c(6,2) || "B_IDRB"
section = h0
cursorm = f0
countm = f0
Address LINKPGM "IEWBIND" ,
"funcver retcode rsncode wtoken" ,
"class section iewbidb cursorm countm"
If RC > 4 then Call dorc "GETN B_BIDB"
call process_bidb iewbidb, c2d(countm,4)
End
where iewbuff looks like:
iewbuff: Procedure
Arg type, entries, version
/* Say "Creating buffer for type
If version = '' then
version = 3
If version = 1 then
lstlen = 512
else
lstlen = 1024
hdrlen = 32 /* standard header */
Select
When type = "IDL" | type = "IDRL" then
Do
name = "IEWB" || "IDL"
entrylen = 36
end /* When type = "IDL" */
When type = "IDB" | type = "IDRB" then
Do
name = "IEWB" || "IDB"
entrylen = 116
end /* When type = "IDB" */
End
etc...
and ends with:
buflen = hdrlen + lstlen + (entrylen * entries)
buffer = Left(name,8) || , /* Eyecatcher */
d2c(buflen,4) || , /* F'length' */
d2c(version,1) || , /* AL1(version) */
d2c(0,3) || , /* Reserved */
d2c(entrylen,4) || , /* Entry length */
d2c(entries,4) || , /* Entry count */
d2c(0,4) || , /* Name offset */
d2c(0,4) /* Names pointer */
Return Left(buffer, buflen) /* return padded with blanks */
and for each such IEWBIND call that returns data there is a processing
routine process_xxx that parses the returned entries and formats them, e.g.
for the Binder ID record:
process_bidb: Procedure
buffer = Arg(1)
ent_count = Arg(2)
Parse Var buffer 1 id 9 bufleng 13 version 14 . 17 entleng 21 ,
count 25 . 33 rest
bufleng = c2d(bufleng,4)
entleng = c2d(entleng,4)
count = c2d(count,4)
Do i = 1 to ent_count /* probably can have only one... */
Parse Var rest 1 b_id 11 b_version 13 b_release 15 b_cc 17 b_yyddd ,
22 b_time 28 . 29 mod_size 33 callerid_chars ,
35 callerid 115 . 117 rest
Say "BindDate: " translate('1234-56-78',date('S',b_yyddd,'J'),'12345678')
Say "BindTime: " translate('12:34:56' ,b_time, '123456')
Say "BinderID: " b_id "Ver" b_version "Rel" b_release
end
Return /* process_bidb */
Then the overall run goes like this (assuming I have the member list in
member.):
Call IEWBIND "STARTD"
Say member.0 "members in" dsname
Do i = 1 to member.0
Say "For module:" member.i
Call IEWBIND "CREATEW"
Call IEWBIND "INCLUDE", member.
Call IEWBIND "B_IDRB", member.i
Call IEWBIND "B_IDRL", member.i
Call IEWBIND "B_PMAR", member.i
Call IEWBIND "B_MAP", member.i
Call IEWBIND "DELETEW"
end /* member.0 */
Call IEWBIND "ENDD"
Well I hope this provides some seeds for someone...
Thank you Tony ! I'll see how far I can go with this.
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
On 1/25/2011 8:32 PM, Tony Harminc wrote:
The sequence of calls to retrieve information is generally:
>
>
> - STARTD start a Binder dialogue
> - For each member:
> - CREATEW Create a workmod
> - INCLUDE include the module data (using DDNAME + MEMBERNAME or
> DDNAME pointing to a UNIX path)
> - Possibly BINDW to bind the workmod and resolve symbols
> - GETD Get Data from one or more classes, according to what you want.
> This can include the object text itself (which you can then process in
> REXX), IDR_B for binder info, IDR_L for language translator
> (compiler) info,
> IDR_Z for AMASPZAP info, etc. etc.
> - DELETEW delete the workmod (unless you want to change it!)
> - ENDD end the Binder dialogue.
>
snip
> ... And there is every
> reason to think that performance will not be good for more than trivial
>
A painful deficiency is that each address LINKPGM will LOAD and DELETE
the called module. It would be a valuable performance enhancement if
Rexx (or a function package) provided interfaces to LOAD and DELETE.
Is such available from, e.g. CBTTAPE.org?
-- gil
> A frequent obstacle is that Rexx is pointer-ignorant: APIs which
> require control blocks containing pointers, such as SMP/E are
> incurably Rexx-hostile; APIs which are pointer-free, such as
> ICSF are more likely to be Rexx-friendly, but considerable data
> format connversion (d2c, c2d, etc.) may be required.
Exactly. (Though one can just as well argue that it's REXX that is
API-hostile...) The Binder API has a number of calls that cannot be
done for this reason, but most of the information retrieval ones have
only one level of pointer, and that is effectively handled by LINKPGM.
I don't find the data conversions raise much trouble; as I said, you
have to be comfortable with the concepts of representing and
manipulating binary data in REXX, and exercise vigilance so that
REXX's oh-so-friendly attitude doesn't bite you (e.g. the notorious
string comparison "00E0" > "0000" is false). The trick is to have
tiny routines to make the conversions, and where slightly higher
performance is needed, to precode what you can as hex constants.
> A painful deficiency is that each address LINKPGM will LOAD and DELETE the called module.
In the case of IEWBIND I think it's not actually as bad as one might
expect, because the module is in LPA, and the LINK won't be doing I/O
and BLDL and all that. And by happy accident the Binder dialogue uses
tokens to maintain context, so there is no worry about things
disappearing after the LINK; in other words there is nothing magic
that a LOAD/process/DELETE sequence would do that multiple LINKs
can't.
> It would be a valuable performance enhancement if
> Rexx (or a function package) provided interfaces to LOAD and DELETE.
> Is such available from, e.g. CBTTAPE.org?
I haven't seen such a thing. To be of any use it would require a
REXX-suitable mechanism to CALL an address in a REXX variable, and
that would also allow CALLs to addresses resolved from various places
other than LOAD, e.g. those many services addressible from the CVT.
Tony H.
I was wrong below (and Robert in his code at bottom and
probably others). The following is my conclusions:
1. MAXLEN as in "MAXLEN()" is only for limiting the data in the
"records". For PDS it will be the shorter value of MAXLEN vs
the actual length of the "record". For PDSE it will be the shorter
value of MAXLEN vs 4096.
2. The Length field for the "records" is always there, both for PDS
and PDSE. The lengths of the "records" for PDS varied from e g 22
(the EC-record) to MAXLEN. The lengths of the "records" for PDSE
varied from MAXLEN (if it was lower than 4096) to 4096.
3. Our errors was in the "segdata loop". We used erroneously the MAXLEN!
This one works although, of course You should use the "record" len:
data = ''
do while length(segdata) > 0
LEN = C2x(substr(segdata,1,2))
data = data||substr(segdata,3,LEN)
segdata = delstr(segdata,1,LEN+2)
end
4. A question is what we should use for MAXLEN for PDS.
As the rest of the "records" (beyond MAXLEN) is skipped we need to know
a minimum length. So far I haven't seen an "EC-record" with other length
than 22...
(For PDSE is 4096 probably needed.)
5. I haven't found any logical connection to the amount of data LMGET
reads each time. With e g MAXLEN set to 31000 and the blksize is 23200
it varied between 961 and 31636. (?)
6. In PDSE the 2 byte "prefix" in front of the EC varied as:
D5E3 (= "IN" as in "IDENT"...)
0000
0028
07FF
087F
095F
138F
1560
167F
206F
233F
288F
Nothing to rely on...
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r Thomas
> Berg
> Skickat: den 24 januari 2011 18:47
> Till: TSO-...@VM.MARIST.EDU
> �mne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
>
> Hi,
>
> I think I found a bug: the "imbedded 2 byte length field" is apparently
> only
> inserted when the dataset is a PDSE, not when it's a PDS.
> I discovered that 2 bytes was missing every 2k in Your "segdata loop"
> below.
> When I used the loop only for PDSE, not PDS, it worked ok.
>
>
> A tip: I found that You can also search for x'1102', x'1115' and x'1182'
> as
> the 2 byte prefix in front of the Eyecatcher. (It worked for me with
> x'11'
> or x'15' as search argument (first byte).)
> Here You have to (?) do a second check after You found the bytes above:
> ...
> If Verify(Substr(data,ec,9), ,
> 'ABCDEFGHIJKLMNOPQRSTUVWXYZ���0123456789') = 0
> ...
> (This test if the EC is all uppercase alpha or numbers.)
>
> You have to repeat this at least 2 times to be sure to get the EC.
> (I got it always at the first or second try when tested.)
> I do this if the known ECs is not found.
>
> Found these EC here (in two big loadlibs):
>
> Eye catcher count
> --------- -----
> 360SED521 16
> 566528408 1391
> 566529508 1
> 5695DF108 9012
> 5695PMB01 14334
> 5741SC104 55
> 5742SC104 160
> 5752SC104 583
>
>
>
> Regards,
> Thomas Berg
> _________________________________________
> Thomas Berg Specialist A M SWEDBANK
>
>
> > -----Ursprungligt meddelande-----
> > Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r
> Robert
> > Zenuk
> > Skickat: den 23 januari 2011 20:07
> > Till: TSO-...@VM.MARIST.EDU
> > �mne: Re: [TSO-REXX] Link Date in a PDS
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Thomas
> Berg
> Skickat: den 26 januari 2011 19:48
> Till: TSO-...@VM.MARIST.EDU
> Ämne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
>
> Hi,
>
> I was wrong below (and Robert in his code at bottom and
> probably others). The following is my conclusions:
>
> 1. MAXLEN as in "MAXLEN()" is only for limiting the data in the
> "records". For PDS it will be the shorter value of MAXLEN vs
> the actual length of the "record". For PDSE it will be the shorter
> value of MAXLEN vs 4096.
>
> 2. The Length field for the "records" is always there, both for PDS
> and PDSE. The lengths of the "records" for PDS varied from e g 22
> (the EC-record) to MAXLEN. The lengths of the "records" for PDSE
> varied from MAXLEN (if it was lower than 4096) to 4096.
>
> 3. Our errors was in the "segdata loop". We used erroneously the MAXLEN!
> This one works although, of course You should use the "record" len:
>
> data = ''
>
> do while length(segdata) > 0
> LEN = C2x(substr(segdata,1,2))
> data = data||substr(segdata,3,LEN)
> segdata = delstr(segdata,1,LEN+2)
> end
>
----------------------------------------------------------------------
Read 1:st row
Place in chkdata
Read 2:nd row
Concatenate with chkdata
do until eof or error
Check chkdata for eye-catcher
If found
Check length from eye-catcher to the end
If > 19
Fetch date and time
leave
Else
/* ec found but not enough chars for date/time */
Read one more row
Concatenate with chkdata
else
delete string 1 to length(row) from chkdata
Read one more row
Concatenate with chkdata
end
//Lasse
-----Ursprungligt meddelande-----
Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r Thomas Berg
Skickat: den 27 januari 2011 11:59
Till: TSO-...@VM.MARIST.EDU
�mne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS - bug in my code example
It's a bug in my code example below (no 3.): it should be "C2d(" - not "C2x(".
�
Regards,
Thomas Berg
_________________________________________
Thomas Berg�� Specialist�� A M�� SWEDBANK
> -----Ursprungligt meddelande-----
> Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r
> Thomas Berg
> Skickat: den 26 januari 2011 19:48
> Till: TSO-...@VM.MARIST.EDU
> �mne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
I've also pondered the possibility of a concurrent ATTACH
interface. This would depend on Rexx's storage management's
not relocating objects for defragmentation. I don't know
that this is guaranteed.
-- gil
I'm still getting
The following message to <karthick.i...@uk.ngrid.com> was
undeliverable.
The reason for the problem:
5.1.0 - Unknown address error 550-'5.7.1
<karthick.i...@uk.ngrid.com>... Delivery to recipient domain
@uk.ngrid.com from sender domain @QUEENSU.CA is not supported.'
----------------------------------------------------------------------
5467 members in PDSe
(Fyi CPU 1.27 elapsed 4.3)
//Lasse
-----Ursprungligt meddelande-----
Fr�n: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] F�r Lorne Dudley
Skickat: den 28 januari 2011 07:05
Till: TSO-...@VM.MARIST.EDU
�mne: Re: [TSO-REXX] Link Date in a PDS(E)
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Lorne
> Dudley
> Skickat: den 28 januari 2011 07:11
> Till: TSO-...@VM.MARIST.EDU
> Ämne: [TSO-REXX] attention list owner --- bounced mail
... /* GET_DATA(): */
Do While dataloc /== ''
len = C2d(Substr(dataloc,1,2))
data = data !! Substr(dataloc,3,len)
dataloc = Substr(dataloc,2 + len)
End
...
newdata = GET_DATA()
data = olddata !! newdata
olddata = newdata
ep = 0
es = 0
searchdata = Substr(data,1,Length(data) - 30)
Do i = 1 To ec.0 While ep = 0
ep = Pos(ec.i,searchdata)
End
i = i - 1
If ep <> 0 Then et = ec.i
...
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Höglund
> Lars
> Skickat: den 27 januari 2011 16:08
> Till: TSO-...@VM.MARIST.EDU
> Ämne: [TSO-REXX] SV: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS - bug in
> my code example
>
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Thomas
> Berg
> Skickat: den 27 januari 2011 11:59
> Till: TSO-...@VM.MARIST.EDU
> Ämne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS - bug in my code
> example
>
> It's a bug in my code example below (no 3.): it should be "C2d(" - not
> "C2x(".
>
>
>
> Regards,
> Thomas Berg
> _________________________________________
> Thomas Berg Specialist A M SWEDBANK
>
>
>
> > -----Ursprungligt meddelande-----
> > Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För
> > Thomas Berg
> > Skickat: den 26 januari 2011 19:48
> > Till: TSO-...@VM.MARIST.EDU
> > Ämne: [TSO-REXX] SV: [TSO-REXX] Link Date in a PDS
<quote>
I was wrong below (and Robert in his code at bottom and probably others). The following is my conclusions:
1. MAXLEN as in "MAXLEN()" is only for limiting the data in the "records". For PDS it will be the shorter value of MAXLEN vs the actual length of the "record". For PDSE it will be the shorter value of MAXLEN vs 4096.
2. *===> The Length field for the "records" is *always* there, *both for PDS and PDSE*. The lengths of the "records" for PDS varied from e g 22 (the EC-record) to MAXLEN. The lengths of the "records" for PDSE varied from MAXLEN (if it was lower than 4096) to 4096.
3. Our errors was in the "segdata loop". We used erroneously the MAXLEN!
This one works although, of course You should use the "record" len:
data = ''
do while length(segdata) > 0
LEN = C2d(substr(segdata,1,2))
data = data||substr(segdata,3,LEN)
segdata = delstr(segdata,1,LEN+2)
end
4. A question is what we should use for MAXLEN for PDS.
As the rest of the "records" (beyond MAXLEN) is skipped we need to know a minimum length. So far I haven't seen an "EC-record" with other length than 22...
(For PDSE is 4096 probably needed.)
5. I haven't found any logical connection to the amount of data LMGET reads each time. With e g MAXLEN set to 31000 and the blksize is 23200 it varied between 961 and 31636. (?)
6. In PDSE the 2 byte "prefix" in front of the EC varied as:
D5E3 (= "IN" as in "IDENT"...)
0000
0028
07FF
087F
095F
138F
1560
167F
206F
233F
288F
Nothing to rely on...
</quote>
Hälsn Thomas
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Lorne
> Dudley
> Skickat: den 28 januari 2011 07:05
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] Link Date in a PDS(E)
360SED521
566528408
566529508
566895801
5695DF108
5695PMB01
569623400
5741SC104
5742SC104
5752SC104
Have You found any more ?
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
----------------------------------------------------------------------
Thanks, good link!
Regards,
Thomas Berg
_________________________________________
Thomas Berg Specialist A M SWEDBANK
> -----Ursprungligt meddelande-----
> Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Lee,
> Bill
> Skickat: den 28 januari 2011 14:42
> Till: TSO-...@VM.MARIST.EDU
> Ämne: Re: [TSO-REXX] Link Date in a PDS(E)
>
> Here is a list from Gilbert Saint-Flour
>
> http://gsf-soft.com/Documents/PRODCODES.shtml
>
> It would be great if this utility also listed the compiler along with the
> date.
> --------------------------------------------------
> This e-mail transmission contains information intended only for the use
of
> the
> recipient(s) named above. Further, it contains information that may be
> privileged
> and confidential. If you are not the intended recipient, you are hereby
> notified
> that any dissemination, distribution, or copying of this message
> (including any
> attachments) is strictly prohibited. If you have received this e-mail in
> error,
> please notify the sender by reply e-mail and then delete this message
from
> your mail
> system. Thank you for your compliance.
My original post on this topic was just for basic PDS's because I was doing
some work in a shop that did not have PDS or Startool and I needed to do
something based on LINKDATE for a basic PDS. The original code posted
worked just fine on basic PDS's in my shop and the other shop.
Now back to my shop and PDSE's. In my world this PDSE performance under
the PDS tool or Startool is unacceptable and keeps us from migrating to
PDSE's. We need to migrate to PDSE's to avoid the enqueue issues from PDS
compression jobs on the heavily used (and updated) 24x7 application loadlibs.
Currently these compresses are performed during a planned weekly Dark
Window. We are trying to eliminate the Dark Window and compresses are one of
the reasons we still have a planned Dark Window.
Ideally, IBM would provide the linkdate as a STATS(YES) option on LMMLIST
and LMMFIND... Cross posting to ISPF-L so the IBM'ers see this. I'll be
looking for you guys at Share to talk about this one.
Thanks,
Rob
In a message dated 1/29/2011 7:05:14 A.M. US Mountain Standard Time,
don.im...@GMAIL.COM writes:
Those variables have values only for fixed-length or variable-length data
sets; they are not returned for load libraries.
- Don Imbriale
On Sat, Jan 29, 2011 at 2:05 AM, Lorne Dudley <dud...@queensu.ca> wrote:
>
> There are examples that show variables
> ZLC4DATE ZLM4DATE ZLMTIME ZLMSEC ZLVERS ZLMOD ZLUSER
> but I have so far been unsuccessful in getting these examples to produce
> values in the above variables.
Thanks for the background on the whole PDS link date "project".
So ..., I understand that fast performance is your objective.
In my investigation into this area (never been there before as opposed
to the many experienced users on this list) I see that normal PDS
libraries have a unique identifier at the front of a 22 byte record when
accessed in raw mode as opposed to MULTX ???
Would it be worth using an entirely separate processing method for the
legacy PDS ? You would not even have to know the detail of the
eye-catcher in this case ???
Attached is the PDS logic stream. How does it perform on your large PDS
loadlib ?
Your thoughts ?
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
> Would it be worth using an entirely separate processing method for the
> legacy PDS ? �You would not even have to know the detail of the
> eye-catcher in this case ???
This is about what IBM recommends, actually! There is another Binder
API, the Fast Data Access one, and it supports only Program Objects
(whether in PDSes or UNIX files), and not load modules. They explain
their thinking by saying that the load module format is both
completely documented and not going to change, and they claim a high
performance API could not compete with an application that reads PDS
data directly.
Now whether the Fast API (which actually has two quite different
interfaces) is one that can be called directly from REXX is a good
question, and I plan to look into this. My quick first impression is
that it probably can, but le bon Dieu, if not perhaps the devil, est
dans le d�tail...
Tony H.
I tried your new technique on our big PDS. It seemed to have a problem
with all the older modules (everything prior to 1999). It looks like the
first 2 bytes of the IDR record changed somewhere around 1998. All those IDR
records have x'8011' as the 2 byte record indicator value. Checking for
both values worked for all our application modules going back to 1983 and a
system LINKLIB that has some really old modules going back to 1976.
Apparently, the IDR record expanded around 1998 from 18 bytes to 22 bytes to
include the time.
Here is a new version of the REXX EXEC that incorporates both techniques;
your IDR technique for PDS's and the eyecatcher technique for PDSE's.
Thanks Lorne. I also put the eyecatchers in a variable rather than a big
SELECT statement so the list could be maintained easier (just add new values to
the end of the list). I also keep stats by eyecatcher when that technique
is used. The removal of the lengths using the 2 byte length value fixed
most of the weird problems. Thanks Thomas. I reworked the LMGET fallout
logic to avoid looping, it will always stop when reaching the end of the
module now (whether the eyecatcher was found or not).
Hopefully this version fixes all the outstanding problems, but let me know
if you still see problems. Thanks everyone for the assistance.
Rob
In a message dated 1/29/2011 1:45:12 P.M. US Mountain Standard Time,
dud...@QUEENSU.CA writes:
Hi Rob !
Thanks for the background on the whole PDS link date "project".
So ..., I understand that fast performance is your objective.
In my investigation into this area (never been there before as opposed
to the many experienced users on this list) I see that normal PDS
libraries have a unique identifier at the front of a 22 byte record when
accessed in raw mode as opposed to MULTX ???
Would it be worth using an entirely separate processing method for the
legacy PDS ? You would not even have to know the detail of the
eye-catcher in this case ???
Attached is the PDS logic stream. How does it perform on your large PDS
loadlib ?
Your thoughts ?
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
Canada
----------------------------------------------------------------------
Rob
In a message dated 1/29/2011 9:47:33 P.M. US Mountain Standard Time,
dud...@queensu.ca writes:
Hi Rob !
Thanks for the latest code.
There is a small problem with my INVALID module.
I'll take a look at this tomorrow as it's near midnight here.
JES2SPL2 1993-06-21 00:00:00
LEGEACFE 2007-03-01 18:24:53
LOADMOD INVALID
219 +++ ldate = date('S',ldate,'J')
IRX0040I Error running LINKDATE, line 219: Incorrect call to routine
Regards
Lorne
The latest code works OK with my largest PDSE.
Thanks for the update.
Regards
Lorne Dudley
Queen's University
Kingston, Ontario
On 1/30/2011 12:57 PM, Robert Zenuk wrote:
> Here is an updated version that fixes the INVALID PDSE module code (I
> removed a valid eyecatcher to confirm).
>
> Rob
----------------------------------------------------------------------
STATS(YES|NO)
Whether statistics for the member are to be returned to the dialog invoking the service. If you specify NO, no statistics are returned. If you specify YES and the data ID represents a data set that has unformatted records (RECFM=U), the statistics are returned in these dialog variables:
ZLAC
A 2-character field containing the authorization code of the member.
ZLALIAS
An 8-character field containing the name of the real member that this member is an alias of. If the member is not an alias this field is blank.
ZLAMODE
A 3-character field containing the AMODE of the member.
ZLATTR
A 20-character field containing the load module attributes. The attributes are 2-character strings separated by blanks. These strings can appear in the attribute string:
NX
Not executable
OL
Only Loadable
OV
Overlay
RF
Refreshable
RN
Reentrant
RU
Reusable
SC
Scatter Load
TS
Test
ZLLIB
Position in concatenated data set sequence; a number from 1 to 16.
ZLRMODE
A 3-character field containing the RMODE of the member.
ZLSIZE
An 8-character field containing the load module size in hex.
ZLTTR
A 6-character field containing the TTR of the member.
ZLSSI
An 8-character field containing the SSI information for a load module.
�
Regards,
Thomas Berg
_________________________________________
Thomas Berg�� Specialist�� A M�� SWEDBANK
----------------------------------------------------------------------
Rob
In a message dated 1/31/2011 5:22:53 P.M. US Mountain Standard Time,
Peter....@BROADRIDGE.COM writes:
Rob,
Attached is a slight correction to the PDSE counting-by-eyecatcher code.
When the eyecatcher is found but there isn't enough string left to extract
the date and time, you need to decrement eccnt.w before you iterate or you
are counting that eyecatcher twice.
HTH
Peter
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On Behalf
> Of Robert Zenuk
> Sent: Sunday, January 30, 2011 12:57 PM
> To: TSO-...@vm.marist.edu
> Subject: Re: Link Date in a PDS(E)
>
> Here is an updated version that fixes the INVALID PDSE module code (I
> removed a valid eyecatcher to confirm).
>
> Rob
--
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.
We have several loadmodules that are in the size of the one below
NAME RENAME LIB SIZE TTR ALIAS-OF AC RENT REFR REUS TEST AM RM
EAGM378 -BROWSED 1 003360A8 001928 00 YES YES 31 ANY
Examine this module will result in
IRX0005I Error running REXXAMB8, line 174: Machine storage exhausted.
After this "time"
TOTAL CPU TIME= 2.29 TOTAL ELAPSED TIME= 21.9
(No, I have no region in the job)
The variable DATA will at the end consist of almost the whole program because the EC, as You can see, is located near the end.
-IPT- BROWSE GKFU.GEM.EXECLIB(EAGM378) Line 00000855 Col 03631
Command ===> Scroll ===> CSR
.Ü....................Ø..°Ø..ðØ..ð........................Ø..°Ø..ðØ..ð..........
.þ...ê........................5695PMB01 .....^.Â.^..^Ã.&BATCH EMULATOR JOB(S867
À..CEEARLUH..CEEARLUÀ..CEEBPIRAH..CEEINTÀ..CEETLOCH..CEETLOCÀ..CEETGTFNH..CEETGT
.µL......{.......................äL......+........................L......!......
................................................................................
******************************** Bottom of Data ********************************
I think that we have to get rid of data in variable DATA that are already checked (for EC)
I'm counting records read per module (stopped after 698 records)
175 *-* say 'Length='length(data) 'read='read_count
>>> "Length=2859008 read=698"
Length=2859008 read=698
//Lasse
P.s
Scanning this module took much power
TOTAL CPU TIME= 2.29 TOTAL ELAPSED TIME= 21.9
-----Ursprungligt meddelande-----
Från: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] För Farley, Peter x23353
Skickat: den 1 februari 2011 01:23
Till: TSO-...@VM.MARIST.EDU
Ämne: Re: [TSO-REXX] Link Date in a PDS(E)
Rob,
Attached is a slight correction to the PDSE counting-by-eyecatcher code. When the eyecatcher is found but there isn't enough string left to extract the date and time, you need to decrement eccnt.w before you iterate or you are counting that eyecatcher twice.
HTH
Peter
> -----Original Message-----
> From: TSO REXX Discussion List [mailto:TSO-...@vm.marist.edu] On
> Behalf Of Robert Zenuk
> Sent: Sunday, January 30, 2011 12:57 PM
> To: TSO-...@vm.marist.edu
> Subject: Re: Link Date in a PDS(E)
>
> Here is an updated version that fixes the INVALID PDSE module code (I
> removed a valid eyecatcher to confirm).
>
> Rob
--
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.
----------------------------------------------------------------------