|
View previous topic :: View next topic
|
| Author |
Message |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
Hello,
My first post here, so please be patient :-)
I have a boatload of JCL members in a PDS I want to process to ensure that a DATACLAS has been specified for all new file allocations.
Wherever I find a file with DISP=NEW, and no DATACLAS value currently exists, I would like to add a DATACLAS= value.
I can do this manually of course, but given the number of members in the library, I may well be retired before I finish.
I would like to try to do this with an ISPF EDIT MACRO of some sort.
The EDIT itself is a bit fuzzy. I might find DISP=NEW or DISP=(NEW,CATLG,DELETE) or something else.
There could be any number of DD statements in the JCL deck.
I cannot quite get my head around how I could find a DD statement (I know I could do a FIND) and then examine all of the lines that apply to the DD statement and know that either a DATACLAS value has been specified or not.
Maybe I could find the 'DD' and assign a range start row label, and then find the next 'DD' and assign an end range row label, and then look for 'DATACLAS' within the label range?
If I don't find 'DATACLAS' I could insert a new line with DATACLAS=somevalue.
Anyway, I am hoping someone may have already travelled this road, and may have something to share. |
|
| Back to top |
|
 |
sergeyken
Senior Member

Joined: 29 Apr 2008 Posts: 2264 Location: USA
|
|
|
|
Too many tricky combinations need to be considered.
| Code: |
//DATA DD DISP=(,KEEP),
//DATA DD DISP=NEW,
//DATA DD DISP=(NEW,KEEP),
//DATA DD DISP=(NEW,CATLG),
//DATA DD DISP=(NEW,CATLG),
//*DATA DD DISP=(NEW,CATLG),DATACLAS=ABCD123, comment...
//DATA DD DISP=(NEW,CATLG),
// DATACLAS=ABCD123, comment...
//DATA DD DISP=OLD, DISP=(NEW,CATLG), comment...
// DATACLAS=ABCD123,
//DATA DD DATACLAS=ABCD123,
// DISP=(NEW,CATLG),
//TEST EXEC PGM=SPECPROG,
// PARM='DATACLAS=ABCD123,DISP=NEW' wrong context...
… etc. etc. etc. ...
|
Unless the original JCL members are strictly formalized and aligned, I would not try to parse free-text JCL with ISPF MACROs... |
|
| Back to top |
|
 |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
Essentially, I did a FIND to locate a DD statement and added a LABEL. Then I did another FIND to identify the NEXT DD statement, or end-of-file and added a LABEL.
Then I did a FIND within the RANGE to locate a DATACLAS value.
If I found one I was done.
Otherwise, I tried to FIND DISP=NEW or DISP=(NEW or DISP=(, showing I had a new file allocation.
Then I just inserted a line to support DATACLAS=... |
|
| Back to top |
|
 |
sergeyken
Senior Member

Joined: 29 Apr 2008 Posts: 2264 Location: USA
|
|
|
|
| Cameron Conacher wrote: |
Essentially, I did a FIND to locate a DD statement and added a LABEL. Then I did another FIND to identify the NEXT DD statement, or end-of-file and added a LABEL.
Then I did a FIND within the RANGE to locate a DATACLAS value.
If I found one I was done.
Otherwise, I tried to FIND DISP=NEW or DISP=(NEW or DISP=(, showing I had a new file allocation.
Then I just inserted a line to support DATACLAS=... |
As I mentioned above, this approach for non-strictly-standardized JCL is a Pandora Box.
You can try doing this, but be prepared to continue fixing newly discovered bugs/special cases for the rest of your life... |
|
| Back to top |
|
 |
David Robinson
Active User
Joined: 21 Dec 2011 Posts: 199 Location: UK
|
|
|
|
Do you have any of the JCL checker tools? Job/Scan has a standards facility in it where you can enforce particular rules or statements applicable to your environment, including updating the JCL. I imagine it would be able to do something like this, although I haven't used it for a while.
The advantage of using a JCL checker is that it "understands" the JCL. You don't have to try and cater for all the variations in code layout that you might come across. |
|
| Back to top |
|
 |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
Yes, we have some checker tooling.
My plan is to make all the changes and then run the tools to ensure I have not broken anything.
And again, my feeling is that if I can hit on 95% of the issues, I will have made a huge dent in the associated work effort of modifying hundreds of thousands of JCL decks and PROCLIB members.
Without the checker, I might have introduced errors to hundreds of thousands of JCL Decks and PROCLIB members. Which would not be a good thing.  |
|
| Back to top |
|
 |
enrico-sorichetti
Superior Member

Joined: 14 Mar 2007 Posts: 10900 Location: italy
|
|
|
|
| Quote: |
Wherever I find a file with DISP=NEW, and no DATACLAS value currently exists, I would like to add a DATACLAS= value.
|
how are You going to determine the data class to be used for each dataset ? |
|
| Back to top |
|
 |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
We have ACS rules in place that use a default DATACLAS Name.
I am inserting a record with the DATACLAS=defaultname. |
|
| Back to top |
|
 |
sergeyken
Senior Member

Joined: 29 Apr 2008 Posts: 2264 Location: USA
|
|
|
|
After thinking a little bit of this issue, I believe that the approach with creating an ISPF macro is not very attractive solution in this situation:
1) if total number of members to fix their DATACLAS is relatively small, it might be easier, and faster just to update them manually, using the same EDIT commands and subcommands which are planned to include into the macro; I expect less efforts are required compared to coding and debugging this macro.
2) if total number of members to fix their DATACLAS is really huge, then wasting time on coding the macro might make sense, but another problem would arise: how to apply that macro (after it has been debugged) to many thousands of members?
As often happened in my life, a very primitive straightforward solution would work much faster, and it requires much less efforts to prepare. Often using an old hammer to knock nails is much more preferable than buying a sophisticated robotic device controlled via Wi-Fi, and used GPS navigation to do the same job.
So far I spent about an hour to code, and test, and debug a simple solution - fully in JCL - using only standard utilities; no more code is needed. It handles any number of members in less than one minute, and updates only those members requiring this update.
| Code: |
//*---------------------------------------------------------------------
// SET LIBRARY=&SYSUID..JCL
// SET KEYPAR='DATACLAS'
// SET DEFVAL='SPECCLAS'
//*---------------------------------------------------------------------
// SET LOG='SYSOUT=*'
//*SET LOG='DUMMY'
// SET DEBUG='SYSOUT=*'
//*SET DEBUG='DUMMY'
//*---------------------------------------------------------------------
//*
//*=====================================================================
//* CONVERT LIBRARY TO STREAM DATA
//*=====================================================================
//STREAM EXEC PGM=IEBPTPCH
//*
//SYSPRINT DD &LOG
//*
//SYSUT1 DD DISP=SHR,DSN=&LIBRARY
//SYSUT2 DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(300,300),RLSE),
// DSN=&&STREAM
//*
//SYSIN DD *
PUNCH TYPORG=PO,MAXFLDS=1
RECORD FIELD=(80)
//*
//*=====================================================================
//* UPDATE LIBRARY STREAM
//*=====================================================================
//UPDATE EXEC PGM=SORT,
// PARM='JP1"&KEYPAR="'
//*
//SYSOUT DD &LOG
//*
//SORTIN DD DISP=(OLD,DELETE),DSN=&&STREAM
//*
//LIST@ DD &DEBUG
//LIST DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&LIST
//*
//CLASS@ DD &DEBUG
//CLASS DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&CLASS
//*
//NEW@ DD &DEBUG
//NEW DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&NEW
//*
//SYSIN DD *
INREC IFTHEN=(WHEN=GROUP,
BEGIN=(2,11,CH,EQ,C'MEMBER NAME'),
PUSH=(82:15,8)),
IFTHEN=(WHEN=GROUP,
BEGIN=(2,2,CH,EQ,C'//',
AND,2,3,CH,NE,C'//*',
AND,5,20,SS,EQ,L(C' DD ',
C' EXEC ',
C' SET ',
C' JCLLIB ',
C' JOB ',
C' IF ',
C' ENDIF ',
C' PROC ',
C' PEND ')),
PUSH=(90:ID=8,SEQ=8))
*
SORT FIELDS=(82,8,CH,A,
90,8,CH,A,
98,8,CH,A),
EQUALS
*
OUTREC IFTHEN=(WHEN=(2,11,CH,EQ,C'MEMBER NAME'),
OVERLAY=(2:C'./ ADD NAME=',15,8,10X))
*
OUTFIL FNAMES=(LIST@,LIST)
*
OUTFIL FNAMES=(NEW@,NEW),
INCLUDE=(2,2,CH,EQ,C'//',
AND,2,3,CH,NE,C'//*',
AND,90,8,ZD,EQ,NUM,
AND,(6,50,SS,EQ,C'DISP=(,',
OR,6,50,SS,EQ,C'DISP=(NEW',
OR,6,50,SS,EQ,C'DISP=NEW'))
*
OUTFIL FNAMES=(CLASS@,CLASS),
INCLUDE=(2,2,CH,EQ,C'//',
AND,2,3,CH,NE,C'//*',
AND,90,8,ZD,EQ,NUM,
AND,5,66,SS,EQ,JP1)
*
END
//*
//*=====================================================================
//* RESTRICT TO ONLY DISP=NEW, AND NO DATACLAS=
//*=====================================================================
//RESTRICT EXEC PGM=SORT
//*
//SYSOUT DD &LOG
//*
//NEW DD DISP=(OLD,DELETE),DSN=&&NEW
//CLASS DD DISP=(OLD,DELETE),DSN=&&CLASS
//*
//NEWMOD@ DD &DEBUG
//NEWMOD DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&NEWMOD
//*
//MEMBERS@ DD &DEBUG
//MEMBERS DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&MEMBERS
//*
//SYSIN DD *
JOINKEYS F1=NEW,
FIELDS=(82,8,A,
90,8,A),
SORTED
*
JOINKEYS F2=CLASS,
FIELDS=(82,8,A,
90,8,A),
SORTED
*
JOIN UNPAIRED,F1,ONLY
*
SORT FIELDS=(82,8,CH,A)
*
OUTFIL FNAMES=(NEWMOD@,NEWMOD)
*
OUTFIL FNAMES=(MEMBERS@,MEMBERS),
REMOVECC,NODETAIL,
SECTIONS=(82,8,
TRAILER3=(82,8))
*
END
//*
//*=====================================================================
//SHORTEN EXEC PGM=SORT
//*
//SYSOUT DD &LOG
//*
//LIST DD DISP=(OLD,DELETE),DSN=&&LIST
//MEMBERS DD DISP=(OLD,DELETE),DSN=&&MEMBERS
//*
//SHORT@ DD &DEBUG
//SHORT DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&SHORT
//*
//SYSIN DD *
JOINKEYS F1=LIST,
FIELDS=(82,8,A),
SORTED
*
JOINKEYS F2=MEMBERS,
FIELDS=(1,8,A),
SORTED
*
REFORMAT FIELDS=(F1:1,105)
*
SORT FIELDS=COPY
*
OUTFIL FNAMES=(SHORT@,SHORT)
*
END
//*
//*=====================================================================
//* CORRECT STREAM
//*=====================================================================
//CORRECT EXEC PGM=SORT,
// PARM='JP1"&KEYPAR=&DEFVAL"'
//*
//SYSOUT DD &LOG
//*
//SHORT DD DISP=(OLD,DELETE),DSN=&&SHORT
//NEWMOD DD DISP=(OLD,DELETE),DSN=&&NEWMOD
//*
//JOINED@ DD &DEBUG
//JOINED DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&JOINED
//*
//CORRECT@ DD &DEBUG
//CORRECT DD DISP=(NEW,PASS),
// UNIT=SYSDA,SPACE=(TRK,(100,100)),
// DSN=&&CORRECT
//*
//SYSIN DD *
JOINKEYS F1=SHORT,
FIELDS=(82,8,A,
90,8,A),
SORTED
*
JOINKEYS F2=NEWMOD,
FIELDS=(82,8,A,
90,8,A),
SORTED
*
JOIN UNPAIRED,F1
*
REFORMAT FIELDS=(F1:2,104,?)
*
SORT FIELDS=COPY
*
OUTFIL FNAMES=(JOINED@,JOINED)
*
OUTFIL FNAMES=(CORRECT@,CORRECT),
IFTHEN=(WHEN=(105,1,CH,EQ,C'B',
AND,1,2,CH,EQ,C'//',
AND,1,3,CH,NE,C'//*',
AND,1,30,SS,EQ,C' DD ',
AND,1,60,SS,EQ,C', '),
BUILD=(1,80,
/,C'// ',JP1,C',')),
IFTHEN=(WHEN=(105,1,CH,EQ,C'B',
AND,1,2,CH,EQ,C'//',
AND,1,3,CH,NE,C'//*',
AND,1,30,SS,EQ,C' DD '),
PARSE=(%1=(ENDAT=BLANKS,
FIXLEN=11),
%2=(ENDAT=BLANKS,
FIXLEN=4),
%3=(ENDBEFR=BLANKS,
FIXLEN=40)),
BUILD=(%1,%2,JP1,C', ',
/,C'// ',%3)),
IFTHEN=(WHEN=NONE,
BUILD=(1,80))
*
END
//*=====================================================================
//* REPLACE UPDATED MEMBERS IN LIBRARY
//*=====================================================================
//REPLACE EXEC PGM=IEBUPDTE,PARM='NEW'
//*
//SYSPRINT DD &LOG
//*
//SYSUT2 DD DISP=SHR,DSN=&LIBRARY
//*
//SYSIN DD DISP=(OLD,DELETE),DSN=&&CORRECT
//*
//*===================================================================== |
I cannot guarantee this code is 100% bug-free, but with my test library I did not find any wrong behavior. Of course, in order to use it in production more testing is strictly required, but for myself it was enough to demonstrate the benefits of the simplest possible solution.
One more benefit: if some misbehavior is detected after a huge library has been converted, is would be a piece of cake to apply the updated code to all thousands of original members. |
|
| Back to top |
|
 |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
Nice,
I went the route of writing and debugging the ISPF Edit macro, and then wrapped it in a small REXX utility which iterates over all members of a PDS. |
|
| Back to top |
|
 |
Joerg.Findeisen
Senior Member

Joined: 15 Aug 2015 Posts: 1429 Location: Bamberg, Germany
|
|
|
|
| @sergeyken: There is only one downside with IEBPTPCH/IEBUPDTE that I know of. When processing Members containing IEBUPDTE statements itself, they would be interpreted in the final step. |
|
| Back to top |
|
 |
sergeyken
Senior Member

Joined: 29 Apr 2008 Posts: 2264 Location: USA
|
|
|
|
| Joerg.Findeisen wrote: |
| @sergeyken: There is only one downside with IEBPTPCH/IEBUPDTE that I know of. When processing Members containing IEBUPDTE statements itself, they would be interpreted in the final step. |
Yes, there are also some other drawbacks in this basic solution.
A simple workaround would be to detect all members with ./ statements (plus combination of DISP=NEW + no DATACLAS), and to move that part into separate dataset/library, with recommendation to update those members manually.
From other side, in the past 10-15 years I did not meet any colleague who has used IEBUPDTE in his JCLs even once!
The most of new "experts" even did not hear about it. |
|
| Back to top |
|
 |
Phrzby Phil
Senior Member
Joined: 31 Oct 2006 Posts: 1054 Location: Richmond, Virginia
|
|
|
|
I retired a few years ago, but I enjoy monitoring this excellent forum.
I have also enjoyed this technical discussion.
I do not recall ever dealing much with DATACLAS, but if I understand the problem here, you want to insert an explicit DATACLAS clause into certain JCL statements lacking it, and the value you are to assign is your installation's default value.
So my question is, and maybe (most likely) I'm missing something here, why all of this trouble (although a very interesting challenge) to specify a default value? |
|
| Back to top |
|
 |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
Great question.
I left out some of the background "noise".
This all relates to Pervasive Encryption.
We have an existing default DATACLAS Name value of lets say "FRED".
However, I need to change this to "FREDEXTENDED" in support of the Pervasive Encryption initiative.
One approach is to simply change the default.
I have issues with that approach, since it would change everything for everyone. Different Applications will line up to manage their own Pervasive Encryption initiatives on their own timeline.
So, one way to skin this cat is to jump in and eliminate the assignment of a "default". I will ensure that every JCL Deck and PROCLIB member within our remit, has assigned an appropriate DATACLAS Name where needed. |
|
| Back to top |
|
 |
Phrzby Phil
Senior Member
Joined: 31 Oct 2006 Posts: 1054 Location: Richmond, Virginia
|
|
|
|
Thanks for the additional context. Always good to include that, as the real experts on this forum will have more to work with.
Assuming different applications' datasets have dedicated high level qualifiers, can the system set defaults per HLQ's?
I expect this is a systems programmer issue, of which I have had little experience. |
|
| Back to top |
|
 |
Cameron Conacher
New User
Joined: 11 Dec 2019 Posts: 8 Location: Canada
|
|
|
|
Yes,
The Systems Programmer folks can set Automatic Class Selection based on HLQ.
An, coincidentally, that is how I first planned to address this item.
However, if I take ownership, and I force all JCL/PROCs to use an appropriate DATACLAS Name, we won't have anything hidden in the long grass anymore.
A DATACLAS Name can specify defaults for primary and secondary space allocation. Or the DATACLAS Name might not specify any. In which case you might see JCL with no DATACLAS Name (use a default) and then assign SPACE= based on the default. Without knowing the default for the DATACLAS Name, and without knowing how the ACS rules make assignments, it is tough to guess what is being leveraged for actual assignments in a JOB.
I am looking at this as an opportunity to clean thing up and be more explicit. |
|
| Back to top |
|
 |
Phrzby Phil
Senior Member
Joined: 31 Oct 2006 Posts: 1054 Location: Richmond, Virginia
|
|
|
|
Thanks for the update. We look forward to further info as your project progresses.
I have always been a fan of cleaning things up and being explicit - good luck! |
|
| Back to top |
|
 |
vasanthz
Global Moderator

Joined: 28 Aug 2007 Posts: 1750 Location: Tirupur, India
|
|
|
|
"I have always been a fan of cleaning things up and being explicit"
I wish my girlfriend said this :'( |
|
| Back to top |
|
 |
Phrzby Phil
Senior Member
Joined: 31 Oct 2006 Posts: 1054 Location: Richmond, Virginia
|
|
|
|
vasanthz, as for Cameron, more context for your problem will also be helpful, and most likely more interesting.
We also will need to know if your girlfriend should say "Good luck!" |
|
| Back to top |
|
 |
Joerg.Findeisen
Senior Member

Joined: 15 Aug 2015 Posts: 1429 Location: Bamberg, Germany
|
|
|
|
On a side note, whatever you specify in the JCL as DATACLAS can be used by the ACS routines. Depending on how strict they (ACS) are, they might enforce their own assignments and simply ignore what JCL wants to have.
However if you allow classes to be used by anyone, be aware that different encryptions might be in use for the same application depending from where the JCLs are copied together. |
|
| Back to top |
|
 |
vasanthz
Global Moderator

Joined: 28 Aug 2007 Posts: 1750 Location: Tirupur, India
|
|
|
|
| Quote: |
| We also will need to know if your girlfriend should say "Good luck!" |
Good luck? I only expect a smile and a simple Thank you, when I make her breakfast in bed. Instead I get too many tantrums like,
"How did you get in? who are you? Why are you covered in baby oil?"
some people... SMH. |
|
| Back to top |
|
 |
Pedro
Global Moderator

Joined: 01 Sep 2006 Posts: 2624 Location: Silicon Valley
|
|
|
|
| Quote: |
Essentially, I did a FIND to locate a DD statement and added a LABEL. Then I did another FIND to identify the NEXT DD statement, or end-of-file and added a LABEL.
Then I did a FIND within the RANGE to locate a DATACLAS value. |
This logic makes me somewhat uneasy, though I cannot articulate exactly why. I think my preference is to enclose your logic to be nested within another search for EXEC statement so that you do all of the DD statements for each job step before going to the next job step. Yeah, I know the difference is minuscule.
Other things to watch out for:
* extending line text beyond column 71
* finding DATACLAS within a comment |
|
| Back to top |
|
 |
|
|
 |
All times are GMT + 6 Hours |
|