MainframeMaster

JCL Tutorial

IF/THEN/ELSE/ENDIF Statements

Using structured conditional logic in JCL for flexible job flows

Progress0 of 0 lessons

Introduction to IF/THEN/ELSE in JCL

While the COND parameter provides a way to conditionally execute job steps, JCL also offers a more structured and readable approach with IF/THEN/ELSE/ENDIF statements. These statements allow for more complex conditional logic and provide a clearer representation of the intended flow.

IF/THEN/ELSE statements were introduced to JCL to provide enhanced conditional processing capabilities with more intuitive syntax. This tutorial covers how to use these statements to create sophisticated conditional job flows.

IF/THEN/ELSE/ENDIF Basic Syntax

The basic structure of IF/THEN/ELSE in JCL is as follows:

Basic Syntax:

jcl
1
2
3
4
5
// IF condition THEN //stepname EXEC PGM=program1 // ELSE //stepname EXEC PGM=program2 // ENDIF

Key points about the IF/THEN/ELSE syntax:

  • The IF statement begins in column 3 (after //) and must be followed by THEN on the same line
  • The ELSE clause is optional
  • Every IF must have a matching ENDIF
  • The statements within the IF/THEN/ELSE blocks are standard JCL statements
  • Conditions are enclosed in parentheses

Important Differences from COND Parameter

Unlike the COND parameter, the IF statement logic is intuitive - the THEN clause is executed if the condition is true. This makes IF statements much easier to read and understand compared to the "bypass if true" logic of COND parameters.

Condition Expressions

IF statements evaluate condition expressions that typically compare return codes. The condition must be enclosed in parentheses.

Comparison Operators:

GT - Greater Than

IF (STEP1.RC GT 4)

GE - Greater than or Equal

IF (STEP1.RC GE 8)

LT - Less Than

IF (STEP1.RC LT 8)

LE - Less than or Equal

IF (STEP1.RC LE 4)

EQ or = - Equal

IF (STEP1.RC = 0)

NE - Not Equal

IF (STEP1.RC NE 0)

Return Code References:

  • stepname.RC - Return code from a specific step
  • RC - Return code from the previous step
  • ABEND - Boolean indicating if the job has abended
  • ABENDCC - The abend completion code
  • RUN - Boolean indicating if the job is currently running
  • MAXRC - Highest return code from any previous step in the job

Examples of Basic Conditions:

jcl
1
2
3
4
5
// IF (STEP1.RC = 0) THEN // IF (RC = 0) THEN // IF (MAXRC < 8) THEN // IF (COMPILE.RC = 0) THEN // IF (ABEND = TRUE) THEN

Logical Operators

JCL IF statements support logical operators to combine multiple conditions:

AND Operator

Both conditions must be true

jcl
1
IF ((STEP1.RC = 0) AND (STEP2.RC < 8)) THEN

OR Operator

At least one condition must be true

jcl
1
IF ((STEP1.RC = 0) OR (STEP2.RC = 0)) THEN

When combining multiple logical operators, use parentheses to indicate precedence:

jcl
1
IF ((STEP1.RC = 0) AND ((STEP2.RC = 0) OR (STEP3.RC = 0))) THEN

Note on Logical Expression Evaluation:

JCL evaluates the entire logical expression, even if the result could be determined before completing the evaluation (unlike some programming languages that use short-circuit evaluation). This means all steps referenced in the condition must have executed previously in the job.

Nesting IF/THEN/ELSE Statements

JCL supports nesting of IF/THEN/ELSE structures, allowing for more complex decision trees:

jcl
1
2
3
4
5
6
7
8
9
// IF (STEP1.RC = 0) THEN //STEPA EXEC PGM=PROGRAMA // ELSE // IF (STEP1.RC = 4) THEN //STEPB EXEC PGM=PROGRAMB // ELSE //STEPC EXEC PGM=PROGRAMC // ENDIF // ENDIF

In this example, if STEP1 has a return code of 0, PROGRAMA executes. If it's 4, PROGRAMB executes. For any other return code, PROGRAMC executes.

Best Practices for Nested IF Statements:

  • Use consistent indentation to show nesting levels
  • Add comments to clarify complex logic
  • Each IF must have a matching ENDIF
  • Be careful with deeply nested logic (more than 3 levels) as it becomes hard to follow

Practical Examples

Example 1: Compile, Link, Execute with Error Handling

A more flexible version of the compile-link-execute pattern using IF/THEN/ELSE:

jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//COMPJOB JOB (ACCT),'COMPILE JOB',CLASS=A //* //COMPILE EXEC PGM=IKFCBL00 //SYSIN DD DSN=SOURCE.COBOL(PROGRAM),DISP=SHR //SYSLIN DD DSN=&&OBJSET,DISP=(NEW,PASS), // UNIT=SYSDA,SPACE=(TRK,(5,5)) //SYSPRINT DD SYSOUT=* //* // IF (COMPILE.RC <= 4) THEN //LINK EXEC PGM=IEWL //SYSLIN DD DSN=&&OBJSET,DISP=(OLD,DELETE) //SYSLMOD DD DSN=LOAD.LIBRARY(PROGRAM),DISP=SHR //SYSPRINT DD SYSOUT=* //* // IF (LINK.RC = 0) THEN //EXECUTE EXEC PGM=PROGRAM //STEPLIB DD DSN=LOAD.LIBRARY,DISP=SHR //SYSOUT DD SYSOUT=* //* // ELSE //LKERROR EXEC PGM=NOTIFY,PARM='LINK FAILED' //SYSPRINT DD SYSOUT=* // ENDIF //* // ELSE //CMPERROR EXEC PGM=NOTIFY,PARM='COMPILE FAILED' //SYSPRINT DD SYSOUT=* // ENDIF //* //CLEANUP EXEC PGM=IEFBR14

Example 1 Explanation:

  • The LINK step only executes if COMPILE was successful (RC <= 4)
  • The EXECUTE step only runs if LINK was completely successful (RC = 0)
  • If LINK fails, LKERROR notification step runs
  • If COMPILE fails, CMPERROR notification step runs
  • CLEANUP runs in all cases as it's outside any conditional block

Example 2: Complex Data Processing Logic

Using complex conditions to control the flow of a data processing job:

jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//DATAJOB JOB (ACCT),'DATA PROCESSING',CLASS=A //* //EXTRACT EXEC PGM=EXTRACT //INPUT DD DSN=INPUT.DATA,DISP=SHR //OUTPUT DD DSN=&&TEMP1,DISP=(NEW,PASS) //SYSPRINT DD SYSOUT=* //* // IF ((EXTRACT.RC = 0) OR (EXTRACT.RC = 4)) THEN //SORT EXEC PGM=SORT //SORTIN DD DSN=&&TEMP1,DISP=(OLD,PASS) //SORTOUT DD DSN=&&TEMP2,DISP=(NEW,PASS) //SYSIN DD * SORT FIELDS=(1,10,CH,A) /* //SYSOUT DD SYSOUT=* //* // IF (SORT.RC = 0) THEN //REPORT EXEC PGM=REPORTER //INPUT DD DSN=&&TEMP2,DISP=(OLD,PASS) //OUTPUT DD DSN=REPORT.DATA,DISP=(NEW,CATLG) //SYSPRINT DD SYSOUT=* // ENDIF //* // ELSE // IF (EXTRACT.RC < 12) THEN //RECOVERY EXEC PGM=RECOVER //INPUT DD DSN=BACKUP.DATA,DISP=SHR //OUTPUT DD DSN=REPORT.DATA,DISP=(NEW,CATLG) //SYSPRINT DD SYSOUT=* // ELSE //NOTIFY EXEC PGM=NOTIFY,PARM='CRITICAL FAILURE' //SYSPRINT DD SYSOUT=* // ENDIF // ENDIF //* //CLEANUP EXEC PGM=IEFBR14,COND=EVEN //TEMP1 DD DSN=&&TEMP1,DISP=(OLD,DELETE) //TEMP2 DD DSN=&&TEMP2,DISP=(OLD,DELETE)

Example 2 Explanation:

  • Normal processing flow: EXTRACT → SORT → REPORT
  • If EXTRACT returns RC=0 or RC=4, proceed to SORT
  • If SORT is successful (RC=0), proceed to REPORT
  • If EXTRACT has a moderate failure (RC between 5 and 11), RECOVERY runs
  • If EXTRACT has a severe failure (RC>=12), NOTIFY runs
  • CLEANUP runs in all cases (COND=EVEN ensures it runs even after abends)

Limitations and Considerations

While IF/THEN/ELSE structures are powerful, they have some limitations to be aware of:

1. No Support in Cataloged Procedures

IF/THEN/ELSE statements must be in the main JCL stream and cannot be placed within cataloged procedures.

2. Limited Comparison Capabilities

IF statements can only compare numeric values (return codes) and cannot directly compare strings or use complex expressions.

3. Statement Level Only

Conditional logic applies to entire JCL statements - you cannot conditionally specify individual parameters within a statement.

4. Version Compatibility

IF/THEN/ELSE structures are not available in older versions of JES. Check your system's compatibility before using.

5. Step Execution Order

All steps referenced in conditions must have executed previously in the job. Forward references are not allowed.

Best Practices

1. Use Clear Indentation

Indent your JCL consistently to clearly show the structure of nested IF/THEN/ELSE blocks. This makes the logic much easier to follow.

2. Add Comments

Include comments that explain the purpose of conditional blocks, especially for complex logic.

jcl
1
2
//* The following conditional block handles error recovery // IF (STEP1.RC > 4) THEN

3. Use Parentheses for Clarity

Even when not strictly required, use parentheses to make the order of operations clear in complex expressions.

4. Consider Readability vs. Complexity

For very complex logic, consider whether breaking the job into multiple simpler jobs might be more maintainable than creating deeply nested IF/THEN/ELSE structures.

5. Include Error Handling

Use conditional logic to gracefully handle errors and provide meaningful notifications or recovery steps.

Choosing Between COND and IF/THEN/ELSE

When deciding between COND parameters and IF/THEN/ELSE structures, consider these factors:

Use COND Parameter When:

  • You have simple conditional logic
  • You need backwards compatibility with older systems
  • You're coding steps within a procedure
  • You want more concise JCL
  • You specifically need "bypass if true" logic

Use IF/THEN/ELSE When:

  • You need complex conditional logic
  • You want to use logical operators (AND, OR)
  • You need to create nested conditions
  • You want more readable and intuitive JCL
  • You need to specify alternative execution paths

In many cases, you can use both COND parameters and IF/THEN/ELSE structures in the same job to take advantage of their respective strengths.

Practice Exercises

Test your understanding of IF/THEN/ELSE structures with these exercises:

Basic IF/THEN/ELSE Structure

Create a JCL job with three steps. Use an IF/THEN/ELSE statement to run PROGA if STEP1 has a return code of 0, otherwise run PROGB.

View Solution
jcl
1
2
3
4
5
6
7
8
9
10
11
//EXERJOB JOB (ACCT),'IF/THEN EXERCISE',CLASS=A //STEP1 EXEC PGM=MYPROG //SYSOUT DD SYSOUT=* //* // IF (STEP1.RC = 0) THEN //STEP2A EXEC PGM=PROGA //SYSOUT DD SYSOUT=* // ELSE //STEP2B EXEC PGM=PROGB //SYSOUT DD SYSOUT=* // ENDIF

Using Logical Operators

Create a JCL job that runs a step only if both STEP1 and STEP2 had a return code of 0 or 4.

View Solution
jcl
1
2
3
4
5
6
7
8
9
10
11
//EXERJOB JOB (ACCT),'LOGICAL OPS',CLASS=A //STEP1 EXEC PGM=MYPROG1 //SYSOUT DD SYSOUT=* //* //STEP2 EXEC PGM=MYPROG2 //SYSOUT DD SYSOUT=* //* // IF ((STEP1.RC LE 4) AND (STEP2.RC LE 4)) THEN //STEP3 EXEC PGM=MYPROG3 //SYSOUT DD SYSOUT=* // ENDIF

Nested IF/THEN/ELSE Statements

Create a JCL job with nested IF statements: If STEP1's return code is 0, run PROGA; if it's 4, run PROGB; otherwise, run PROGC.

View Solution
jcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//EXERJOB JOB (ACCT),'NESTED IF',CLASS=A //STEP1 EXEC PGM=MYPROG //SYSOUT DD SYSOUT=* //* // IF (STEP1.RC = 0) THEN //STEPA EXEC PGM=PROGA //SYSOUT DD SYSOUT=* // ELSE // IF (STEP1.RC = 4) THEN //STEPB EXEC PGM=PROGB //SYSOUT DD SYSOUT=* // ELSE //STEPC EXEC PGM=PROGC //SYSOUT DD SYSOUT=* // ENDIF // ENDIF

Frequently Asked Questions

What is the difference between COND parameter and IF/THEN/ELSE statements?+
The COND parameter uses a 'bypass if true' logic and combines conditions with OR logic, making it concise but sometimes counter-intuitive. IF/THEN/ELSE statements provide more readable and flexible conditional logic with both AND and OR operators, support for nested conditions, and a more intuitive 'execute if true' approach. IF/THEN/ELSE is typically used for complex conditions while COND is better for simple cases.
Can I nest IF/THEN/ELSE statements in JCL?+
Yes, JCL supports nested IF/THEN/ELSE structures. You can place an IF statement within the THEN or ELSE clause of another IF statement. Each nested IF must have its corresponding ENDIF statement. Nesting allows for more complex decision trees in your JCL, but be careful with indentation and commenting to maintain readability as nested conditions can quickly become complex.
How do I reference step return codes from previous jobs?+
Within a single job, you can reference step return codes using STEPNAME.RC. However, you cannot directly reference return codes from previous jobs in standard JCL. If you need to pass condition information between jobs, consider using either a return code dataset that stores values between jobs, a job scheduler with dependency capabilities (like CA7, Control-M), or implement a jobstream using REXX or other scripting to manage job dependencies.
What's the maximum complexity of conditions I can create in IF statements?+
JCL IF statements support fairly complex conditions with AND and OR operators, parentheses for grouping, and multiple comparisons. You can create conditions with multiple AND/OR operators and use nested IF statements for even more complex logic. However, for very complex logic, consider breaking the logic into multiple IF statements or using a preprocessing step with REXX or other scripting languages to determine execution paths.
Are there any limitations to IF/THEN/ELSE processing in JCL?+
Yes, there are several limitations: 1) IF/THEN/ELSE statements must be in the main JCL stream (not in cataloged procedures), 2) You cannot directly compare strings or use complex expressions - only numeric comparisons of return codes are supported, 3) Some JCL features cannot be used within conditional blocks in certain contexts, 4) IF/THEN/ELSE statements aren't available in older versions of JES, 5) You cannot use IF/THEN/ELSE to conditionally code specific DD parameters - the entire statement must be conditional.

Test Your Knowledge

1. Which statement marks the end of a conditional block in JCL?

  • END
  • ENDIF
  • ENDPROC
  • ENDBLOCK

2. Which of the following is a valid comparison operator in JCL IF statements?

  • EQU
  • ==
  • =
  • EQUALS

3. What logical operators are supported in JCL IF statements?

  • AND & OR only
  • AND, OR & NOT only
  • & and | only
  • AND & OR & XOR

4. How would you test if a step named STEP1 returned a code less than or equal to 4?

  • IF (STEP1.RC <= 4)
  • IF STEP1.RC LE 4
  • IF (STEP1.RC LE 4)
  • IF (STEP1.RC LEQ 4)

5. Which of the following statements would correctly test for a return code of 0 OR 4?

  • IF (RC = 0 OR RC = 4)
  • IF (RC = 0 | RC = 4)
  • IF (RC = 0 OR = 4)
  • IF (RC = 0 OR 4)

6. Which of the following is NOT a valid RC reference in JCL?

  • STEP1.RC
  • RC
  • MAXRC
  • LASTRC