1. Stems — arrays no REXX

Um stem é uma variável com um ponto no nome — LISTA. — que funciona como array associativo. Por convenção, LISTA.0 guarda o número de elementos e LISTA.1, LISTA.2... guardam os valores:

/* Criar um stem manualmente */ FRUTAS.0 = 3 FRUTAS.1 = 'Maçã' FRUTAS.2 = 'Banana' FRUTAS.3 = 'Laranja' /* Percorrer o stem */ DO I = 1 TO FRUTAS.0 SAY I'.' FRUTAS.I END /* Construir stem dinamicamente (ex: capturando linhas) */ CONTADOR = 0 DO WHILE CONDITION CONTADOR = CONTADOR + 1 DADOS.CONTADOR = VALOR_ATUAL END DADOS.0 = CONTADOR

Stems também aceitam índices não numéricos — como chaves em um dicionário:

/* Stem com chave textual — como hashmap */ SALARIO.'MARIA' = 4500 SALARIO.'JOAO' = 3200 SALARIO.'ANA' = 5100 NOME = 'MARIA' SAY NOME'ganha' SALARIO.NOME /* Saída: MARIA ganha 4500 */

🦕 Analogia — Stems como tabelas do COBOL

No COBOL você usa OCCURS para criar arrays e acessa elementos com TABELA(I). No REXX, o stem TABELA.I faz o mesmo papel — mas sem declaração prévia, sem tamanho fixo, e aceitando índices de qualquer tipo. É mais próximo de um dicionário Python do que de um array Java.

2. PARSE — decompondo strings com templates

O PARSE é a instrução mais poderosa do REXX para extrair partes de uma string. Ele usa um template para descrever como dividir o texto:

/* PARSE VAR — decompor uma variável */ LINHA = 'CALCJOB JOB01234 OUTPUT 0000' /* Por espaços (cada palavra vai para uma variável) */ PARSE VAR LINHA JOBNOME JOBID STATUS RC_STEP SAY JOBNOME /* CALCJOB */ SAY JOBID /* JOB01234 */ SAY RC_STEP /* 0000 */ /* Por posição — extrai colunas fixas */ REGISTRO = 'MARIA SANTOS SP004500' PARSE VAR REGISTRO 1 NOME 11 SOBRENOME 21 UF 23 SALARIO SAY NOME /* MARIA */ SAY UF /* SP */ SAY SALARIO /* 004500 */
/* PARSE VALUE — decompor uma expressão */ PARSE VALUE DATE('S') WITH AAAA +4 MM +2 DD SAY 'Ano:' AAAA 'Mês:' MM 'Dia:' DD /* DATE('S') retorna '20260617' → AAAA=2026, MM=06, DD=17 */ /* PARSE com delimitador customizado */ CSV = 'MARIA,SANTOS,SP,4500' PARSE VAR CSV NOME ',' SOBRENOME ',' UF ',' SALARIO

3. Subrotinas — CALL, RETURN e PROCEDURE EXPOSE

Subrotinas organizam o código e evitam repetição. No REXX, subrotinas internas ficam após o corpo principal e são separadas por um label com dois pontos:

/* REXX - exemplo com subrotinas */ CALL ImprimirCabecalho 'RELATÓRIO MENSAL' CALL ProcessarDados EXIT 0 /* ── Subrotina sem isolamento de variáveis ── */ ImprimirCabecalho: PARSE ARG TITULO SAY CENTER(TITULO, 60, '=') RETURN /* ── Subrotina com PROCEDURE EXPOSE ── */ ProcessarDados: PROCEDURE EXPOSE DADOS. TOTAL /* Somente DADOS. e TOTAL são visíveis aqui. Outras variáveis do chamador não existem neste escopo. */ DO I = 1 TO DADOS.0 TOTAL = TOTAL + DADOS.I END RETURN

💡 PROCEDURE EXPOSE — escopo explícito

Sem PROCEDURE, a subrotina compartilha todas as variáveis com o chamador (como parágrafos do COBOL). Com PROCEDURE, as variáveis ficam isoladas — a subrotina não enxerga nada do chamador. Com PROCEDURE EXPOSE você declara explicitamente quais variáveis quer compartilhar. Use PROCEDURE EXPOSE para evitar efeitos colaterais acidentais em execs grandes.

Funções que retornam valor

/* Subrotina que retorna valor — chamada como função */ RESULTADO = Dobrar(21) SAY RESULTADO /* 42 */ EXIT 0 Dobrar: PROCEDURE PARSE ARG N RETURN N * 2

4. SIGNAL ON — tratamento de erros

O SIGNAL ON configura handlers para diferentes tipos de condição de erro. Quando a condição ocorre, o REXX desvia para o label correspondente:

/* Configurar handlers antes de começar */ SIGNAL ON ERROR NAME TratarErro SIGNAL ON SYNTAX NAME TratarSintaxe SIGNAL ON HALT NAME TratarHalt /* Código principal */ ADDRESS TSO 'LISTDS DATASET.INEXISTENTE' IF RC \= 0 THEN SIGNAL TratarErro SAY 'Processamento concluído' EXIT 0 /* ── Handlers ── */ TratarErro: SAY 'ERRO detectado na linha' SIGL SAY 'RC do último comando:' RC SAY 'Condição:' CONDITION('C') EXIT 12 TratarSintaxe: SAY 'ERRO DE SINTAXE na linha' SIGL SAY ERRORTEXT(RC) EXIT 16 TratarHalt: SAY 'Exec interrompido pelo usuário' EXIT 4

Variáveis especiais disponíveis nos handlers:

VariávelConteúdo
SIGLNúmero da linha que causou o erro
RCReturn code do comando ou condição
CONDITION('C')Nome da condição (ERROR, SYNTAX...)
CONDITION('D')Descrição da condição
ERRORTEXT(n)Texto do erro REXX número n

5. TRACE — depurando execs

O TRACE é o depurador built-in do REXX. Ele exibe cada instrução antes de executar e mostra os valores intermediários — invaluable quando um exec não está se comportando como esperado:

/* Ativar trace de resultados */ TRACE R /* R = Results: mostra instrução + valor resultante */ A = 10 B = A * 3 SAY B /* Saída do trace: 3 *-* A = 10 >>> 10 4 *-* B = A * 3 >>> 30 5 *-* SAY B 30 */ /* Desativar trace */ TRACE O /* O = Off */
OpçãoO que mostra
TRACE RInstrução + valor resultante de cada expressão
TRACE ITudo — cada token intermediário (muito verboso)
TRACE CSó comandos enviados para o ambiente (ADDRESS TSO...)
TRACE ESó erros — útil em produção para log mínimo
TRACE OOff — desativa trace

6. Exemplo completo — script de inventário

Um exec que captura a lista de datasets de um usuário, filtra os maiores que um threshold e gera um relatório:

/* REXX - Inventário de datasets por usuário */ ARG PREFIXO THRESHOLD IF PREFIXO = '' THEN PREFIXO = 'USUARIO' IF THRESHOLD = '' THEN THRESHOLD = 80 SIGNAL ON ERROR NAME FimComErro /* Capturar lista de datasets */ CALL OUTTRAP 'SAIDA.' ADDRESS TSO 'LISTCAT LEVEL('PREFIXO') ALL' CALL OUTTRAP 'OFF' /* Imprimir cabeçalho */ SAY CENTER('DATASETS ACIMA DE 'THRESHOLD'% DE USO', 60, '=') SAY LEFT('DATASET', 44) RIGHT('%USO', 6) SAY COPIES('-', 50) ENCONTRADOS = 0 DO I = 1 TO SAIDA.0 IF POS('NONVSAM', SAIDA.I) > 0 THEN DO PARSE VAR SAIDA.I . '-' DSN . DSN = STRIP(DSN) R = LISTDSI("'"DSN"'") IF SYSUSED >= THRESHOLD THEN DO SAY LEFT(DSN, 44) RIGHT(SYSUSED'%', 6) ENCONTRADOS = ENCONTRADOS + 1 END END END SAY COPIES('-', 50) SAY ENCONTRADOS 'dataset(s) precisam de atenção.' EXIT 0 FimComErro: SAY 'Erro na linha' SIGL'. RC='RC EXIT 12