John_Ha wrote:No-one ever writes JCL from scratch - they find something close enough and hack it.
I wrote tens of thousands of lines of JCL, since I was a mainframe programmer/analyst for over three decades. Of course I would borrow from other JCL I had written when possible, but it was often easier to just create anew instead of searching for a good match. JCL is rather wordy, especially before improvements were made in the mid-1980s, but it is not difficult. Here is some of my JCL, which had to be created from scratch as no one else had done anything remotely similar.
Though JCL may seem awful, it helps to understand the context. The machines for which it was designed had, by modern standards, tiny amounts of memory, say 256K (or even 32K), and slow processors. Thus simplicity — for the operating system, not for the programmer — was very important. This pushed more work onto the people who created the JCL, but that was OK because the machine's resources were so valuable. Programmers were less expensive than computers. There was no "virtual storage". That ¼ megabyte had to hold the operating system, the program, and its data. And typically this was the only computer which the organization had. Times were quite different then.
Mainframes today still use JCL for two reasons:
• It is quite flexible in managing the machine's resources.
• Downward compatibility is regarded as very important in that environment. Things developed 20 or more years ago, should work
without any change today. An assembler program written in the mid-1970s for 24-bit hardware will run just fine on a modern 64-bit mainframe. I know this from personal experience.
//*-----------------------------------------------------------------*//
//* BEFORE SUBMITTING THIS JOB, EXIT ISPF AND ISSUE *//
//* THE "TSOLIB DEACT" AND "FREE ALL" COMMANDS *//
//*-----------------------------------------------------------------*//
//* SEE DETAILED DOCUMENTATION IN \\FILES\SHARE\CORPORATE\MIS\ *//
//* COMPUTER SERVICES\AS400 S390 STORAGE SYSTEMS\PUBLIC\S390\ *//
//* SAPR3 DOCUMENTATION\USING FTPGROUP TO COPY BETWEEN SYSPLEXS.TXT *//
//*-----------------------------------------------------------------*//
// SET TARGET=TWQ0 LPAR WHERE DATA WILL BE SENT
// SET PDS=B68778.DATA DATASET WITH 4 MEMBERS BELOW
// SET NETRC=FTPNETRC MEMBER WITH USER ID
// SET DUMP=FTPDUMP B68778.**
// SET RESTORE=FTPREST **
// SET JOBCARD=FTPJOB MEMBER WITH JOB STATEMENT
// SET WORK=BASIS.B68778.ADRDSSU OUTPUT FROM DF/DSS DUMP
// SET MEGS=50 SIZE OF OUTPUT IN MEGS
//*-----------------------------------------------------------------*//
//* DELETE WORK DATASET IF IT EXISTS *//
//*-----------------------------------------------------------------*//
//#0 EXEC PGM=IKJEFT01,REGION=6M,PARM='%FTPGRPR0 &WORK'
//SYSEXEC DD DISP=SHR,DSN=SYS6.AMBER.DATA
//SYSTSIN DD DUMMY
//SYSTSPRT DD SYSOUT=*
//*-----------------------------------------------------------------*//
//* DUMP DATASET GROUP TO DISK *//
//*-----------------------------------------------------------------*//
//#1 IF RC = 0 THEN
//#1 EXEC PGM=ADRDSSU,REGION=6M,TIME=NOLIMIT
//SYSIN DD DISP=SHR,DSN=&PDS(&DUMP)
//SYSPRINT DD SYSOUT=*
//DATA DD DISP=(NEW,PASS),DSN=&WORK,UNIT=SYSDA,
// AVGREC=M,SPACE=(1,(&MEGS,&MEGS),RLSE),
// DSORG=PS,RECFM=U,BLKSIZE=27998
//*-----------------------------------------------------------------*//
//* CREATE PARAMETERS FOR UTILITIES *//
//*-----------------------------------------------------------------*//
//#2 IF RC = 0 THEN
//#2 EXEC PGM=IKJEFT01,REGION=6M,PARM='%FTPGRPR1'
//SYSEXEC DD DISP=SHR,DSN=SYS6.AMBER.DATA
//SYSTSIN DD DUMMY
//SYSTSPRT DD SYSOUT=*
//RESTORE DD DISP=SHR,DSN=&PDS(&RESTORE)
//JOBCARD DD DISP=SHR,DSN=&PDS(&JOBCARD)
//DATA DD DISP=(OLD,CATLG),DSN=*.#1.DATA
//FTPDEL DD DISP=(NEW,PASS),UNIT=VIO,AVGREC=U,SPACE=(80,80),
// DSORG=PS,RECFM=FB,LRECL=80
//FTPPUT DD DISP=(NEW,PASS),UNIT=VIO,AVGREC=U,SPACE=(80,80),
// DSORG=PS,RECFM=FB,LRECL=80
//FTPSUB DD DISP=(NEW,PASS),UNIT=VIO,AVGREC=U,SPACE=(80,80),
// DSORG=PS,RECFM=FB,LRECL=80
//JOB DD DISP=(NEW,PASS),UNIT=VIO,AVGREC=U,SPACE=(80,80),
// DSORG=PS,RECFM=FB,LRECL=80
//*-----------------------------------------------------------------*//
//* DELETE DATA FROM TARGET IF IT EXISTS *//
//*-----------------------------------------------------------------*//
//#3 IF RC = 0 THEN
//#3 EXEC PGM=FTP,REGION=6M,TIME=NOLIMIT,
// PARM='&TARGET (TIMEOUT 600'
//INPUT DD DISP=(OLD,DELETE),DSN=*.#2.FTPDEL FB/80
//NETRC DD DISP=SHR,DSN=&PDS(&NETRC) FB/80
//OUTPUT DD SYSOUT=* FB/160
//SYSPRINT DD SYSOUT=*
//*-----------------------------------------------------------------*//
//* SEND DATA TO TARGET NODE *//
//*-----------------------------------------------------------------*//
//#4 IF RC = 0 THEN
//#4 EXEC PGM=FTP,REGION=6M,TIME=NOLIMIT,
// PARM='&TARGET (EXIT TIMEOUT 600'
//INPUT DD DISP=(OLD,DELETE),DSN=*.#2.FTPPUT FB/80
//NETRC DD DISP=SHR,DSN=&PDS(&NETRC) FB/80
//OUTPUT DD SYSOUT=* FB/160
//DATA DD DISP=(OLD,DELETE),DSN=&WORK
//SYSPRINT DD SYSOUT=*
//*-----------------------------------------------------------------*//
//* SUBMIT JOB TO RESTORE DATA ON TARGET NODE *//
//*-----------------------------------------------------------------*//
//#5 IF RC = 0 THEN
//#5 EXEC PGM=FTP,REGION=6M,TIME=NOLIMIT,
// PARM='&TARGET (EXIT TIMEOUT 600'
//INPUT DD DISP=(OLD,DELETE),DSN=*.#2.FTPSUB FB/80
//NETRC DD DISP=SHR,DSN=&PDS(&NETRC) FB/80
//JOB DD DISP=(OLD,DELETE),DSN=*.#2.JOB FB/80
//OUTPUT DD SYSOUT=* FB/160
//SYSPRINT DD SYSOUT=*
//#5 ENDIF RC = 0
//#4 ENDIF RC = 0
//#3 ENDIF RC = 0
//#2 ENDIF RC = 0
//#1 ENDIF RC = 0