Conditional Job Control Language (JCL) in z/VSE was a major step forward when it was introduced in the ’90s. In the intervening years, z/VSE systems programmers have developed intelligent, complex job streams. The design of conditional JCL was well done and highly functional with few restrictions of any consequence. There have been few requests for enhancements, indicating the initial designs were well-executed.
From day one, it was understood that using conditional JCL to control the execution of a job stream wouldn’t allow branching backward (previous JCL). Users accepted that restriction as reasonable. They realized that although it would be a nice feature, it would be difficult for developers to provide and would introduce the potential for an infinite loop in JCL streams. What follows are two techniques using existing conditional JCL to accomplish the effect of backward branching in JCL with a single, maintainable JCL stream and branching forward into another procedure.
Branch Backward in a Procedure
By definition, all // GOTO statements and conditional GOTOs search for the label after the initiated command. Occasionally, however, we find a situation where we really need to repeat a prior JCL step or two and then continue processing the job. Often, we cancel the job, then reinitiate a restart, which isn’t the cleanest solution.
So, let’s examine a solution that works today with the existing toolset on any z/VSE version delivered since the ’90s.
- Place the necessary label (/. LABEL) statements in the JCL for restart points where needed.
- Place the necessary logic in the JCL to determine when a condition exists for a branch back capability.
- Add a // SETPARM STEP=END as the next-to-last statement in the procedure. When the procedure fully completes correctly, all subsequent executions of this same procedure in the job will be bypassed. The last statement is a unique end label used to skip over the prior statement when the branch back is in force. When a branch back is needed, set the value of STEP to the branch back point and use the // GOTO or conditional GOTO to set up the branch back and to proceed to the last statement (/. END) of the procedure. The second execution of the same procedure will begin and use the value in STEP to continue the job where specified. You’re creating a simple logical branch back condition in the JCL, but not a physical return to prior JCL.
- Catalog the complete JCL, less any // JOB and /&, as a procedure. Make the first statement in the procedure a // GOTO &STEP. First execution and branch back executions will all use the procedure in Figure 1, so we must maintain only that procedure.
- Construct a job stream, setting the value of STEP for the initial procedure execution and execute the procedure at least twice. The procedure may be repeated twice or as many times as appropriate or needed using the same logic. When any one of the procedures completes without branch back, the rest will be skipped. If none complete correctly, the job stream will still reach the /&. There’s no chance of a continuous unintentional loop, since the reality is we’ll always be going forward physically, even when logically we’re branching back.
Defining STEP before procedure execution is necessary so the value will be passed to the procedure and, if changed, returned to JCL. The STEP on the execute procedure is also required to pass parameters into and out of the procedure (see Figure 2).
During the second procedure execution, if the same condition occurs again, you’re in a loop that will end with the second or last execution of the procedures. Hopefully, the second time through, the condition tested will be correct and the procedure will complete. The first procedure to complete correctly will cause the rest to be bypassed. In the example, we tested the value of STEP to determine if it was the second execution and proceeded to step 3.
To simplify DLBL/EXTENT/TLBL/ASSGN command processing, it may be best to group DLBL/EXTENT/TLBL/ASSGN statements after the JOB statement and before the PROC statement. It isn’t required that DLBL/EXTENT/TLBL/ASSGN statements be there, but it eliminates duplicate processing and may make the job easier to understand. Alternatively, having all labels in STDLABEL and the assigns permanently assigned at z/VSE or partition start-up is an excellent way to simplify.
If something needs to change in the procedure for the second or later execution, make it a variable and set the value between procedure executions with a SETPARM.