Translate

Mostrar mensagens com a etiqueta Linkage. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Linkage. Mostrar todas as mensagens

sexta-feira, 22 de novembro de 2019

Data Division : Quando um Programador Descobre que Cada Byte Deixa uma Impressão Digital — e que a Cena do Crime Começa Antes da PROCEDURE DIVISION

 

Bellacosa Mainframe apresenta a Data Division no COBOL

☕ Um Café no Bellacosa Mainframe

Data Division sem Mistérios para Programadores COBOL

Quando um Programador Descobre que Cada Byte Deixa uma Impressão Digital — e que a Cena do Crime Começa Antes da PROCEDURE DIVISION

Nova York, 02h17 da manhã.

A chuva escorre pelas paredes de vidro do laboratório forense enquanto os reflexos azuis das viaturas atravessam a sala. Sobre uma bancada de aço inoxidável existe algo aparentemente simples: um programa COBOL encontrado em produção depois de um processamento noturno terminar com dados inconsistentes.

Nenhum cadáver.

Nenhuma arma.

Nenhuma testemunha disposta a falar.

Apenas milhões de bytes, um arquivo sequencial, algumas áreas de memória e um saldo bancário que apareceu negativo onde jamais deveria existir um valor menor que zero.

O programador iniciante olha para o código e afirma:

— O problema deve estar na PROCEDURE DIVISION.

O investigador veterano do mainframe coloca as luvas, aproxima-se do terminal 3270 e responde:

— Esse é o primeiro erro de quem ainda não aprendeu a investigar sistemas legados. A lógica pode executar o crime, mas é na DATA DIVISION que encontramos as impressões digitais.

Bem-vindo ao laboratório forense do Bellacosa Mainframe.

Hoje não examinaremos sangue, fibras, pólvora ou DNA. Examinaremos registros, campos, buffers, parâmetros, tabelas, condições, formatos numéricos e áreas de armazenamento.

Porque, em COBOL, nenhum byte desaparece sem deixar vestígios.


Bellacosa Mainframe em DATA DIVISION em destaque

A cena do crime: o que é a DATA DIVISION?

Um programa COBOL tradicional costuma ser organizado em grandes divisões:

       IDENTIFICATION DIVISION.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       PROCEDURE DIVISION.

A IDENTIFICATION DIVISION identifica o programa.

A ENVIRONMENT DIVISION descreve aspectos do ambiente onde ele será executado.

A DATA DIVISION define os dados utilizados pelo programa.

A PROCEDURE DIVISION contém as instruções que manipulam esses dados.

Uma comparação simples seria:

DivisãoFunção
IDENTIFICATION DIVISIONIdentificação do caso
ENVIRONMENT DIVISIONDescrição da cena
DATA DIVISIONCatálogo de evidências
PROCEDURE DIVISIONReconstrução dos acontecimentos

Muitos iniciantes resumem a Data Division como “o lugar onde declaramos variáveis”.

Isso está correto, mas é incompleto.

A Data Division não apenas declara variáveis. Ela especifica:

  • o tamanho de cada campo;

  • o formato dos dados;

  • a representação física em memória;

  • a hierarquia entre campos;

  • o tempo de vida das informações;

  • a origem dos dados;

  • a forma de compartilhamento entre programas;

  • a organização de registros em arquivos;

  • as áreas utilizadas como entrada e saída;

  • as diferentes interpretações possíveis para os mesmos bytes.

É quase como se cada campo viesse acompanhado de uma ficha criminal completa.

       05 WS-SALDO PIC S9(7)V99 COMP-3.

Esta linha não diz apenas que existe um saldo.

Ela revela que:

  • o campo é numérico;

  • aceita sinal;

  • possui sete posições inteiras;

  • possui duas posições decimais implícitas;

  • utiliza formato decimal compactado;

  • ocupa uma quantidade específica de bytes;

  • precisa ser manipulado respeitando sua representação interna.

O compilador utiliza essa descrição para gerar as instruções adequadas.

Portanto, a Data Division é um contrato de memória.


O laboratório possui diferentes salas

A Data Division pode conter várias seções:

       DATA DIVISION.

       FILE SECTION.

       WORKING-STORAGE SECTION.

       LOCAL-STORAGE SECTION.

       LINKAGE SECTION.

       SCREEN SECTION.

       REPORT SECTION.

Nem todas precisam aparecer no mesmo programa.

Em sistemas corporativos atuais, as mais frequentes são:

  • FILE SECTION;

  • WORKING-STORAGE SECTION;

  • LINKAGE SECTION.

A LOCAL-STORAGE SECTION também é muito importante em programas reutilizáveis e reentrantes.

SCREEN SECTION e REPORT SECTION são mais específicas e hoje aparecem com menor frequência em ambientes IBM z/OS tradicionais.

Vamos entrar em cada sala do laboratório.


FILE SECTION: o depósito de evidências externas

A FILE SECTION descreve os registros dos arquivos utilizados pelo programa.

Um detalhe crucial: ela não armazena o arquivo inteiro na memória.

Ela normalmente representa uma área onde um registro é disponibilizado a cada operação de leitura ou gravação.

Considere o seguinte arquivo de clientes:

00001JOAO DA SILVA                 00000150000
00002MARIA OLIVEIRA                00000275050
00003PEDRO SANTOS                  00000098075

Um arquivo pode possuir milhões de registros. O programa não precisa carregar todos de uma vez.

Na FILE SECTION, descrevemos o formato de um registro:

       FILE SECTION.

       FD  ARQ-CLIENTES.

       01  REG-CLIENTE.
           05 REG-CODIGO       PIC 9(5).
           05 REG-NOME         PIC X(30).
           05 REG-SALDO        PIC 9(9)V99.

O FD significa File Description.

Ele introduz a descrição lógica do arquivo.

       FD ARQ-CLIENTES.

Logo abaixo aparece o registro:

       01 REG-CLIENTE.

Quando o programa executa:

       READ ARQ-CLIENTES

o próximo registro disponível é colocado na área associada ao arquivo.

Em termos simplificados:

Arquivo em disco
      |
      v
Sistema de arquivos
      |
      v
Buffer de entrada
      |
      v
REG-CLIENTE

Depois, o programa pode examinar os campos:

       DISPLAY REG-CODIGO
       DISPLAY REG-NOME
       DISPLAY REG-SALDO

Uma correção importante sobre a imagem

Na imagem apresentada, a File Section aparece relacionada a “variáveis temporárias”. Isso pode causar confusão.

A FILE SECTION não é normalmente utilizada como área genérica de variáveis temporárias. Sua função principal é descrever registros associados a arquivos.

As variáveis temporárias ficam geralmente na WORKING-STORAGE SECTION ou na LOCAL-STORAGE SECTION.

Em uma investigação técnica, essa distinção é importante. Colocar a etiqueta errada em uma evidência pode comprometer todo o caso.


O arquivo não existe sozinho: SELECT e FD

Em muitos programas, a declaração do arquivo possui duas partes.

Na ENVIRONMENT DIVISION, encontramos o SELECT:

       ENVIRONMENT DIVISION.

       INPUT-OUTPUT SECTION.

       FILE-CONTROL.

           SELECT ARQ-CLIENTES
               ASSIGN TO CLIENTES
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-FILE-STATUS.

Na DATA DIVISION, encontramos o FD:

       FILE SECTION.

       FD  ARQ-CLIENTES.

       01  REG-CLIENTE.
           05 REG-CODIGO       PIC 9(5).
           05 REG-NOME         PIC X(30).
           05 REG-SALDO        PIC 9(9)V99.

O SELECT descreve a relação lógica com o ambiente.

O FD descreve o registro.

É como se o SELECT informasse onde a evidência foi encontrada, enquanto o FD explicasse sua estrutura física.


FILE STATUS: o laudo que muitos esquecem de consultar

Um programa robusto não deve assumir que toda operação de arquivo funcionará corretamente.

Por isso utilizamos:

       FILE STATUS IS WS-FILE-STATUS

E declaramos:

       01 WS-FILE-STATUS       PIC XX.

Após um OPEN, READ, WRITE, REWRITE, DELETE ou CLOSE, o campo pode indicar o resultado da operação.

Exemplo:

       READ ARQ-CLIENTES
           AT END
               SET FIM-ARQUIVO TO TRUE
       END-READ

Ou:

       IF WS-FILE-STATUS NOT = '00'
           DISPLAY 'ERRO DE ARQUIVO: ' WS-FILE-STATUS
       END-IF

O valor 00 normalmente representa sucesso.

Mas atenção: os significados exatos podem variar conforme a operação e a organização do arquivo.

Uma boa prática é nunca tratar o status de arquivo como um detalhe decorativo.

Um READ malsucedido não é silêncio. É uma testemunha tentando falar.


WORKING-STORAGE SECTION: a sala central do laboratório

A WORKING-STORAGE SECTION é uma das áreas mais utilizadas em programas COBOL.

Ela contém dados que geralmente existem durante toda a execução da unidade de programa.

       WORKING-STORAGE SECTION.

       01 WS-CONTADOR          PIC 9(5) VALUE ZERO.
       01 WS-TOTAL             PIC S9(9)V99 COMP-3 VALUE ZERO.
       01 WS-FIM-ARQUIVO       PIC X VALUE 'N'.

Enquanto o programa estiver ativo, essas áreas permanecem disponíveis.

Podemos utilizar a Working-Storage para:

  • contadores;

  • acumuladores;

  • flags;

  • mensagens;

  • campos auxiliares;

  • datas;

  • áreas de entrada e saída;

  • tabelas;

  • constantes;

  • códigos de retorno;

  • estruturas temporárias;

  • copybooks;

  • campos utilizados em cálculos.

Contador

       01 WS-QTD-CLIENTES      PIC 9(7) VALUE ZERO.

Uso:

       ADD 1 TO WS-QTD-CLIENTES

Acumulador

       01 WS-TOTAL-SALDOS      PIC S9(11)V99 COMP-3
                               VALUE ZERO.

Uso:

       ADD REG-SALDO TO WS-TOTAL-SALDOS

Flag

       01 WS-FIM-ARQUIVO       PIC X VALUE 'N'.

Uso:

       IF WS-FIM-ARQUIVO = 'S'
           DISPLAY 'PROCESSAMENTO ENCERRADO'
       END-IF

Funciona, mas pode ser melhorado com nível 88.


Nível 88: o testemunho semântico

O nível 88 não reserva uma nova área de memória.

Ele fornece nomes significativos para valores ou condições de outro campo.

       01 WS-FIM-ARQUIVO       PIC X VALUE 'N'.
           88 FIM-ARQUIVO      VALUE 'S'.
           88 NAO-FIM-ARQUIVO  VALUE 'N'.

Agora podemos escrever:

       SET FIM-ARQUIVO TO TRUE

E testar:

       PERFORM UNTIL FIM-ARQUIVO

Isso é muito mais expressivo do que:

       PERFORM UNTIL WS-FIM-ARQUIVO = 'S'

Os dois funcionam, mas o nível 88 aproxima o código da linguagem do negócio.

Outro exemplo:

       01 WS-TIPO-CLIENTE      PIC X.
           88 CLIENTE-COMUM    VALUE 'C'.
           88 CLIENTE-VIP      VALUE 'V'.
           88 CLIENTE-BLOQUEADO VALUE 'B'.

Uso:

       IF CLIENTE-BLOQUEADO
           DISPLAY 'OPERACAO NAO AUTORIZADA'
       END-IF

O nível 88 é como uma legenda pericial: ele transforma valores brutos em significados compreensíveis.


VALUE: o estado inicial da evidência

A cláusula VALUE define um conteúdo inicial.

       01 WS-CONTADOR          PIC 9(5) VALUE ZERO.
       01 WS-MENSAGEM          PIC X(30)
                               VALUE 'INICIO DO PROCESSAMENTO'.
       01 WS-STATUS            PIC X VALUE 'A'.

Sem uma inicialização adequada, o programa pode trabalhar com conteúdo inesperado.

Em muitos ambientes, determinadas áreas podem receber valores previsíveis conforme o compilador, o runtime e a forma de carregamento. Porém, um programa profissional não deve depender de suposições frágeis.

Sempre que o valor inicial for importante, declare-o ou inicialize-o explicitamente.

       INITIALIZE WS-AREA-TRABALHO

Mas investigue o uso de INITIALIZE com cuidado: ele não é necessariamente equivalente a mover espaços ou zeros para todos os campos indiscriminadamente. Seu comportamento respeita as categorias dos itens e pode ser alterado com cláusulas adicionais.


LOCAL-STORAGE SECTION: cada chamada recebe uma cena isolada

A LOCAL-STORAGE SECTION é semelhante à Working-Storage, mas possui uma diferença essencial: suas áreas são alocadas para cada ativação do programa.

       LOCAL-STORAGE SECTION.

       01 LS-CONTADOR          PIC 9(5) VALUE ZERO.
       01 LS-MENSAGEM          PIC X(40).

Em termos conceituais:

Primeira chamada:
LS-CONTADOR próprio

Segunda chamada:
LS-CONTADOR próprio

Terceira chamada:
LS-CONTADOR próprio

Cada invocação recebe seu próprio conjunto de dados locais.

Isso é especialmente útil em:

  • programas reentrantes;

  • rotinas reutilizáveis;

  • ambientes com várias chamadas simultâneas;

  • aplicações servidoras;

  • processamento sob Language Environment;

  • componentes que não devem preservar estado entre ativações.

Working-Storage versus Local-Storage

Uma simplificação útil:

CaracterísticaWorking-StorageLocal-Storage
ExistênciaAssociada à instância carregada do programaCriada para cada invocação
InicializaçãoNormalmente ocorre quando o programa é carregadoOcorre em cada entrada
Uso típicoEstado geral, constantes, áreas persistentes durante execuçãoDados privados de uma chamada
ReentrânciaExige maior cuidadoFacilita isolamento por ativação

Entretanto, não reduza a discussão a “Working-Storage é compartilhada e Local-Storage nunca é”.

O comportamento real depende de fatores como:

  • forma de chamada;

  • programas estáticos ou dinâmicos;

  • uso de CANCEL;

  • opções de compilação;

  • ambiente CICS;

  • atributos de reentrância;

  • runtime;

  • arquitetura da aplicação.

No laboratório do mainframe, frases absolutas são frequentemente suspeitas.


Um caso clássico: o contador que se recusava a voltar para zero

Imagine um subprograma:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CALCULA01.

       DATA DIVISION.

       WORKING-STORAGE SECTION.

       01 WS-CONTADOR          PIC 9(4) VALUE ZERO.

       PROCEDURE DIVISION.

           ADD 1 TO WS-CONTADOR
           DISPLAY 'CONTADOR: ' WS-CONTADOR

           GOBACK.

O programa chamador executa várias chamadas.

Um iniciante pode esperar:

CONTADOR: 0001
CONTADOR: 0001
CONTADOR: 0001

Mas, dependendo da forma de carregamento e das condições de execução, pode observar:

CONTADOR: 0001
CONTADOR: 0002
CONTADOR: 0003

Isso ocorre porque a Working-Storage pode manter seu conteúdo entre chamadas enquanto o programa permanecer carregado.

Mover o contador para Local-Storage muda a intenção:

       LOCAL-STORAGE SECTION.

       01 LS-CONTADOR          PIC 9(4) VALUE ZERO.

Agora cada chamada recebe uma nova área inicializada.

Esse tipo de comportamento parece sobrenatural apenas até encontrarmos a seção correta.

Depois disso, torna-se evidência técnica.


LINKAGE SECTION: dados que pertencem a outra pessoa

A LINKAGE SECTION descreve dados fornecidos por outra unidade de execução.

Esses dados não são, em princípio, áreas comuns criadas e pertencentes ao subprograma da mesma forma que itens da Working-Storage.

Exemplo de programa chamador:

       WORKING-STORAGE SECTION.

       01 WS-CLIENTE.
           05 WS-CODIGO        PIC 9(5).
           05 WS-NOME          PIC X(30).
           05 WS-SALDO         PIC S9(7)V99 COMP-3.

       PROCEDURE DIVISION.

           MOVE 12345 TO WS-CODIGO
           MOVE 'STELLA BONASERA' TO WS-NOME
           MOVE 1500.75 TO WS-SALDO

           CALL 'ATUALIZA1'
               USING WS-CLIENTE

           GOBACK.

Programa chamado:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. ATUALIZA1.

       DATA DIVISION.

       LINKAGE SECTION.

       01 LK-CLIENTE.
           05 LK-CODIGO        PIC 9(5).
           05 LK-NOME          PIC X(30).
           05 LK-SALDO         PIC S9(7)V99 COMP-3.

       PROCEDURE DIVISION USING LK-CLIENTE.

           ADD 100 TO LK-SALDO

           GOBACK.

O chamador entrega uma área.

O subprograma descreve essa área na Linkage Section.

A PROCEDURE DIVISION USING estabelece a associação entre os argumentos recebidos e os itens de Linkage.


BY REFERENCE, BY CONTENT e BY VALUE

O método de passagem de parâmetros muda completamente a investigação.

BY REFERENCE

É a forma tradicional e muito comum.

       CALL 'ATUALIZA1'
           USING BY REFERENCE WS-CLIENTE

O subprograma recebe acesso à área do chamador.

Alterações podem ser percebidas pelo chamador.

Chamador possui WS-SALDO
        |
        v
Subprograma acessa a mesma área
        |
        v
Alteração volta para o chamador

BY CONTENT

O subprograma recebe uma cópia lógica do argumento.

       CALL 'CONSULTA1'
           USING BY CONTENT WS-CLIENTE

O programa chamado pode trabalhar com o conteúdo, mas mudanças não devem retornar para a área original como numa passagem por referência.

BY VALUE

Utilizado para passar o valor diretamente, sendo especialmente relevante na interoperabilidade com outras linguagens e APIs.

       CALL 'ROTINAC'
           USING BY VALUE WS-CODIGO

BY VALUE exige atenção a tamanho, representação e convenções de chamada.

Não basta o número “parecer igual”. Os bytes precisam ser compatíveis.

Em integração, o assassino frequentemente se chama “layout incompatível”.


O contrato precisa ser idêntico

Considere o chamador:

       01 WS-CLIENTE.
           05 WS-CODIGO        PIC 9(5).
           05 WS-NOME          PIC X(30).
           05 WS-SALDO         PIC S9(7)V99 COMP-3.

E o chamado:

       01 LK-CLIENTE.
           05 LK-CODIGO        PIC 9(5).
           05 LK-NOME          PIC X(20).
           05 LK-SALDO         PIC S9(7)V99 COMP-3.

O nome possui 30 bytes no chamador, mas apenas 20 na visão do chamado.

Isso desloca o campo seguinte.

O subprograma pode interpretar os últimos dez bytes do nome como parte do saldo.

Não existe magia.

Existe desalinhamento.

Em sistemas reais, esse erro pode gerar:

  • valores corrompidos;

  • dados aparentemente aleatórios;

  • S0C7;

  • sobreposição de campos;

  • gravações incorretas;

  • falhas intermitentes;

  • resultados diferentes após recompilações.

Por isso copybooks compartilhados são tão importantes.


COPYBOOK: o laudo oficial do layout

Em vez de repetir a mesma estrutura em dezenas de programas, podemos centralizá-la em um copybook.

Arquivo CPYCLI01:

       01 CLIENTE-DADOS.
           05 CLIENTE-CODIGO   PIC 9(5).
           05 CLIENTE-NOME     PIC X(30).
           05 CLIENTE-SALDO    PIC S9(7)V99 COMP-3.

No chamador:

       WORKING-STORAGE SECTION.

       COPY CPYCLI01.

No chamado:

       LINKAGE SECTION.

       COPY CPYCLI01.

Assim, ambos utilizam a mesma definição.

Mas existe uma armadilha: alterar o copybook e recompilar apenas um dos programas.

O fonte parece correto.

O copybook parece correto.

O programa recompilado parece correto.

Mas o módulo antigo continua esperando o layout anterior.

E então nasce um crime perfeito: duas versões corretas individualmente, incompatíveis quando trabalham juntas.

A solução envolve disciplina de gestão de dependências, recompilação, testes e controle de versões.


SCREEN SECTION: a antiga sala de interrogatório

A SCREEN SECTION permite definir telas em implementações COBOL que oferecem esse recurso.

Exemplo genérico:

       SCREEN SECTION.

       01 TELA-CLIENTE.
           05 BLANK SCREEN.
           05 LINE 3 COLUMN 10
              VALUE 'CODIGO DO CLIENTE:'.
           05 LINE 3 COLUMN 30
              PIC 9(5)
              USING WS-CODIGO.

Ela foi utilizada em sistemas interativos de diversas plataformas.

No universo IBM mainframe, especialmente em aplicações CICS, interfaces 3270 são frequentemente definidas por mapas BMS.

Em IMS, pode-se encontrar MFS.

Em arquiteturas modernas, o COBOL pode funcionar atrás de:

  • APIs REST;

  • aplicações web;

  • serviços de integração;

  • mensageria;

  • z/OS Connect;

  • CICS Transaction Gateway;

  • aplicativos móveis.

A tela pode ter desaparecido do COBOL, mas o programa continua processando o coração da transação.


REPORT SECTION: o especialista aposentado que ainda sabe demais

A REPORT SECTION está associada ao Report Writer, um recurso criado para facilitar a produção de relatórios estruturados.

Ela podia ajudar a organizar:

  • cabeçalhos;

  • detalhes;

  • rodapés;

  • totais;

  • quebras de grupo;

  • paginação.

Exemplo conceitual:

       REPORT SECTION.

       RD RELATORIO-VENDAS.

       01 TYPE IS PAGE HEADING.
          05 COLUMN 1 PIC X(20)
             VALUE 'RELATORIO DE VENDAS'.

Atualmente, muitos relatórios são produzidos por:

  • programas tradicionais;

  • DFSORT;

  • ferramentas de BI;

  • bancos de dados;

  • aplicações distribuídas;

  • geradores de documentos;

  • plataformas analíticas.

Mesmo assim, sistemas antigos podem utilizar Report Writer até hoje.

Em mainframe, “antigo” não significa necessariamente “inútil”.

Às vezes significa apenas “estável há 35 anos e ainda fechando a contabilidade antes do amanhecer”.


A hierarquia dos níveis: reconstruindo o corpo do registro

COBOL utiliza números de nível para representar a hierarquia dos dados.

       01 WS-CLIENTE.
           05 WS-IDENTIFICACAO.
               10 WS-CODIGO    PIC 9(5).
               10 WS-CPF       PIC 9(11).
           05 WS-NOME          PIC X(30).
           05 WS-ENDERECO.
               10 WS-RUA       PIC X(30).
               10 WS-NUMERO    PIC 9(5).
               10 WS-CIDADE    PIC X(20).

Visualmente:

WS-CLIENTE
├── WS-IDENTIFICACAO
│   ├── WS-CODIGO
│   └── WS-CPF
├── WS-NOME
└── WS-ENDERECO
    ├── WS-RUA
    ├── WS-NUMERO
    └── WS-CIDADE

Os itens de grupo não possuem PIC.

Eles são formados pelos campos subordinados.

Podemos mover ou exibir o grupo inteiro:

       DISPLAY WS-CLIENTE

Mas isso manipula a sequência física dos bytes, não uma abstração independente.


Os níveis especiais

Além dos níveis comuns, COBOL possui níveis especiais.

Nível 01

Define uma estrutura principal ou registro.

       01 WS-CLIENTE.

Níveis 02 a 49

Definem itens subordinados.

           05 WS-NOME PIC X(30).

Nível 66

Utilizado com RENAMES.

       66 WS-DADOS-BASICOS RENAMES
          WS-CODIGO THRU WS-NOME.

Hoje é pouco usado e deve ser tratado com cuidado, pois pode dificultar a leitura.

Nível 77

Define um item elementar independente.

       77 WS-CONTADOR PIC 9(5).

Ainda pode ser encontrado em programas antigos, embora muitos padrões modernos prefiram organizar itens sob níveis 01.

Nível 78

Em algumas implementações, é utilizado para constantes de compilação.

Sua disponibilidade e detalhes dependem do compilador.

Nível 88

Define nomes de condição.

           88 CLIENTE-ATIVO VALUE 'A'.

PICTURE: o retrato falado do dado

A cláusula PIC, abreviação de PICTURE, descreve a categoria e o formato do campo.

Alfanumérico

       05 WS-NOME PIC X(30).

Pode conter letras, números, espaços e outros caracteres compatíveis com a codificação utilizada.

Numérico

       05 WS-IDADE PIC 9(3).

Representa três posições numéricas.

Alfabético

       05 WS-INICIAL PIC A.

Seu uso é menos comum em programas modernos.

Com sinal

       05 WS-SALDO PIC S9(7)V99.

O S indica sinal.

Decimal implícito

       05 WS-VALOR PIC 9(5)V99.

O V não ocupa uma posição física.

Ele indica onde o programa deve interpretar a casa decimal.

O valor:

0012345

pode ser interpretado como:

123,45

de acordo com o layout.

Esse é um dos grandes suspeitos em integrações.

Se um sistema envia centavos e outro espera reais, um pagamento de R$ 150,00 pode ser interpretado como R$ 15.000,00 ou R$ 1,50.

O byte está correto.

A interpretação está errada.


DISPLAY, COMP, COMP-3: mesma informação, corpos diferentes

Um número pode possuir diferentes representações internas.

DISPLAY

       05 WS-VALOR PIC 9(5).

Cada dígito costuma ocupar uma posição de caractere.

COMP ou BINARY

       05 WS-VALOR PIC S9(9) COMP.

O valor é armazenado em representação binária conforme as regras do compilador e opções aplicáveis.

COMP-3

       05 WS-VALOR PIC S9(7)V99 COMP-3.

Utiliza decimal compactado.

Dois dígitos normalmente são armazenados por byte, com uma parte do último byte usada para o sinal.

É muito comum em aplicações financeiras porque representa valores decimais com precisão e economia de espaço.

A pista do S0C7

Um S0C7 normalmente aponta para uma exceção de dados durante uma operação decimal.

Causas comuns:

  • campo numérico contém bytes inválidos;

  • layout incorreto;

  • deslocamento provocado por copybook incompatível;

  • campo não inicializado;

  • arquivo lido com definição errada;

  • tentativa de calcular usando dados alfanuméricos;

  • erro de REDEFINES;

  • parâmetros desalinhados.

O erro aparece na Procedure Division porque uma instrução tentou utilizar o campo.

Mas o verdadeiro criminoso pode estar na Data Division.


REDEFINES: duas interpretações para a mesma evidência

REDEFINES permite que a mesma área de memória seja vista de maneiras diferentes.

       01 WS-DATA-NUMERICA.
           05 WS-DATA-AAAAMMDD PIC 9(8).

       01 WS-DATA-DETALHADA
          REDEFINES WS-DATA-NUMERICA.
           05 WS-ANO           PIC 9(4).
           05 WS-MES           PIC 9(2).
           05 WS-DIA           PIC 9(2).

Se:

       MOVE 20260725 TO WS-DATA-AAAAMMDD

então podemos acessar:

WS-ANO = 2026
WS-MES = 07
WS-DIA = 25

Nenhum dado foi copiado.

A mesma sequência de bytes recebeu duas descrições.

É poderoso, eficiente e perigoso.

Um REDEFINES incorreto pode transformar:

  • nome em número;

  • data em saldo;

  • código em endereço;

  • payload em campos incompatíveis.

No CSI do mainframe, REDEFINES é aquele suspeito elegante que parece sempre ter um álibi.


OCCURS: a formação da quadrilha

OCCURS define repetições de uma estrutura, criando tabelas.

       01 WS-TABELA-CLIENTES.
           05 WS-CLIENTE OCCURS 100 TIMES.
               10 WS-CODIGO    PIC 9(5).
               10 WS-NOME      PIC X(30).

Isso reserva espaço para cem ocorrências.

Podemos acessar:

       MOVE 12345 TO WS-CODIGO (1)
       MOVE 'MAC TAYLOR' TO WS-NOME (1)

Subscript

       01 WS-I PIC 9(3) COMP VALUE 1.

       DISPLAY WS-NOME (WS-I)

Index

A tabela pode ser definida com índice:

       05 WS-CLIENTE OCCURS 100 TIMES
           INDEXED BY IDX-CLIENTE.

Uso:

       SET IDX-CLIENTE TO 1
       DISPLAY WS-NOME (IDX-CLIENTE)

O índice possui natureza própria e pode ser otimizado para o deslocamento interno da tabela.

Nunca ultrapasse os limites do OCCURS.

Acessar a ocorrência 101 de uma tabela com cem elementos pode atingir memória pertencente a outro campo.

É o equivalente digital de atravessar a fita amarela da cena do crime.


Passo a passo: montando um programa completo

Vamos construir um pequeno processamento sequencial.

1. Declarar o arquivo no ambiente

       ENVIRONMENT DIVISION.

       INPUT-OUTPUT SECTION.

       FILE-CONTROL.

           SELECT ARQ-CLIENTES
               ASSIGN TO CLIENTES
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-FILE-STATUS.

2. Descrever o registro

       DATA DIVISION.

       FILE SECTION.

       FD  ARQ-CLIENTES.

       01  REG-CLIENTE.
           05 REG-CODIGO       PIC 9(5).
           05 REG-NOME         PIC X(30).
           05 REG-SALDO        PIC S9(7)V99 COMP-3.

3. Criar áreas auxiliares

       WORKING-STORAGE SECTION.

       01 WS-FILE-STATUS       PIC XX.

       01 WS-CONTROLES.
           05 WS-FIM           PIC X VALUE 'N'.
               88 FIM-ARQUIVO  VALUE 'S'.
               88 HA-REGISTRO  VALUE 'N'.

       01 WS-TOTAIS.
           05 WS-QTD           PIC 9(7) VALUE ZERO.
           05 WS-TOTAL-SALDO   PIC S9(13)V99 COMP-3
                               VALUE ZERO.

4. Abrir o arquivo

       PROCEDURE DIVISION.

       0000-PRINCIPAL.

           OPEN INPUT ARQ-CLIENTES

           IF WS-FILE-STATUS NOT = '00'
               DISPLAY 'ERRO NO OPEN: ' WS-FILE-STATUS
               MOVE 12 TO RETURN-CODE
               GOBACK
           END-IF

5. Ler o primeiro registro

           PERFORM 1000-LER-CLIENTE

6. Processar até o fim

           PERFORM UNTIL FIM-ARQUIVO

               ADD 1 TO WS-QTD
               ADD REG-SALDO TO WS-TOTAL-SALDO

               DISPLAY REG-CODIGO
                       ' '
                       REG-NOME

               PERFORM 1000-LER-CLIENTE

           END-PERFORM

7. Encerrar

           CLOSE ARQ-CLIENTES

           DISPLAY 'CLIENTES: ' WS-QTD
           DISPLAY 'TOTAL:    ' WS-TOTAL-SALDO

           GOBACK.

8. Criar o parágrafo de leitura

       1000-LER-CLIENTE.

           READ ARQ-CLIENTES
               AT END
                   SET FIM-ARQUIVO TO TRUE
               NOT AT END
                   SET HA-REGISTRO TO TRUE
           END-READ.

O programa completo demonstra como cada seção coopera.

A File Section fornece o registro.

A Working-Storage guarda o controle e os totais.

A Procedure Division conduz o processamento.

Cada elemento possui responsabilidade própria.


Checklist forense para analisar uma DATA DIVISION

Quando um programa apresenta erro de dados, examine:

1. O PIC está correto?

Compare tamanho, sinal e casas decimais.

PIC 9(7)V99

não é equivalente a:

PIC 9(9)

2. O formato interno é compatível?

PIC S9(7)V99 COMP-3

não possui a mesma representação física de:

PIC X(5)

3. O arquivo está com o LRECL esperado?

Se o programa espera 100 bytes, mas o arquivo possui 120, parte do registro pode ser ignorada ou interpretada incorretamente.

4. O copybook é a versão correta?

Verifique data, biblioteca, concatenação e versão usada na compilação.

5. Chamador e chamado foram recompilados?

Uma mudança na interface pode exigir recompilar todos os consumidores.

6. Existe REDEFINES?

Descubra qual visão está sendo usada em cada ponto.

7. Existe OCCURS?

Verifique limites, índices e subscritos.

8. O campo foi inicializado?

Não presuma que contém zeros ou espaços.

9. O parâmetro foi passado pelo método correto?

Confirme BY REFERENCE, BY CONTENT ou BY VALUE.

10. O campo possui alinhamento ou sincronização especial?

Cláusulas como SYNCHRONIZED podem introduzir bytes de preenchimento dependendo do compilador e da estrutura.


Curiosidades da sala de evidências

Curiosidade 1: o nome do campo não existe no arquivo

Um arquivo físico não contém necessariamente nomes como:

REG-CODIGO
REG-NOME
REG-SALDO

Ele contém bytes.

Os nomes existem no programa para que os humanos e o compilador interpretem as posições.

O mesmo arquivo pode receber layouts diferentes.

Um deles estará correto.

Os demais produzirão ficção científica.

Curiosidade 2: PIC não é uma máscara de exibição apenas

Muitos iniciantes associam PICTURE apenas à aparência.

Na verdade, ela define categoria, tamanho e interpretação do item.

Curiosidade 3: o ponto decimal pode não existir fisicamente

No V implícito, nenhum caractere de ponto ou vírgula é armazenado.

PIC 9(5)V99

ocupa sete dígitos, não oito posições contendo um separador.

Curiosidade 4: um item de grupo pode misturar categorias

       01 WS-REGISTRO.
           05 WS-CODIGO PIC 9(5).
           05 WS-NOME   PIC X(20).

O grupo inteiro pode ser tratado como uma sequência de bytes para certas operações, apesar de conter campos de diferentes categorias.

Curiosidade 5: a memória é inocente

A memória não sabe que aqueles bytes representam CPF, saldo ou data.

Ela apenas armazena bits.

O significado vem do layout.

Quando o layout mente, a memória obedece.


Easter eggs do laboratório CSI Mainframe

Em homenagem ao clima de investigação, os nomes dos exemplos esconderam algumas referências.

  • MAC TAYLOR aparece como líder da equipe forense de Nova York.

  • STELLA BONASERA foi usada em uma estrutura de cliente.

  • O horário de 02h17 lembra a rotina dos processamentos batch que terminam quando a cidade dorme.

  • O terminal 3270 funciona como a mesa de autópsia digital.

  • O S0C7 é o equivalente mainframe de encontrar uma impressão digital impossível na arma do crime.

  • O copybook incompatível é o “suspeito que possuía duas identidades”.

  • O REDEFINES representa a evidência que muda de aparência dependendo do ângulo da luz.

  • O OCCURS é a fotografia de uma quadrilha perfeitamente alinhada na parede do distrito policial.

E existe um easter egg maior.

Em quase todo mistério COBOL, o programador procura primeiro a linha que falhou.

O investigador experiente procura primeiro o dado que chegou até ela.


Dicas do Bellacosa Mainframe para o iniciante

Use nomes que revelem intenção

Evite:

       01 X1 PIC X.

Prefira:

       01 WS-STATUS-CLIENTE PIC X.

Agrupe campos relacionados

       01 WS-CONTROLES.
           05 WS-FIM-ARQUIVO PIC X.
           05 WS-ERRO        PIC X.
           05 WS-RETORNO     PIC 9(4).

Use níveis 88

Eles tornam o código mais claro e reduzem comparações espalhadas.

Padronize prefixos

Exemplo:

  • WS- para Working-Storage;

  • LS- para Local-Storage;

  • LK- para Linkage;

  • REG- para registros de arquivo;

  • CT- para constantes;

  • IDX- para índices.

Isso não é uma regra universal da linguagem, mas ajuda muito na leitura.

Documente formatos numéricos

Especialmente:

  • sinal;

  • casas decimais;

  • COMP;

  • COMP-3;

  • valores enviados a outros sistemas.

Trate copybooks como interfaces

Uma alteração em copybook não é apenas uma mudança de layout.

Pode ser uma mudança de contrato entre dezenas ou centenas de programas.

Nunca ignore o tamanho total

Calcule o comprimento do registro.

Confirme com:

  • LRECL;

  • documentação;

  • catálogo;

  • ferramenta de browse;

  • definição do dataset;

  • programa produtor;

  • programa consumidor.

Teste limites

Para OCCURS, teste:

  • primeira posição;

  • última posição válida;

  • tabela vazia;

  • tabela completa;

  • tentativa de ultrapassagem;

  • chave não encontrada.


A conclusão da investigação

A equipe se reúne diante do painel de vidro.

O programa não falhou porque o ADD estava errado.

A instrução era perfeitamente válida.

O problema estava em um copybook antigo usado por um subprograma que não havia sido recompilado.

O chamador enviava:

       05 CLIENTE-NOME PIC X(30).

O chamado ainda esperava:

       05 CLIENTE-NOME PIC X(20).

Os dez bytes excedentes deslocaram o saldo.

Quando o programa tentou somar aquele conteúdo como decimal compactado, ocorreu o S0C7.

A linha da Procedure Division apenas encontrou o corpo.

O crime havia sido planejado na Data Division.

Essa é a lição central.

A DATA DIVISION não é um depósito passivo de declarações. Ela é a fundação arquitetural do programa COBOL.

A FILE SECTION descreve os registros que chegam de arquivos.

A WORKING-STORAGE SECTION mantém controles, acumuladores, tabelas e áreas utilizadas durante a execução.

A LOCAL-STORAGE SECTION fornece áreas independentes para cada ativação.

A LINKAGE SECTION estabelece contratos de comunicação entre programas.

A SCREEN SECTION pode descrever interfaces interativas.

A REPORT SECTION pode organizar relatórios estruturados.

Os níveis constroem hierarquias.

A cláusula PIC define formatos.

VALUE estabelece estados iniciais.

OCCURS cria tabelas.

REDEFINES oferece diferentes interpretações para a mesma memória.

Os níveis 88 transformam códigos em significado.

COMP e COMP-3 revelam que dois campos numericamente semelhantes podem possuir corpos físicos completamente diferentes.

Para o programador iniciante, dominar a Data Division significa começar a enxergar além da aparência do código.

Você deixa de ver apenas:

       05 SALDO PIC S9(7)V99 COMP-3.

E passa a enxergar:

Campo assinado
Decimal
Sete posições inteiras
Duas casas decimais
Representação compactada
Contrato físico de armazenamento
Possível ponto de integração
Possível origem de S0C7
Possível incompatibilidade com copybook

Esse é o momento em que o estudante deixa de apenas escrever COBOL e começa a investigar sistemas.

Porque na programação corporativa os defeitos raramente anunciam sua origem.

Eles aparecem em outro módulo.

Falham horas depois.

Dependem de um registro específico.

Só acontecem em produção.

Desaparecem durante o teste.

Retornam no fechamento mensal.

E deixam para trás apenas um dump, um código de retorno, algumas mensagens no spool e um campo cheio de bytes que ninguém deveria ter interpretado daquela maneira.

Mas não se preocupe.

Coloque as luvas.

Abra o compile listing.

Verifique o offset.

Compare o copybook.

Calcule o comprimento.

Analise o formato.

Siga o rastro dos bytes.

No laboratório do Bellacosa Mainframe, toda variável possui uma história.

Todo registro possui um passado.

Todo ABEND possui uma causa.

E toda Data Division, quando examinada com atenção, acaba confessando.

Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...