Use IF-THEN-ELSE

(Republished at 9:55AM EST)

If your Endevor Processors are like most shops, you sometimes find yourself in the position of trying to remember which symbolics to override for which functions in which stage of which environment for which system… you know what I mean.

Many Administrators have taken advantage of symbolics in their CA-ENDEVOR processors so that they can control what is happening where. Unfortunately, we sometimes forget to customize exactly the same processor exactly the same way for every system in a stage. We have been able to ensure some consistency through the creative use of EXECIF and COND CODE checking (plus the later introduction of Batch Administration), but those tools are relatively limited leaving human intervention to complete the necessary customization.

Fortunately, Endevor introduced a tool to the Administrators arena; IF-THEN-ELSE processing. With a little imagination, some re-analysis of your present processors, and a little structure thrown in for good measure, you now have the opportunity to simplify your life as an Administrator; or at least reduce the number of calls due to processors operating differently across systems.

Consider the following processor…

//COPYSRC PROC INLIB=NDVR.&C1SY..&C1ST..SRCELIB1,
// OTLIB=NDVR.&C1SY..&C1ST..SRCELIB2
//COPY EXEC PGM=IEBCOPY,
// MAXRC=4,
// EXECIF=((&C1ST,NE,STG1),
// (&C1ST,NE,STG2),
// (&C1ST,NE,STG3))
//SYSPRINT DD SYSOUT=*
//INDD DD DSN=&INLIB,
// DISP=SHR
//OUTDD DD DSN=&OTLIB,
// DISP=SHR
//SYSIN DD *
COPY INDD=INDD,OUTDD=OUTDD
MEMBER=(&C1ELEMENT,,R)
/*
//* END OF PROCESSOR

This is a very simple processor that could be used to copy source from one library to another library. The conditions on the EXEC statement (i.e. the EXECIF statements) ensure the processor will never execute when the StageID is STG1, STG2, or STG3; otherwise, it will execute. While extremely simple, it will serve to illustrate the potential of IF-THEN-ELSE.

In our make-believe shop, there is no dataset that actually is suffixed “SRCELIB1” or “SRCELIB2” as in the example. Instead, the Administrator must remember to specify the real library name for the source-type the processor is defined to. Unfortunately, the Administrator did not embed or directly relate the name of the libraries to the types he/she wants to manipulate. So, consider the following table…

il1

The symbolics INLIB and OTLIB must be overridden manually by the Administrator to specifically supply the correct suffix depending on type every time the processor is used. If they forget, the processor abends.

So… how can we improve this processor? In essence, start making it a “smart” processor?

Let’s start with the EXEC statement.

Unlike regular JCL, IF-THEN-ELSE processing within ENDEVOR has full access to all the ENDEVOR symbolics. So why not use the opportunity to clarify (and eliminate) the EXECIF statement?

//COPYSRC PROC INLIB=NDVR.&C1SY..&C1ST..SRCELIB1,
// OTLIB=NDVR.&C1SY..&C1ST..SRCELIB2
// IF (&C1ST NE STG1) AND
// (&C1ST NE STG2) AND
// (&C1ST NE STG3) THEN
//COPY EXEC PGM=IEBCOPY,
// MAXRC=4
//SYSPRINT DD SYSOUT=*
//INDD DD DSN=&INLIB,
// DISP=SHR
//OUTDD DD DSN=&OTLIB,
// DISP=SHR
//SYSIN DD *
COPY INDD=INDD,OUTDD=OUTDD
MEMBER=(&C1ELEMENT,,R)
/*
// ENDIF
//* END OF PROCESSOR

Controlling the execution step in this way allows you to conditionally execute programs within your processor based on (for example) Processor Group Name, Type, Element… any processor symbolic supplied by ENDEVOR or, for that matter, any symbolic you define to the processor.

Now, let’s eliminate the need for library symbolics entirely within the processor by adding some intelligent checking based on our known nomenclature for libraries.

//COPYSRC PROC
// IF ((&C1ST NE STG1) AND
// (&C1ST NE STG2) AND
// (&C1ST NE STG3)) AND
// ((&C1TY = JCL) OR
// (&C1TY = PROC) OR
// (&C1TY = COBOL) OR
// (&C1TY = PLI)) THEN
//COPY EXEC PGM=IEBCOPY,
// MAXRC=4
//SYSPRINT DD SYSOUT=*
// IF (&C1TY = PROC) THEN
//INDD DD DSN=NDVR.&C1SY..&C1ST..PRCLIB,
// DISP=SHR
//OUTDD DD DSN=NDVR.&C1SY..&C1ST..PRCLIB2,
// DISP=SHR
// ELSE
// IF (&C1TY = JCL) THEN
//INDD DD DSN=NDVR.&C1SY..&C1ST..DRVJC,
// DISP=SHR
//OUTDD DD DSN=NDVR.&C1SY..&C1ST..DRVJC2,
// DISP=SHR
// ELSE
// IF (&C1TY = COBOL) THEN
//INDD DD DSN=NDVR.&C1SY..&C1ST..COBSRCE,
// DISP=SHR
//OUTDD DD DSN=NDVR.&C1SY..&C1ST..COBSRCE2,
// DISP=SHR
// ELSE
//INDD DD DSN=NDVR.&C1SY..&C1ST..PLSRCE,
// DISP=SHR
//OUTDD DD DSN=NDVR.&C1SY..&C1ST..PLSRCE2,
// DISP=SHR
// ENDIF
// ENDIF
// ENDIF
//SYSIN DD *
COPY INDD=INDD,OUTDD=OUTDD
MEMBER=(&C1ELEMENT,,R)
/*
// ENDIF
//* END OF PROCESSOR

In this example, I have allowed a fall-through to the PLI library if none of the types match the specified ones because I changed the conditional execution of the program to also check for source type. Combinations of IF-THEN-ELSE in EXEC statements and in DD statements provide a powerful new tool for controlling the execution of steps within processors as well as libraries used.

Experiment! In a recent upgrade to a linkage-editor processor, I was able to remove as many as 30 symbolics that were “prone to error” due to just-plain human error.

If you want to structure or simplify the “look” of your processors, try using INCLUDEs. You could, for example, put all the different library sets into separate INCLUDE members. Now your processor could look like the following…

//COPYSRC PROC
// IF ((&C1ST NE STG1) AND
// (&C1ST NE STG2) AND
// (&C1ST NE STG3)) AND
// ((&C1TY = JCL) OR
// (&C1TY = PROC) OR
// (&C1TY = COBOL) OR
// (&C1TY = PLI)) THEN
//COPY EXEC PGM=IEBCOPY,
// MAXRC=4
//SYSPRINT DD SYSOUT=*
// IF (&C1TY = PROC) THEN
++INCLUDE PROCLIBS
// ELSE
// IF (&C1TY = JCL) THEN
++INCLUDE JCLLIBS
// ELSE
// IF (&C1TY = COBOL) THEN
++INCLUDE COBLIBS
// ELSE
++INCLUDE PLILIBS
// ENDIF
// ENDIF
// ENDIF
//SYSIN DD *
COPY INDD=INDD,OUTDD=OUTDD
MEMBER=(&C1ELEMENT,,R)
/*
// ENDIF
//* END OF PROCESSOR

There is a lot of potential in IF-THEN-ELSE processing. Use your imagination and automate yourself out of trouble!

3 thoughts on “Use IF-THEN-ELSE

  1. In this example I would probably retain the original EXECIF because it displays a C1X0015I STEP 0005 (stepname) NOT EXECUTED BECAUSE OF AN “EXECIF” CLAUSE in the C1MSG1. I prefer to see a message whenever a processor step was not executed.

    Like

  2. The simplification is even better when the libraries are named with the actual ‘type’ as one of the file nodes, in addition to using the start-stage (&C1SSTAGE or &C1SSTGID) variable.
    The following
    // IF (&C1TY = PROC) THEN
    //INDD DD DSN=NDVR.&C1SY..&C1ST..PRCLIB,
    // DISP=SHR
    //OUTDD DD DSN=NDVR.&C1SY..&C1ST..PRCLIB2,
    // DISP=SHR
    // ELSE
    //…
    //… ENDIF
    //… ENDIF
    becomes
    //INDD DD DSN=NDVR.&C1SY..&C1SST..&C1TYPE,
    // DISP=SHR
    //OUTDD DD DSN=NDVR.&C1SY..&C1ST..&C1TYPE,
    // DISP=SHR
    which works for every type removing the need for the IF-THEN-ELSE altogether.

    Like

  3. preface your if/else/endif logic with labels. We use //CHKIF###, CHKLS###, CHKND### where the ### is relative to the CHKIF. this makes it easier to keep track of things when there are a plethora of CHKIF’s…

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s