1. Return Codes — o que são

Quando um step termina, ele retorna um Return Code (RC) — um número inteiro de 0 a 4095 que indica o resultado da execução. Os valores mais comuns por convenção:

RCSignificado convencional
0Sucesso total — tudo certo
4Sucesso com avisos — processou, mas com alguma advertência
8Erro — processou com erros, resultado pode ser inválido
12Erro grave — processamento abortado internamente
16Erro fatal — não processou

🦕 Analogia — RC é como a nota de uma prova

O RC é a "nota" que o programa dá para si mesmo ao terminar. RC=0 é 10 (perfeito), RC=4 é 7 (passou, mas com ressalvas), RC=8 é 4 (reprovado). O JCL pode olhar essa nota e decidir: "se o step anterior tirou menos que 5, não deixo o próximo step rodar".

✅ Utilitários IBM têm convenção própria

DFSORT retorna RC=0 (ok) ou RC=16 (erro grave). IDCAMS retorna RC=0, 4, 8 ou 12. O compilador COBOL (IGYCRCTL) retorna RC=0 (sem erros), RC=4 (warnings), RC=8 (erros de compilação), RC=12 (erros severos). Sempre verifique a documentação do utilitário que você está usando.

2. Setando RC no programa COBOL

Seu programa COBOL pode definir o Return Code que o job vai receber através do campo especial RETURN-CODE na WORKING-STORAGE:

COBOLDefinindo Return Code no programa
       WORKING-STORAGE SECTION.
       01  WS-STATUS-PROC    PIC X(01).
           88  PROC-OK       VALUE 'S'.
           88  PROC-ERRO     VALUE 'E'.

       PROCEDURE DIVISION.
       0000-INICIO.
           PERFORM 2000-PROCESSAR

           IF PROC-OK
               MOVE 0  TO RETURN-CODE   * RC=0: tudo ok
           ELSE
               MOVE 8  TO RETURN-CODE   * RC=8: houve erros
           END-IF
           STOP RUN.

3. IF/THEN/ELSE/ENDIF no JCL

Introduzido no z/OS moderno, é a forma recomendada para controle de fluxo. Muito mais legível que o COND antigo.

JCLSintaxe do IF/THEN/ELSE/ENDIF
//         IF (condição) THEN
//stepname   EXEC  PGM=programa   * executado se condição TRUE
//         ELSE
//stepname   EXEC  PGM=outro       * executado se condição FALSE
//         ENDIF

💗 O IF do JCL não executa código — ele executa STEPs

Cuidado com a analogia com o IF do COBOL. No JCL, o IF não executa uma instrução — ele decide se um step inteiro (EXEC) vai rodar ou não. O bloco IF..ENDIF pode conter vários steps, todos condicionados ao mesmo teste.

4. Operadores de comparação

A condição do IF testa o RC do step indicado:

ExpressãoAlternativa simbólicaSignificado
RC = 0RC EQ 0RC igual a 0
RC > 0RC GT 0RC maior que 0
RC >= 4RC GE 4RC maior ou igual a 4
RC < 8RC LT 8RC menor que 8
RC <= 4RC LE 4RC menor ou igual a 4
RC ¬= 0RC NE 0RC diferente de 0
ABENDStep terminou com abend
RUNStep foi executado
JCLIF/THEN/ELSE — exemplos práticos
//MEUJOB  JOB  ACCT,'LADY COBOL',CLASS=A,MSGCLASS=X

//* Step 1: compila o programa
//COMPILE  EXEC  PGM=IGYCRCTL
//SYSPRINT DD  SYSOUT=*
//SYSIN    DD  DSN=LC001.COBOL.SOURCE(CALCFOL),DISP=SHR
//* ... outros DDs da compilacao

//* Se a compilacao ok (RC <= 4): faz o link e executa
//         IF (COMPILE.RC <= 4) THEN

//LKED     EXEC  PGM=IEWL
//* ... DDs do linkedit

//EXEC     EXEC  PGM=CALCFOL
//* ... DDs do programa

//         ELSE

//* Se compilacao falhou: gera aviso
//ERRO     EXEC  PGM=IEFBR14
//SYSOUT   DD  SYSOUT=*

//         ENDIF

Testando múltiplos steps e usando AND/OR

JCLCondições compostas
//* Executa STEP03 somente se STEP01 e STEP02 deram RC=0
//         IF (STEP01.RC = 0 AND STEP02.RC = 0) THEN
//STEP03   EXEC  PGM=MEUPGM
//         ENDIF

//* Executa limpeza se qualquer step teve abend
//         IF (STEP01.ABEND OR STEP02.ABEND) THEN
//LIMPEZA  EXEC  PGM=IEFBR14
//         ENDIF

5. Parâmetro COND (legado)

O COND é o mecanismo antigo, ainda muito presente em código legado. A lógica é invertida e confunde muita gente: a condição do COND é o que faz o step ser pulado — não o que faz ele rodar.

⚠️ A lógica invertida do COND

COND=(0,NE) parece dizer "execute se RC diferente de 0", mas na verdade diz:
"PULE este step se o RC de qualquer step anterior for diferente de 0"

Ou seja: execute APENAS se todos os steps anteriores tiverem RC=0. É exatamente o oposto do que a expressão sugere. Por isso o IF/THEN/ELSE foi criado — é muito mais legível. Prefira sempre o IF.

JCLCOND — sintaxe e lógica
* COND=(valor, operador) — pula o step SE a condição for TRUE
//STEP02  EXEC  PGM=PROG2,COND=(0,NE)
* "Pule STEP02 se qualquer RC anterior for NE (diferente) de 0"
* = execute STEP02 apenas se todos anteriores tiveram RC=0

* Testar RC de um step especifico
//STEP03  EXEC  PGM=PROG3,COND=(4,LT,STEP01)
* "Pule STEP03 se RC do STEP01 for LT (menor) que 4"
* = execute STEP03 apenas se STEP01 tiver RC >= 4

6. COND=EVEN e COND=ONLY

Dois valores especiais do COND que controlam steps de limpeza e tratamento de erro:

ValorComportamentoUso típico
COND=EVENExecuta este step mesmo se steps anteriores sofreram abendSteps de limpeza que devem rodar sempre
COND=ONLYExecuta este step SOMENTE se um step anterior sofreu abendSteps de tratamento de erro
JCLCOND=EVEN e COND=ONLY
//STEP01   EXEC  PGM=MEUPROG
//* ... DDs

//* Roda SEMPRE, mesmo se STEP01 abendou — faz limpeza
//LIMPEZA  EXEC  PGM=IEFBR14,COND=EVEN
//DSWORK   DD  DSN=PROD.WORK.TEMP,DISP=(OLD,DELETE)

//* Roda SOMENTE se houve abend — envia alerta
//ALERT    EXEC  PGM=SENDMAIL,COND=ONLY
//SYSOUT   DD  SYSOUT=*

7. Cenários práticos completos

Cenário 1 — Pipeline de compilação, link e execução

JCLCompile-Link-Go com IF
//CLGJOB   JOB  ACCT,'LADY COBOL',CLASS=A,MSGCLASS=X

//* STEP1: Compilacao
//COMPILE  EXEC  PGM=IGYCRCTL,REGION=0M
//STEPLIB  DD  DSN=IGY.V6R4M0.SIGYCOMP,DISP=SHR
//SYSIN    DD  DSN=LC001.COBOL.SRC(CALCFOL),DISP=SHR
//SYSLIN   DD  DSN=&&OBJETO,DISP=(NEW,PASS),
//              UNIT=SYSDA,SPACE=(TRK,(5,2))
//SYSPRINT DD  SYSOUT=*
//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(1,1))

//* Se compilacao ok, faz link-edit e executa
//         IF (COMPILE.RC <= 4) THEN

//* STEP2: Link-Edit
//LKED     EXEC  PGM=IEWL,REGION=0M
//SYSLIN   DD  DSN=&&OBJETO,DISP=(OLD,DELETE)
//SYSLMOD  DD  DSN=LC001.LOAD.LIB(CALCFOL),DISP=SHR
//SYSPRINT DD  SYSOUT=*

//* STEP3: Execucao
//EXEC     EXEC  PGM=CALCFOL
//STEPLIB  DD  DSN=LC001.LOAD.LIB,DISP=SHR
//ENTRADA  DD  DSN=PROD.FUNC.DADOS,DISP=SHR
//SYSOUT   DD  SYSOUT=*

//         ENDIF
//

🟣 IF aninhado — cuidado com a indentação

O JCL permite IFs aninhados (IF dentro de IF), mas a indentação não é obrigatória — o sistema não se importa com espaços extras. Em jobs complexos, é tentador encadear muitos IFs, mas isso torna o JCL difícil de manter. Uma alternativa melhor é usar Procedures com parâmetros simbólicos para encapsular a lógica de steps e manter o JCL principal limpo.