Add months but the parameter is from the data JCL - mainframe

I have data like this
----+----1----+----2----+----3----+--
000000002320110328087YY01200000020124
I want to add the months from column 11-18, with the value from 24-26
I am thinking about the outrec field is like this
11,8,Y4T,ADDMONS,24,3,TOGREG=Y4T(-)
But when I try it , it give rc=0016, because of the operand error ,
I am thinking about store the value of 24,3 to a variable then i put it to variable , but i dont know if JCL can provide that .. anyone can help?
Notes : i use dfsort , not icetool
and i dont want to hardcode it because i already try 11,8,Y4T,ADDMONS,+12,TOGREG=Y4T(-), and it works but if can , iwant to replace the "+12" with the value from column 24-26

The syntax diagram for ADDMONS for your case is shown as:
p,m,Y4T,ADDMONS,p,m,f,TOGREG=Y4T(-)
You're missing the f subparameter. Since the number of months to add is a series of digits, the format would be UFF. I ran this sort job:
//SORT#010 EXEC PGM=ICEMAN
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SORTIN DD *
000000002320110328087YY01200000020124
/*
//SORTOUT DD SYSOUT=*
//SYSIN DD *
SORT FIELDS=COPY
OUTREC FIELDS=(11,8,Y4T,ADDMONS,24,3,UFF,TOGREG=Y4T(-))
/*
The result in SORTOUT is:
2012-03-28
Is this what you wanted?

I'm not aware of a way to do this with plain DFSORT.
For instance PARSE would not work, because it would fail to resolve %2:
INREC PARSE=(%1=(ABSPOS=11,FIXLEN=8),
%2=(ABSPOS=24,FIXLEN=3)),
BUILD=(%1,Y4T,ADDMONS,+%2,TOGREG=Y4T(-))
You might want to look at sort exits if you'd like to go with DFSORT.

You get a bad return code because DFSORT doesn't know how to interpret the three bytes you gave it with 24,3.
You should use : 11,8,Y4T,ADDMONS,24,3,ZD,TOGREG=Y4T(-)
The ZD that I have inserted means : Zoned Decimal. It corresponds to a PIC 9 USAGE DISPLAY in Cobol.
You can interpret COMP-3 with PD and COMP-5 or BINARY with BI.

Related

Generate a report using DFSORT

I have a task to write a JCL job invoking ICETOOL/DFSORT to generate a report. The report takes a VSAM KSDS as input and generates a list of bank branches.
Each record in the BRANCHES KSDS is of the form
• 4-byte binary unsigned integer representing a 6-digit decimal branch sortcode (e.g. 420101)
• 1-byte EBCDIC flag: ◦ EBCDIC 'A' means the branch is owned by ZeusBank and all its accounts are held in the ACCOUNTS KSDS
◦ EBCDIC 'B' means the branch is not owned by ZeusBank so we do not hold its account information in the ACCOUNTS KSDS
• 32-byte EBCDIC character branch name (e.g. “ZEUSBANK FOOFORD BAR STREET” or “OTHERBANK QUUXHAM BAZ ROAD”), blank padded on the right.
The report should look like this
I'm pretty new to JCL so please forgive if the question is simple. Thanks.
You can try this:
//STEPSORT EXEC PGM=SORT
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SORTIN DD DSN=DATASETNAME
//SORTOUT DD SYSOUT=*
//SYSIN DD *
SORT FIELDS=(5,1,CH,A)
OUTFIL HEADER2=(1:C'LIST OF WHATEVER BANK',4/,
1:C'SORTCODE',10:C'FLAG',15:C'BRANCH',/,
1:C'--------',10:C'----',15:C'------'),
BUILD=(1:1,4,BI,TO=ZD,LENGTH=6,10:5,1,15:6,32)
/*

Setting PATH in IEBGENER from file

I'm trying to set the PATH parameter in a IEBGENER step in a JCL from a file. But I can't seem to get it to work.
Here is what the original step, that works just fine, looks like:
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD *
Some text
//SYSUT2 DD PATH='/local/Folder1/File1',
// PATHDISP=(KEEP,KEEP),
// PATHOPTS=(OWRONLY,OCREAT,OEXCL),
// PATHMODE=(SIRUSR,SIWUSR)
What I want to do is set the PATH parameter in SYSUT2 from a file that is written in some previous step. Something like this:
BROWSE TEST.FILE1 Line 0000000000 Col 001 080
Command ===> Scroll ===> CSR
********************************* Top of Data **********************************
TPATH='/local/Folder1/File1'
******************************** Bottom of Data ********************************
//SETPATH SET DSN=TEST.FILE1,DISP=SHR
//*
//COPY EXEC PGM=IEBGENER
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
//SYSUT1 DD *
Some text
//SYSUT2 DD PATH='&TPATH',
// PATHDISP=(KEEP,KEEP),
// PATHOPTS=(OWRONLY,OCREAT,OEXCL),
// PATHMODE=(SIRUSR,SIWUSR)
This of course complains about no variable TPATH in the JCL, which logically makes sense as it can't find the variable name in the JCL.
Also tried putting the entire SYSUT2 in a separate file, but without success.
A "good enough" compromise would be to concatenate a file prefix with a date and time parameter, but that would only work in production when the job is run via a scheduler (with OPCSCAN or similar). Not in test where I submit the job myself, or is it possible to do that without a scheduler?
'/local/Folder1/File' & iDate & iTime -- You get the point.
Any ideas much appreciated!
One way to do this would be to write the SYSUT2 DD statement to a member in a separate PDS or PDSE, then INCLUDE that member in your IEBGENER step. The separate PDS or PDSE must be specified in a JCLLIB statement.
You could also run BPXBATCH and use cp instead of IEBGENER to copy your data.
If you have the Dovetail Technologies Co:Z Toolkit installed, fromdsn might be what you're looking for.

Mainframe JCl for ans

One Jcl question
We have 3 steps in jcl,
Step1
Step2
Step3
If step 1 output empty ,then step2 need to run else step 3 need to be run.
Any one know answer?
It should not be add any new steps and solution should be thru jcl only
if you would like to do that with JCL there are several possibilities. I give you my favorite one:
//* Using IDCAMS
//* -------------------------------------------------------------------
//* Sets RC=0000 if dataset has records. *
//* Sets RC=0004 if dataset is empty. *
//*-------------------------------------------------------------------*
//IDCAMS0 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//MYFILE DD DISP=SHR,DSN=<Dataset Name>
//SYSIN DD *
PRINT INFILE(MYFILE) CHARACTER COUNT(1)
Regards,
Andreas
I wouldn't call it an elegant solution, but one simple way to handle this is to write yourself a short program that runs after step 1 and before step 2. This program checks to see if the output file from step 1 is empty or not, setting the return code to indicate one from the other, and then you can use standard JCL COND checking on the subsequent steps to get the result you want.
There are lots of ways to check for empty files...I'd use stat() in C/C++, but it can be done in Java and even REXX or other scripting languages if you prefer. In worst case, you just open and read the input file, returning the empty return code if you get an immediate EOF, otherwise return the non-empty return code.

Take the last file and use it as jcl variable

I have to do a job that uses the last file from a base name. For example, if I am having:
FILE.140115
FILE.140111
FILE.140101
I need to catch FILE.140115 wich has the closest date from today.
So, I would use:
//TEST010 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//OUTDD DD DSN=FILE.LISTFILE,
// DISP=(NEW,CATLG,DELETE),
// DATACLAS=(MED),
// DCB=(RECFM=VB,LRECL=125)
//SYSIN DD *
LISTCAT ENT(FILE.*) -
NAME -
OUTFILE(OUTDD)
Then, using a sort I can obtain a single file with the name of the file that I need inside. But I dont know how to use the content of this file as a variable to use it as parameter in another step.
Is there a way to do this without using CLIST? Or other ways to do what I want.
Thanks in advance!
Have you tried using a GDG? Many problems normally solved in a distributed environment with date/timestamps in file names are readily solved in a mainframe environment with GDGs.

How to create a member in an existing pds using jcl

I've used the below jcl:
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DUMMY,RECFM=FB,LRECL=80
//SYSUT2 DD DSN=RK.MYDIR.FILES(NEW1),DISP=(SHR)
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY
I was able to create it. But i can't understand the code here. Is there any possibility to create using IEFBR14. If not this is the nly way. Please kindly explain me the code. Thank you
It can't be done with IEFBR14
IEBCOPY is more appropriate:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBCOPY.htm
This is the reference which helps explain IEBGENER:
http://publib.boulder.ibm.com/infocenter/zos/basics/index.jsp?topic=/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBGENER.htm
If you're interested in the reason why, understand that IEFBR14 doesn't actually open any of the DD statements you code in your JCL. Rather, it's just a shorthand way to drive the system allocation (and deallocation) routines. Indeed, if you were to look at an assembler listing of iEFBR14, you'd find it's only two instructions: set the R15 return code to zero, and exit.
With batch processing, the idea is that the system (JES plus the batch initiator) should do a lot of the work before an application even starts. Thus, if you allocate a new dataset, or reference (say) a tape device that takes time for the operator to mount, the system does all this for you before your program even starts. IEFBR14 is a convenient way to use the system allocation routines to allocate files using these capabilities of JCL.
But there's a catch when it comes to accessing PDS datasets in JCL, like you're trying to do.
When you specify DSN(MEMBER) syntax in JCL, the allocation routines don't particularly care about the MEMBER part - turns out, this isn't a function of the initiator, but is instead implemented in OPEN/CLOSE. In your example, allocation verifies that the dataset exists (since you coded DISP=SHR), and when a program OPENs the DD statement, the OPEN routines automatically issue BPAM FIND/POINT/STOW to get you to the PDS member you specified. This is how your PDS member gets created, and so you need to use a program that actually OPENs the file (IEBGENR, IEBUPDTE, IEBCOPY, IDCAMS, etc would all work).
One small unrelated comment is that you might want to be careful about updating datasets (especially PDS) using DISP=SHR. If you manage to get the timing wrong, two of these jobs could in theory run at exactly the same time, and this would likely cause corruption to your dataset. Unless you're certain you're the only task accessing the PDS, it's safer to use DISP=OLD in this case.
If you'd like to create multiple members at once, I suggest IEBUPDTE.
From IBM:
This basic example uses IEBUPDTE to add two JCL procedures to the data set named MY.PROCLIB:
//ADDPROC1 JOB 1,SMCHUGH,MSGCLASS=X
// EXEC PGM=IEBUPDTE
//SYSPRINT DD SYSOUT=*
//SYSUT1 DD DISP=OLD,DSN=MY.PROCLIB
//SYSUT2 DD DISP=OLD,DSN=MY.PROCLIB
//SYSIN DD DATA
./ ADD LIST=ALL,NAME=MYJOB1
//STEP1 EXEC=SUZNX1
//PRINT DD SYSOUT=A
// (more JCL for MYJOB1)
//SYSUDUMP DD SYSOUT=* (last JCL for MYJOB1)
./ REPL LIST=ALL,NAME=LASTJOB
//LIST EXEC PGM=SUZNLIST
// (more JCL for this procedure)
//* LAST JCL STATEMENT FOR LASTJOB
./ ENDUP
/*
This creates one new member, MYJOB1, but you can see that it can also replace members (LASTJOB).
http://publib.boulder.ibm.com/infocenter/zos/basics/topic/com.ibm.zos.zdatamgmt/zsysprogc_utilities_IEBUPDTE.htm
If you are copying the contents of a DSN into the new member, use IEBGENER.
To set the attributes of the new DSN dynamically use the LIKE parameter.
For example (using Mikes example above)
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset
//SYSUT2 DD DISP=(,CATLG,DELETE),DSN=your.output.dataset,
// LIKE=your.input.dataset
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY <-- no CONTROL statements
The LIKE attribute lets you easily create a new dataset, using the attributes of the dataset you specify, I also changed the disposition to reflect what a new DSN should be set to.
Warning! -- in re using IEBGENER with SYSUT2 DD DSN=PDS(MEMBER): Don't forget to specify the MEMBER name -- if you do, IEBGENER will overwrite your PDS from the beginning with whatever it finds in SYSUT1, starting with ruining your PDS directory!
The IEBGENER utility is used to copy a single file.
The SYSUT1 DD name is used to supply the INPUT or file to be copied from.
The SYSUT2 DD name is the OUTPUT file.
The SYSIN DD provides the CONTROL statements (if any).
//STEP1 EXEC PGM=IEBGENER
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset
//SYSUT2 DD DISP=SHR,DSN=your.output.dataset
//SYSPRINT DD SYSOUT=*
//SYSIN DD DUMMY <-- no CONTROL statements
Note that the file/dataset can be a sequential dataset or a member of a partitioned dataset.
//SYSUT1 DD DISP=SHR,DSN=your.input.dataset(member)
//SYSUT2 DD DISP=SHR,DSN=your.output.dataset(member)

Resources