1. O que é uma Procedure

Uma Procedure JCL é um bloco nomeado de statements JCL (um ou mais steps) que pode ser chamado e reutilizado por vários jobs. Em vez de repetir os mesmos 30 linhas de JCL em cada job, você define a procedure uma vez e a chama com EXEC PROC=nome.

🦕 Analogia — procedure é como uma receita de bolo

Uma receita de bolo de chocolate está escrita no caderno da vovó. Qualquer pessoa da família pode fazer o bolo seguindo a receita — e pode customizar substituindo o chocolate amargo por ao leite (override de parâmetro). A receita não muda, só o ingrediente passado muda. É exatamente isso: a procedure é a receita, e você passa os ingredientes via parâmetros simbólicos.

2. Instream Procedure

Definida dentro do próprio job, antes do primeiro //nome JOB... espera, na verdade instream procedures ficam depois do JOB card e antes dos steps que a chamam, delimitadas por PROC e PEND.

JCLInstream procedure — definição e chamada
//MEUJOB  JOB  ACCT,'LADY COBOL',CLASS=A,MSGCLASS=X

//*--------------------------------------------------------*
//* Definição da instream procedure COPIAPROC              *
//*--------------------------------------------------------*
//COPIAPROC PROC  DSN1=PADRAO.ENTRADA,       * param com default
//                DSN2=PADRAO.SAIDA

//COPYSTEP EXEC  PGM=IEBGENER
//SYSUT1   DD  DSN=&DSN1,DISP=SHR          * usa o parametro
//SYSUT2   DD  DSN=&DSN2,
//              DISP=(NEW,CATLG,DELETE),
//              UNIT=SYSDA,SPACE=(TRK,(5,2)),
//              LIKE=&DSN1
//SYSIN    DD  DUMMY
//SYSPRINT DD  SYSOUT=*

//         PEND     * fim da definição da procedure

//*--------------------------------------------------------*
//* Chamadas à procedure com parâmetros diferentes         *
//*--------------------------------------------------------*
//EXEC01  EXEC  COPIAPROC,
//              DSN1=PROD.FUNC.JAN,
//              DSN2=BKUP.FUNC.JAN

//EXEC02  EXEC  COPIAPROC,
//              DSN1=PROD.FUNC.FEV,
//              DSN2=BKUP.FUNC.FEV

✅ Quando usar instream procedure

Use quando a procedure é específica para aquele job e não precisa ser compartilhada com outros jobs. São boas para testes ou para encapsular lógica de steps repetidos dentro de um mesmo job longo.

3. Cataloged Procedure

Armazenada permanentemente em um PROCLIB (biblioteca de procedures) — geralmente SYS1.PROCLIB ou uma biblioteca do site. Qualquer job pode chamar sem precisar definir a procedure localmente.

JCLChamando uma cataloged procedure
//MEUJOB  JOB  ACCT,'LADY COBOL',CLASS=A,MSGCLASS=X

//* Chama a proc COBUCL (compilacao COBOL catalogada)
//COMPILE  EXEC  COBUCL,
//               MEMBER=CALCFOL,        * nome do fonte
//               SRCLIB=LC001.COBOL.SRC  * biblioteca do fonte
//

💗 Como descobrir quais procedures existem no site

No ISPF, use o comando ISRDDN ou pesquise nos datasets da JCLLIB/PROCLIB. Muitos sites também têm documentação interna listando as procedures disponíveis e seus parâmetros. Outra forma: se você tiver o nome, use EDIT 'SYS1.PROCLIB(NOMEPROC)' para ler o fonte da procedure.

4. Parâmetros simbólicos

Parâmetros simbólicos são variáveis dentro da procedure, indicadas com &. Você define os defaults no PROC e sobrescreve na chamada.

OndeSintaxeExemplo
Definição (padrão)//nome PROC SYM=valor-default//MINHA PROC ENV=PROD,MES=202412
Uso dentro da proc&SIMBOLO ou &&SIMBOLODSN=&ENV..FUNC.&MES
Na chamadaEXEC NOMPROC,SYM=valorEXEC MINHA,ENV=TEST,MES=202411

⚠️ &SIM vs. &SIM.. — os dois pontos importam

Quando o símbolo é seguido imediatamente por letras ou números (sem separador), você precisa de dois pontos para delimitar o nome: &ENV..DADOS significa o valor de ENV seguido de ".DADOS". Sem os pontos duplos, o sistema tentaria interpretar "ENVDADOS" como um único símbolo. Isso é um dos erros mais comuns ao escrever procedures.

JCLProcedure com parâmetros simbólicos
//* Definição da procedure no PROCLIB
//PROCFOL  PROC  ENV=PROD,              * ambiente: PROD ou TEST
//               MES=202412,            * mes de referencia
//               REGIAO=128M           * regiao de memoria

//CALCSTEP EXEC  PGM=CALCFOL,PARM='&MES',
//               REGION=&REGIAO

//STEPLIB  DD  DSN=&ENV..LOAD.LIB,DISP=SHR
*                  ^-- ENV + ".LOAD.LIB" = PROD.LOAD.LIB ou TEST.LOAD.LIB

//ENTRADA  DD  DSN=&ENV..FUNC.&MES,DISP=SHR
*                  ^-- PROD.FUNC.202412 ou TEST.FUNC.202411

//SYSOUT   DD  SYSOUT=*
//         PEND

//*-- Chamada em producao (usa defaults)
//RODAR    EXEC  PROCFOL

//*-- Chamada em teste com outro mes
//TESTAR   EXEC  PROCFOL,
//               ENV=TEST,
//               MES=202411

5. Override de DDs e parâmetros

Mesmo após chamar uma procedure, você pode sobrescrever DDs específicos adicionando um DD com o mesmo nome após o EXEC. A sintaxe usa stepname.ddname:

JCLOverride de DD após chamar procedure
//MEUJOB  JOB  ACCT,'LADY COBOL',CLASS=A,MSGCLASS=X

//EXECPROC EXEC  PROCFOL,ENV=TEST

//* Override: substitui o DD ENTRADA definido na proc
//* Formato: //stepname.ddname DD ...
//CALCSTEP.ENTRADA DD  DSN=TEST.FUNC.ESPECIAL,DISP=SHR

//* Override: redireciona SYSOUT para arquivo em vez de spool
//CALCSTEP.SYSOUT  DD  DSN=TEST.SAIDA.LOG,
//                      DISP=(NEW,CATLG,DELETE),
//                      UNIT=SYSDA,SPACE=(TRK,(2,1))
//

6. Procedures aninhadas

É possível chamar uma procedure a partir de outra (nesting), mas com uma limitação importante: no máximo 2 níveis de aninhamento (uma procedure chamando outra, mas não uma terceira dentro da segunda).

⚠️ Instream procedures não podem ser aninhadas

Apenas Cataloged Procedures podem ser aninhadas. Tentar aninhar uma instream procedure causa erro de JCL. Em ambientes complexos, a abordagem mais limpa é ter procedures catalogadas bem projetadas com parâmetros simbólicos em vez de aninhar profundamente.

7. Exemplo real: proc de compilação COBOL

Veja uma procedure completa de compilação COBOL, semelhante ao que você encontraria em ambientes reais:

JCLCOBCOMP — procedure de compilação COBOL
//*============================================================*
//* PROC : COBCOMP                                             *
//* DESCR: Compila um programa COBOL e gera o objeto           *
//* PARAM: SRCLIB  = biblioteca de fontes COBOL                *
//*        MEMBER  = nome do membro a compilar                 *
//*        LOADLIB = biblioteca de destino do objeto           *
//*============================================================*
//COBCOMP  PROC
//              SRCLIB=PROD.COBOL.SOURCE,
//              MEMBER=PROGRAMA,
//              LOADLIB=PROD.LOAD.LIB,
//              REGION=0M

//* Step 1: Compilacao
//COMPILE  EXEC  PGM=IGYCRCTL,REGION=&REGION
//STEPLIB  DD  DSN=IGY.V6R4M0.SIGYCOMP,DISP=SHR
//SYSIN    DD  DSN=&SRCLIB(&MEMBER),DISP=SHR
//SYSLIN   DD  DSN=&&OBJETO,DISP=(NEW,PASS),
//              UNIT=SYSDA,SPACE=(TRK,(10,5))
//SYSPRINT DD  SYSOUT=*
//SYSUT1   DD  UNIT=SYSDA,SPACE=(CYL,(3,1))
//SYSUT2   DD  UNIT=SYSDA,SPACE=(CYL,(3,1))
//SYSUT3   DD  UNIT=SYSDA,SPACE=(CYL,(3,1))
//SYSUT4   DD  UNIT=SYSDA,SPACE=(CYL,(3,1))

//* Step 2: Link-Edit (so roda se compilacao ok)
//         IF (COMPILE.RC <= 4) THEN
//LKED     EXEC  PGM=IEWL,REGION=0M
//SYSLIN   DD  DSN=&&OBJETO,DISP=(OLD,DELETE)
//         DD  DSN=CEE.SCEELKED,DISP=SHR         * runtime LE
//SYSLMOD  DD  DSN=&LOADLIB(&MEMBER),DISP=SHR
//SYSPRINT DD  SYSOUT=*
//         ENDIF

//         PEND   * fim da procedure COBCOMP

Chamando a procedure no job

JCLJob que usa a procedure COBCOMP
//COMPJOB  JOB  ACCT,'LADY COBOL',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID

//* Compila CALCFOL da library de desenvolvimento
//STEP01   EXEC  COBCOMP,
//               SRCLIB=LC001.COBOL.SOURCE,
//               MEMBER=CALCFOL,
//               LOADLIB=LC001.LOAD.LIB

//* Compila RELAT-MES com defaults da proc
//STEP02   EXEC  COBCOMP,
//               MEMBER=RELATMES    * so sobrescreve o MEMBER
//

🟣 JCLLIB — onde o JES procura as procedures

Por padrão, o JES procura procedures no SYS1.PROCLIB e outras bibliotecas configuradas no sistema. Você pode adicionar suas próprias bibliotecas usando o statement JCLLIB ORDER= antes do primeiro EXEC:

//MYLIBS JCLLIB ORDER=(MINHA.PROCLIB,SYS1.PROCLIB)

Isso é útil para trabalhar com procedures em desenvolvimento antes de movê-las para a biblioteca oficial de produção.