Baixe o app para aproveitar ainda mais
Prévia do material em texto
1. Histórias e controvérsias Se você saca dinheiro num caixa eletrônico, confere seu extrato bancário na internet ou recebe uma conta telefônica, você está usando o COBOL, mesmo sem saber. A Common Business Oriented Language é (de longe) a linguagem de programação mais utilizada em sistemas críticos de grandes empresas. Mas é também a mais criticada, comentada e controversa no mundo da Tecnologia da Informação. Em maio de 1959, por iniciativa do governo americano, fabricantes, usuários e pesquisadores da ciência da computação formaram um comitê para desenvolver uma linguagem de programação universal, que pudesse ser adotada em diferentes equipamentos e que facilitasse o desenvolvimento e a manutenção de sistemas para ambientes comerciais. O custo de manutenção de sistemas do departamento de defesa crescia à medida que aumentava o uso de computadores. A redução desses custos também beneficiaria a indústria pois facilitaria a comercialização de seus equipamentos para um mercado mais amplo. O comitê ganhou o nome de CODASYL (Conference on Data Systems Languages) e passou a trabalhar na junção de duas linguagens de programação que vinham sendo desenvolvidas isoladamente: A FLOW-MATIC, desenvolvida por Grace Hopper na Remington Rand, e a COMTRAN, desenvolvida por Bob Berner na IBM. Foi o próprio Berner que sugeriu o nome COBOL, mas a influência da FLOW-MATIC, de Hopper, foi maior no produto final. O COBOL[1] surgiu como uma linguagem “autodocumentável”, com sintaxe parecida com o inglês, e organizada em divisões, seções parágrafos e sentenças, semelhante a um texto comum. [1] Gramaticalmente faria mais sentido fazer referencia “a” COBOL, uma vez que se trata de uma linguagem. Neste livro, no entanto, optamos por usar “o COBOL” por ser a forma mais comum em língua portuguesa. Evolução Um primeiro documento detalhando a linguagem foi publicado pelo CODASYL em 1960. Mas havia ainda alguma omissões que levaram os fabricantes a implementar as primeiras versões da linguagem com diferenças significativas de semântica e sintaxe em seus equipamentos. Em 1968, o ISO (International Standard Organization) e o ANSI (American National Standard Institute) se uniram para propor um novo padrão, que incorporasse as melhores soluções de cada fabricante. Desse trabalho surgiu a versão que ficou conhecida como COBOL/68 ou COBOL/ANS. Desde então, o COBOL vem passando por diversas revisões, incorporando conceitos e recursos que surgiram com o desenvolvimento de equipamentos e sistemas operacionais. Cada uma dessas revisões recebe o nome do ano em que foram publicadas. Os padrões mais significativos, até o momento, são conhecidos como COBOL/74, COBOL/85, COBOL/2002 e COBOL/2014. Esses dois últimos incorporam o conceito de orientação a objetos, mas a maior parte dos programas escritos (ainda hoje) em COBOL adotam o modelo procedimental clássico. O COBOL no mercado O governo americano foi determinante para a popularidade inicial do COBOL ao exigir que todos os fornecedores de computadores para o governo oferecessem um compilador para essa linguagem. Mas outros fatores também contribuíram para sua rápida aceitação no mercado: • Por ser orientada a dados estruturados, ela se adaptava bem às necessidades de processamento comercial, principalmente pela facilidade com que representava informações de negócio • O uso de uma “gramática” fortemente baseada no inglês facilitava a formação de novos profissionais, diminuindo os custos associados a desenvolvimento e manutenção de sistemas • Por ser uma linguagem independente de fabricante, um programa escrito em Cobol para um computador podia ser facilmente adaptado para rodar em outro, o que preservava os investimentos realizados Ainda hoje, uma das principais características do COBOL é a portabilidade. É possível, por exemplo, migrar todo um sistema construído num mainframe da IBM e processá-lo num servidor Linux, com pouquíssimas alterações. Grandes empresas contam com sistemas críticos que foram desenvolvidos décadas atrás e que passaram de equipamento em equipamento, de geração em geração. Uma pesquisa global encomendada pela Micro Focus em 2013[1] mostra que o COBOL está presente em 90% das empresas listadas na Fortune 500: Grandes bancos, empresas de aviação, concessionárias de serviço público, agências de governo, operadoras de cartão de crédito, grandes redes de varejo, montadoras de automóveis… grandes corporações em geral mantêm 70% de toda a sua lógica de negócios escrita em COBOL. O momento decisivo Se houve um momento em que o COBOL foi realmente ameaçado, esse momento aconteceu no final dos anos 1990, numa “crise” que ficou conhecida como bug do milênio. Naqueles dois ou três anos que antecederam o ano 2000, muitas das grandes empresas usuárias do COBOL cogitaram seriamente a possibilidade de substituí-lo. Afinal, se havia necessidade de varrer todos os programas em busca de anos com dois dígitos, e depois alterá-los, testá-los e homologá-los, por que não simplesmente escrever tudo de novo em outra linguagem? O que pesou na decisão final foi preço e retorno do investimento. Reescrever um desses grandes sistemas, na prática, significava: • Documentar a funcionalidade de dezenas de milhares de programa, centenas de milhões de linhas de código e todos os dados permanentes e transitórios envolvidos; • Selecionar e adquirir uma plataforma de hardware e/ou software para desenvolvimento, teste e produção que oferecesse a mesma capacidade de processamento, segurança e estabilidade; • Especificar, escrever, testar e homologar todo o sistema na nova plataforma, garantindo as integrações anteriores, internas e externas; • Planejar a implantação em roll-outs sucessivos que garantissem a continuidade da operação da empresa, considerando inclusive a duplicação de manutenções evolutivas mandatórias, enquanto durasse a transição • Treinar e apoiar milhares de usuários Muitos sistemas departamentais e periféricos de fato migraram para pacotes ERP e/ou aplicações desenvolvidas em plataformas mais novas. Mas os sistemas críticos – aqueles que respondiam pela core do negócio – foram apenas renovados para o ano 2000 e continuam funcionando até hoje. Críticas e controvérsias Talvez existam poucas linguagens de programação tão controversas quanto o COBOL. E essa situação não é recente. O meio acadêmico nunca demonstrou muito interesse pelo desenvolvimento de uma linguagem que pretendia atender a processos comerciais, financeiros e administrativos em geral. O próprio CODASYL foi formado, basicamente, por empresas e agências do governo americano. Nesse distanciamento entre o meio acadêmico e a necessidade das empresas pode estar a origem de diversas críticas que, ainda hoje, ouvimos sobre essa linguagem. O COBOL foi projetado para facilitar a leitura dos programas, seguindo uma linguagem semelhante ao inglês. Não podemos esquecer que, quando essa linguagem surgiu, a ciência da computação dependia predominantemente de linguagens simbólicas, de baixo nível, dominadas por engenheiros que, muitas vezes, haviam trabalhado no projeto do hardware. O COBOL buscou tornar o trabalho de programação mais acessível, mais intuitivo, mais portável e menos dependente das características de cada máquina, uma vez que, comparado às linguagens anteriores, seus comandos eram quase autoexplicativos. Com o passar do tempo, justamente esse modelo sintático foi o causador das primeiras críticas: o COBOL passou a ser considerado “verborrágico”, com suas mais de 300 palavras reservadas e a necessidade de codificação de “frases com verbo e predicado” para realizar operações que as linguagens mais modernas resolvem de forma mais simples. Outra crítica se deve ao fato de que o COBOL é uma linguagem procedural, num mundo orientado a objetos. É inegável que linguagens como Java ou C++ foram projetadas para facilitar a implementação de abstracões, encapsulamentos, heranças e polimorfismos, conceitos relativamenterecentes. O uso dessas linguagens em aplicações interativas é mais do que indicado. Mas o COBOL continua imbatível quando a meta é processar centenas de milhões de registros, em jobs concorrentes, mesmo quando comparado a outras linguagens tradicionais do ambiente mainframe, como NATURAL, Easytrieve ou Rexx. Também por ser uma linguagem procedural, alguns alegam que é muito fácil escrever um programa de forma ruim. Existem comandos nessa linguagem que são execrados (como o ALTER) ou temidos (como o GO TO) e que têm potencial para tornar um programa incompreensível. Mas, convenhamos, é possível codificar mal um programa em qualquer linguagem, e qualquer um que já tenha se confrontado com um sistema orientado a objetos mal projetado sabe disso. O bom uso do COBOL requer que o programador pense de forma estruturada e domine a arte de projetar algoritmos. Mas talvez o que mais se comente, sem muito conhecimento de causa, é que “programas em COBOL são extensos” ou que “com o COBOL o programador tem que escrever muito”. Nesse aspecto, algumas questões que precisam ser consideradas: • Um programa “curto” não é necessariamente bom, principalmente se for difícil de entender (e manter) alguns anos após sua construção; • Um programa não é necessariamente “extenso” por causa da linguagem. Uma especificação ruim pode resultar num programa grande por excesso de acoplamento funcional ou desconhecimento da linguagem; • Um programa COBOL pode ser extenso porque foi construído, por exemplo, antes do advento das built-in functions (ou funções intrínsecas), introduzidas no padrão ANSI/ISO de 1989 e 1993. [1] https://www.microfocus.com/about/press-room/article/2013/academia-needs-more- support-to-tackle-the-it-skills-gap. Acessado em dezembro de 2016. 2. Estrutura da linguagem O Cobol foi desenvolvido na era dos primeiros mainframes, que dispunham apenas de perfuradoras e leitoras de cartão para receber informações do meio exterior. Cada linha de programa era, na verdade, um cartão de papelão perfurado e o programa completo era uma pilha de cartões. Muitas das características da linguagem, presentes até hoje, foram definidas nessa época. Linha de programa Por causa dos cartões perfurados, até hoje as linhas de um programa Cobol podem ter no máximo 80 caracteres, divididos em cinco áreas: Figura 1. As áreas reservadas de uma linha de programa COBOL • Sequence number area: Vai da coluna 1 à coluna 6. Ela era originalmente usada para numerar as linhas (ou cartões) do programa, facilitando a reordenação manual, quando necessário. Os compiladores atuais não exigem mais que essa coluna esteja numerada e ignoraram qualquer informação colocada ali. Alguns pacotes de gestão de configuração (e alguns programadores) usam esse espaço para marcar as alterações de código. • Indicator area: É formada apenas pela coluna 7. Essa coluna pode conter alguns caracteres que fornecem informações específicas para o compilador. Por exemplo, um asterisco (*) nesta posição indica que a linha é apenas um comentário; um hífen (-) indica que uma sentença ou um literal não coube na linha anterior e continuará nesta linha. • Área A: Vai da coluna 8 à coluna 11. Algumas estruturas de um programa Cobol (divisões, seções, parágrafos e variáveis de nível 1, especificamente) devem começar obrigatoriamente neste espaço. • Área B: Vai da coluna 12 à coluna 72. É usada basicamente para a codificação de variáveis de nível superior a 1, cláusulas e comandos em geral. • Identifier Area: Vai da coluna 73 à coluna 80. Quando os programas eram codificados em cartões perfurados, essa área era usada para registrar o nome do programa, que se repetia em todos os cartões. Compiladores atuais ignoram as informações presentes neste espaço. Assim como acontece com a sequence number area, alguns pacotes de gestão de configuração (e alguns programadores) usam essas posições para registrar informações sobre as alterações realizadas sobre o programa. Depois da revisão de 2002, o COBOL passou a permitir uma nova estrutura de linha de código, chamado free format. Nesse formato, não há a restrição de 80 caracteres por linha, e as linhas não precisa mais respeitar as áreas mencionadas acima. Muitos gostaram da novidade, outros detestaram. De qualquer forma, a grande maioria das instalações ainda segue o modelo tradicional. Figura 2. Pilha de cartões perfurados (IBM Archives) Quem vê o COBOL pela primeira vez considera esse formato anacrônico e excessivamente rígido. Os editores de programa, no entanto, costumam facilitar o trabalho do programador, permitindo a configuração de zonas de tabulação (nas colunas 7, 8, 12 e depois de 4 em 4 espaços) ou oferecendo recursos como a autoedentação, que posiciona as “palavras certas” nas “colunas certas”. O COBOL não é case sensitive. Você pode codificar o programa combinando letras maiúsculas ou minúsculas. Curiosamente, quase todos os programas que você vai encontrar foram escritos apenas com letras maiúsculas, e isso é quase uma tradição que vem do tempo em que os programas eram codificados em terminais de mainframes. O ideal é que você respeite sempre o padrão adotado pela sua empresa para manter a coerência visual dos sistemas. Nesse livro, programas e exemplos serão codificados com letras maiúsculas, que é o formato mais frequentemente encontrado nas empresas. Linhas de comentário As linhas de comentários num programa COBOL são aquelas que têm um asterisco na coluna 7. Essas linhas são ignoradas pelo compilador. *----------------------------------------------------------------* * OBJETIVO: ABRIR ARQUIVOS E TESTAR FILE STATUS *----------------------------------------------------------------* 12-ABRE-ARQUIVOS. MOVE "NAO" TO WT-FL-ERRO. OPEN I-O AIA0103 IF WT-ST-AIA0103 NOT = "00" AND "05" AND "35" MOVE "AIP0103" TO XXERROS-NM-PROGRAMA MOVE "AIA0103" TO XXERROS-NM-ARQUIVO MOVE WT-ST-AIA0103 TO XXERROS-CD-ERRO CALL "XXERROS" USING XXCOMUM-PARAMS XXERROS-PARAMS MOVE "SIM" TO WT-FL-ERRO END-IF. Palavras reservadas Palavras reservadas são aquelas que têm um significado pré-determinado para o compilador e que, por esse motivo, não podem ser usadas pelos programadores para dar nomes a parágrafos, variáveis, arquivos etc. Todo compilador COBOL adota um dos padrões ANS/ISO (74, 85, 2002, 2014…) e implementam algumas extensões que não foram previstas pelo padrão. Por esse motivo, a lista de palavras reservadas pode variar de compilador para compilador e o melhor lugar para obter essa lista é o próprio manual. Se você seguir o padrão de nomenclatura que usaremos nesse livro dificilmente usará uma palavra reservada acidentalmente. Mas se eventualmente isso acontecer o compilador se encarregará de alertá-lo em tempo de compilação para que faça as devidas correções. Nomes definidos pelo programador Além das palavras reservadas, que formam o vocabulário da linguagem, o programador terá que dar nomes a diversos componentes, tais como parágrafos, arquivos, campos dos arquivos, variáveis de trabalho, argumentos de execução etc. Muitos manuais se referem a esses nomes como data names ou data items. Os nomes definidos pelo programador podem ter até 30 caracteres e devem ser formados por letras, números e hífens. Dois fatores precisamos ser considerados pelo programador no momento em que os nomes são criados: 1. É importante que o nome tenha um significado que qualquer programador consiga entender no futuro. Uma variável de trabalho chamada SALARIO-MENSAL ou CONTADOR-LIDOS é melhor do que SL ou CL 2. Programas comerciais frequentemente trabalham com diversos arquivos, dependem de dezenas de campos de arquivo e variáveis de trabalho e seus algoritmos são formados por vários parágrafos. É importante, portanto, seguir o padrão de nomenclatura definido pela instalação, ou adotar um padrão próprio, se a empresa não o fizer.Uma prática muito comum é usar prefixos para diferenciar os campos de um arquivo das variáveis de trabalho usadas pelo programa. Por exemplo, CRA0201-SALARIO-MENSAL sugere que o campo SALARIO-MENSAL pertence ao arquivo CRA0201, enquanto WT- CONTADOR-LIDOS dá a entender que essa é uma variável de trabalho definida na WORKING-STORAGE, sobre a qual falaremos mais adiante. Divisões, seções, parágrafos e sentenças O COBOL foi concebido para que o programa fonte tivesse uma estrutura parecida com um texto escrito em inglês. Todo programa possui quatro divisões. Cada divisão é organizada em seções, que por sua vez são formadas por parágrafos. Cada parágrafo possui uma ou mais sentenças. Essa hierarquia tem por objetivo facilitar a localização de determinadas informações, da mesma forma que capítulos, tópicos, parágrafos e frases facilitam a localização de determinados assuntos num livro. A figura abaixo mostra alguns exemplos de divisões, seções, parágrafos e sentenças num programa COBOL. Figura 3. Exemplos de divisões, seções, parágrafos e sentenças no COBOL Mais adiante falaremos em detalhes sobre cada uma dessas estruturas. Por ora, vamos pegar como exemplo a divisão chamada ENVIRONMENT DIVISION. Nessa divisão ficam informações sobre o ambiente onde o programa será executado. Uma das seções da ENVIRONMENT se chama INPUT-OUTPUT SECTION. Nessa seção estarão informações sobre as entradas e saídas do programa. Um dos parágrafos da INPUT-OUTPUT se chama FILE-CONTROL, onde são declarados os arquivos que serão lidos, gravados e/ou alterados. O parágrafo FILE-CONTROL é formado por uma ou mais cláusulas SELECT. Haverá um SELECT para cada arquivo, informando seu formato, seu nome interno (o nome que será usado pelo programa), seu nome externo (o nome do arquivo para o sistema operacional) e algumas outras informações. Nos próximos capítulos veremos em detalhes cada uma das divisões e seções de um programa COBOL. O uso do ponto O uso do ponto em COBOL tem papel semelhante ao ponto-e-vírgula de outras linguagens, mas pode causar alguma confusão, no início, porque seu uso costuma ser mais flexível. Todos os nomes de divisão, seção e parágrafo devem terminar com um ponto. Nas três primeiras divisões (IDENTIFICATION, ENVIRONMENT e DATA) qualquer sentença também deve terminar com um ponto, como no exemplo abaixo: IDENTIFICATION DIVISION. PROGRAM-ID. LTP0101. AUTHOR. JOAO DA SILVA. DATE-WRITTEN. 25/10/2016. Na PROCEDURE DIVISION, que é onde ficam os comandos do programa, apenas a última sentença de cada parágrafo precisa de um ponto. Isso só é válido para compiladores que adotaram o padrão COBOL ANS/85 ou posterior, já que foi nesta revisão que a ANS introduziu o conceito de delimitadores de escopo (END-IF, END-READ, END-PERFORM etc.). Antes do surgimento dos delimitadores, o ponto precisa ser usado para encerrar o escopo de alguns comandos. Repare no exemplo abaixo que o único comando que precisa de um ponto é o STOP RUN na última linha, por ser o último comando do parágrafo CALCULA-TABUADA. PROCEDURE DIVISION. CALCULA-TABUADA. ACCEPT “INFORME UM NUMERO: “ WT-BASE PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10 DISPLAY WT-BASE “ X “ I “ = “ WT-BASE * I END-PERFORM STOP RUN. Literais e constantes figurativas Literais são valores constantes, formados por um conjunto de caracteres. Eles podem ser usados tanto na atribuição do valor inicial de uma variável, na alteração desse valor inicial durante a execução do programa, na exibição de mensagens ou na formação de relatórios. 77 TITULO-RELATORIO PIC X(030) VALUE “FLUXO DE CAIXA”. MOVE “CONTAS A RECEBER 2016” TO SUBTITULO DISPLAY “TERMINO DO PROGRAMA” Nos exemplos acima, a primeira linha mostra o literal “FLUXO DE CAIXA” sendo atribuído como valor inicial para a variável TITULO-RELATORIO. A segunda linha, mostra uma variável chamada SUBTITULO recebendo como valor o literal “CONTAS A RECEBER 2016”. A terceira linha mostra o literal “TERMINO DO PROGRAMA” sendo exibido para o usuário. Literais alfanuméricos, como os que usamos nesses exemplos, são formados por letras, números e caracteres especiais (espaços em branco, asteriscos, hifens…) e devem ser delimitados por aspas duplas ou simples, dependendo da parametrização que foi estabelecida para o compilador Literais numéricos são formados por números, sinais de mais ou menos e pontos decimais, como nos exemplos abaixo: 77 PERCENTUAL-FINAL PIC 9(003) VALUE 100. MOVE 3600 TO MINUTOS-DIA DISPLAY “COTACAO DO DOLAR: “ 3.65 A primeira linha mostra o literal numérico 100 sendo usado como valor inicial na declaração da variável PERCENTUAL-FINAL. A segunda linha mostra literal numérico 3600 sendo atribuído à variável MINUTOS-DIA em tempo de execução. A terceira linha exibe na tela do usuário o literal alfanumérico “COTACAO DO DOLAR: “ seguido do literal numérico 3.65, que possui duas casas decimais. Algumas palavras reservadas do COBOL substituem alguns literais numéricos e alfanuméricos. Essas palavras são chamadas de constantes figurativas. Podemos escrever, por exemplo… MOVE “ “ TO NOME-DO-CLIENTE Ou… MOVE SPACES TO NOME-DO-CLIENTE Neste caso, a palavra reservada SPACES está substituindo um literal alfanumérico formado apenas por espaços em branco. Outras constantes figurativas muito usadas no COBOL são: • HIGH-VALUES: Equivale a um literal alfanumérico formado apenas pelo maior caracter da tabela ASCII ou EBCDIC (normalmente o hexadecimal x”FF”). • LOW-VALUES: Equivale a um literal alfanumérico formado apenas pelo menor caracter da tabela ASCII ou EBCDIC (normalmente o hexadecimal x”00”). • ZEROS: Equivale a um literal numérico formado apenas por zeros. • ALL caracter: Equivale a um literal alfanumérico formado apenas pelo caracter que aparece em seguida. Exemplos: ALL “X”, ALL “A”, ALL “1” etc. Assim, se você precisar zerar uma variável tempo de execução, você pode escrever: MOVE ZEROS TO NOME-DA-VARIAVEL Ou se quiser criar uma variável preenchida com asteriscos, pode fazer: 03 WR-CAB3 PIC X(080) VALUE ALL “*”. Construção e execução de um programa Um programa COBOL passa por três etapas principais antes de ser executado: edição, compilação e linkedição. Figura 4. Etapas entre a construção e a execução de um programa COBOL Na edição, o programador constrói ou altera o programa fonte usando o editor de texto disponível no ambiente de desenvolvimento. O programa fonte passa então por um processo de compilação, que verificará se as regras de sintaxe e codificação da linguagem foram cumpridas. Em mainframes, o compilador normalmente é executado por um job escrito em JCL que foi submetido pelo programador. As mensagens emitidas pelo compilador, inclusive mensagens de erro, são exibidas em relatórios gerados pelo job e disponibilizados num spool de execução após a compilação. No Linux, normalmente o compilador é executado por um shell script que exibe as mensagens de erro na tela e/ou redireciona essas mensagens para um arquivo texto. Existem também IDEs com interfaces gráficas (Windows, X-Window, Mac OS…) que compilam e exibem os resultados em janelas. Se não houver nenhum erro impeditivo na compilação, um programa objeto em linguagem de máquina será gerado. Esse programa objeto passa então por um processo chamado de linkedição, que basicamente estabelece endereços de memória para instruções e dados utilizados pelo programa. Normalmente o linkeditor é executado no mesmo job do compilador (o linkeditor é um step a mais no mesmo job ou script, de compilação). O linkeditor também gera mensagens para o programador através de relatórios que ficam num spool de execução (no caso dos mainframes), na tela e/ou num arquivo texto (no caso do Linux) ou numa janela específica (no caso das IDEs com interfaces gráficas). Se nenhum problema for detectado nesta etapa, o linkeditor gera um módulo de carga, que na prática é o programa executável. Alguns comentários sobre padrões e convençõesToda instalação estabelece seus próprios padrões de codificação que, numa linguagem com décadas de uso, foram aperfeiçoados ao longo do tempo. Mesmo que uma convenção adotada pela empresa não pareça fazer sentido (e algumas vezes realmente não faz), precisamos respeitá-la para, em última análise, manter a coesão semântica e sintática do portfólio de sistemas. Este livro explicará os conceitos gerais de cada estrutura da linguagem COBOL, e em alguns casos discutirá (e justificará) algumas das melhores práticas que o autor encontrou em diversos projetos ao longo dos últimos 30 anos. Mas, naturalmente, os padrões mostrados aqui não devem ser considerados melhores (ou piores) do que os outros. Poucas convenções se justificam em função de performance ou de qualquer outro motivo puramente técnico. A maior parte das regras de codificação que fazem parte de um padrão estão preocupadas com a facilidade de manutenção futura, que só vai ser alcançada se todos os programas da instalação (ou pelo menos a grande maioria) seguirem um mesmo formato. 3. Identification Division A IDENTIFICATION DIVISION deve ser a primeira divisão declarada em qualquer programa Cobol. Ela estabelece o nome do programa e contém alguns outros parágrafos opcionais que contribuem para a sua documentação. Esta é a única divisão que não é formada por seções, e sim por parágrafos. O único parágrafo obrigatório é o PROGRAM-ID, que estabelece o nome do programa e deve ser o primeiro a ser codificado. Todos os outros parágrafos são opcionais e podem aparecer em qualquer ordem dentro desta divisão. Nome do programa O COBOL/85 estabeleceu que o nome de um programa pode ter até 30 caracteres, mas muitos compiladores (como os que são usados em mainframes) só permitem nomes de programas com 8 caracteres ou menos, sendo que o primeiro caracter deve ser necessariamente alfabético. Esse nome deve aparecem sempre após o parágrafo PROGRAM-ID: IDENTIFICATION DIVISION. PROGRAM-ID. CRP0206. É comum que as empresas definam um padrão de nomenclatura que permita ao programador identificar o sistema e o subsistema (ou módulo) ao qual o programa pertence. O exemplo abaixo é apenas um dos muitos padrões de nomenclatura possíveis: O parágrafo PROGRAM-ID possui algumas cláusulas opcionais: PROGRAM-ID. {nome-do-programa} IS INITIAL. PROGRAM-ID. {nome-do-programa} IS COMMON. PROGRAM-ID. {nome-do-programa} IS RECURSIVE. As opções INITIAL, COMMON e RECURSIVE são usadas na codificação de subprogramas (também chamados de subrotinas), ou seja, programas que são chamados por outros programas para executar uma função específica. A cláusula INITIAL indica que o subprograma será carregado em memória e suas variáveis serão “inicializadas” cada vez que ele for chamado. A cláusula COMMON indica que o fonte do subprograma será inserido no fonte do programa “chamador”, uma abordagem conhecida como nested program, raramente utilizada. A cláusula RECURSIVE permite o que o subprograma chame a si mesmo. O COBOL permite que as três cláusulas sejam combinadas para atender a uma necessidade específica. Por exemplo, a declaração abaixo estabelece que o subprograma CRP0901 será um nested program que poderá chamar a si mesmo: PROGRAM-ID. CRP0901 IS COMMON RECURSIVE. O parágrafo PROGRAM-ID permite que o programa tenha um nome externo diferente do nome interno. Isso pode ser útil em sistemas operacionais que permitem nomes longos para os programas executáveis. A linha abaixo define FATP0101 como nome de programa, mas externamente (para o sistema operacional) ele será executado como “CadastraCategorias”. PROGRAM-ID. FATP0101 AS “CadastraCategorias”. Se não houver uma cláusula AS no PROGRAM-ID o nome externo do programa executável será igual ao seu nome interno. Esta é a situação mais comum. Nome do programador O parágrafo AUTHOR é opcional, mas normalmente o padrão de codificação das empresas obriga seu uso. Ele deve ser preenchido com o nome do programador responsável pela codificação inicial, como no exemplo abaixo: IDENTIFICATION DIVISION. PROGRAM-ID. CRP0206. AUTHOR. PAULO ANDRE DIAS. O ponto após o nome do autor é obrigatório, o que, como já mencionamos, é também é exigido em todos os outros parágrafos desta divisão. Data de codificação O parágrafo DATE-WRITTEN também é opcional. Normalmente é preenchido com a data em que o programa terminou de ser codificado e entrou na fase de testes. O exemplo abaixo mostra a codificação desse parágrafo: IDENTIFICATION DIVISION. PROGRAM-ID. CRP0206. AUTHOR. PAULO ANDRE DIAS. DATE-WRITTEN. 25/10/2015. Muitas instalações não exigem seu preenchimento, mas obrigam o programador a colocar essa data no corpo do parágrafo REMARKS, que veremos adiante. Comentários sobre o programa Apesar de opcional, o parágrafo REMARKS é exigido em quase todas as instalações. Neste parágrafo, os programadores descrevem o nome longo do programa, seu objetivo e explicam seu funcionamento. Algumas empresas também podem adotar um modelo que exiba o nome do sistema, subsistema e módulo que contém o programa e informações sobre todas as atualizações e correções que são realizadas ao longo do tempo. O exemplo abaixo mostra o uso mais simples da cláusula REMARKS: IDENTIFICATION DIVISION. PROGRAM-ID. CRP0206. AUTHOR. JOAO JOSE DA SILVA. DATE-WRITTEN. 25/10/2015. REMARKS. SELECIONA DUPLICATAS ATIVAS Exemplo completo A IDENTIFICATION DIVISION funciona como uma espécie de “folha de rosto” para o programa, permitindo que logo nas primeiras linhas o programador entenda a finalidade do programa, tenha uma ideia sobre como ele funciona, os arquivos que acessa e as últimas atualizações pelas quais ele passou. As (boas) empresas normalmente estabelecem um modelo que deve ser seguido por todos os programadores. O trecho a seguir usa um desses modelos: *================================================================* IDENTIFICATION DIVISION. *----------------------------------------------------------------* PROGRAM-ID. CRP0206. AUTHOR. PAULO ANDRE DIAS. DATE-WRITTEN. 25/10/2015. REMARKS. *----------------------------------------------------------------* * SISTEMA: CR – CONTAS A RECEBER * JOB: 02 – GERACAO DE FLUXO DE CAIXA * PROGRAMA: 06 – SELECIONA DUPLICATAS ATIVAS * * OBJETIVO: GERAR ARQUIVO DE SAIDA QUE CONTEM APENAS AS DUPLI- * CATAS QUE NAO FORAM CANCELADAS. A SITUACAO DA DU- * PLICATA DEVE SER DIFERENTE DE CANCELADA (“CNC”) * * VERSOES: DATA DESCRICAO * ------ ----------------------------------------- * XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * *----------------------------------------------------------------* Repare nas linhas de comentários (tracejados) que destacam o início da divisão. Esse recurso é muito utilizado para facilitar a leitura do código fonte, principalmente em editores que não possuem coloração por sintaxe. Observe também que o parágrafo REMARKS na verdade está em branco, mas abaixo dele existem diversas linhas de comentários que fornecem informações sobre sistema, subsistema, módulo, nome e descrição do programa e o histórico de atualizações que ele sofreu. 4. Environment Division A ENVIRONMENT é a divisão do COBOL que reúne informações sobre o ambiente onde o programa será executado. Normalmente são parâmetros de execução, opções de compatibilidade e declarações de arquivos de entrada e saída. Ela é composta por duas seções: CONFIGURATION SECTION e INPUT- OUTPUT SECTION. Se nenhuma informação da ENVIRONMENT for necessária para o programa toda a divisão pode ser omitida. Substituição do ponto decimal A CONFIGURATION SECTION é a seção que fornece dados sobre a plataforma que será usada para compilar e executar o programa, além de permitir que o programador estabeleça alguns parâmetros para execução e compatibilidade. Nesta seção é possível, por exemplo, escolher o alfabeto que será usadopelo programa (ASCII ou EBCDIC), alterar o símbolo de valor monetário ($), definir o posicionamento de sinais em campos numéricos e uma série de outras opções. No entanto, na imensa maioria dos casos, você utilizará esta seção apenas para substituir o ponto decimal (padrão americano) pela vírgula decimal (padrão brasileiro). Essa cláusula faz com que, por exemplo, o valor 1,359.85 seja exibido como 1.359,85. Para isso, codificamos a CONFIGURATION SECTION e um de seus parágrafos, SPECIAL-NAMES, com a sentença DECIMAL-POINT IS COMMA, como no exemplo abaixo: ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. Declaração de arquivos Arquivos convencionais são todos os arquivos sequenciais, indexados e/ou relativos que não fazem parte de um banco de dados. Esse recurso é muito utilizado em COBOL, principalmente em sistemas que precisam processar milhões de registros diariamente. Processar informações em modo batch usando arquivos convencionais apresenta uma performance muito superior à que seria obtida se o sistema usasse apenas banco de dados. Todos os arquivos convencionais que serão lidos, gravados ou modificados pelo programa precisam ser declarados no parágrafo FILE-CONTROL da seção INPUT-OUTPUT SECTION, da ENVIRONMENT DIVISION. O trecho abaixo mostra a declaração de dois arquivos: ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT CRA0205 ASSIGN TO “../dat/cra0205.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0205. SELECT CRA0206 ASSIGN TO “../dat/cra0206.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0206. Haverá uma cláusula SELECT para cada arquivo acessado pelo programa. Existem diversos parâmetros que podem ser usados nesta cláusula. É possível, por exemplo, definir o tipo de proteção (lock) que será usado para modificar registros, o modo como o arquivo será compartilhado, o método de acesso (sequencial ou randômico), e assim por diante. Veremos muitas outras opções da cláusula SELECT ao longo desse livro. Os dois arquivos declarados no exemplo anterior se chamam CRA0205 e CRA0206. Esses nomes serão utilizados internamente pelo programa, e não precisam ter nenhuma semelhança com o nome real do arquivo (o nome externo usado pelo sistema operacional), que aparece entre aspas depois da cláusula ASSIGN[1]. O tipo de arquivo é definido pela cláusula ORGANIZATION. Nesse exemplo, os dois arquivos são do tipo linear sequencial. Arquivos sequenciais lineares são semelhantes a arquivos texto, num ambiente Windows ou Linux. Nesse tipo de organização, os registros são separados por caracteres delimitadores. No Windows os registros são delimitados por dois caracteres: carriage return (CR, que equivale ao hexadecimal x’0D’ da tabela ASCII) e line feed (LF, que equivale ao hexadecimal x’0A’). No Unix ou no Linux, os registros são delimitados apenas pelo caracter LF. Declarando o File Status A cláusula FILE STATUS informa em que variável de trabalho o COBOL deverá colocar o código de retorno das operações de I/O que serão realizadas com cada arquivo. Ela identifica uma variável que será definida mais adiante no programa, e o ideal é que você crie uma variável de file status para cada arquivo: ENVIRONMENT DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT CRA0205 ASSIGN TO “../dat/cra0205.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0205. SELECT CRA0206 ASSIGN TO “../dat/cra0206.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0206. No nosso exemplo, dissemos que os códigos de retorno do arquivo CRA0205 ficarão na variável WT-ST-CRA0205, e que para o arquivo CRA0206 esses códigos ficarão em WT- ST-CRA0206. Essas duas variáveis terão que ser declaradas no programa, e veremos como fazer isso no próximo capítulo. Poderíamos ter dado qualquer nome válido para essas variáveis. Os nomes que usamos aqui (WT-ST-…) segue um dos muitos padrões de nomenclatura usados pelas empresas. Toda operação de I/O realizada sobre os arquivos fará com que o COBOL atualize essas variáveis com um código de retorno de dois dígitos: Figura 5. Principais códigos de retorno para file statuis Observe na figura anterior que alguns códigos de retorno são esperados pelo programa. Um file status igual a 10, por exemplo, significa que todos os registros do arquivo já foram lidos e essa é uma situação normal. Outros códigos sugerem que houve um erro de programa, como o file status 41. Outros ainda sinalizam problemas operacionais, como o file status 35. Normalmente os sistemas adotam algum procedimento padronizado para encerramento anormal quando acontece um file status inesperado, como o 41 ou o 35. Exemplo completo Como mencionamos anteriormente, todas as empresas definem padrões de codificação que buscam facilitar a construção do programa e suas manutenções futuras. Isso envolve não só o uso de comentários nos lugares certos mas também a própria formatação do código fonte e as regras de nomenclatura para programas, arquivos e variáveis. O trecho abaixo mostra como ficaria nossa ENVIRONMENT DIVISION seguindo um desses padrões: *================================================================* ENVIRONMENT DIVISION. *----------------------------------------------------------------* CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. INPUT-OUTPUT SECTION. FILE-CONTROL. *----------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------* SELECT CRA0205 ASSIGN TO “../dat/cra0205.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0205. *----------------------------------------------------------------* * DUPLICATAS ATIVAS EMITIDAS NO PERIODO *----------------------------------------------------------------* SELECT CRA0206 ASSIGN TO “../dat/cra0206.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0206. Repare que aqui também usamos linhas de comentários tracejados para destacar o início da ENVIRONMENT DIVISION. Além disso, colocamos comentários para descrever o conteúdo de cada um dos arquivos usados pelo programa. Repare que a INPUT-OUTPUT SECTION não informa se os arquivos serão acessados para leitura ou gravação. Isso será estabelecido mais adiante, na PROCEDURE DIVISION. Também não sabemos nada ainda sobre o conteúdo de cada arquivo. Isso também será definido mais adiante, na DATA DIVISION, sobre o qual falaremos no próximo capítulo. [1] A cláusula ASSIGN varia ligeiramente de plataforma para plataforma. Este livro adota as convenções do Linux. O exemplo mostra que os arquivos estarão num subdiretório chamado “../dat” e que os arquivos (reais) terão uma extensão .dat. 5. Data Division A organização de um programa COBOL em divisões, seções e parágrafos tem por objetivo manter cada coisa em seu lugar. Talvez essa percepção fique mais evidente a partir de agora. O COBOL faz uma clara distinção entre a descrição do processamento, que acontecerá na PROCEDURE DIVISION, e os dados que esse processamento utilizará. O lugar onde declaramos esses dados é justamente na DATA DIVISION. A DATA DIVISION descreve de uma forma estruturada todos os dados que serão acessados pelo programa. Todas as variáveis devem ser declaradas nesta divisão, sejam elas campos de arquivos convencionais, atributos de banco de dados, parâmetros fornecidos pelo usuário ou pelo programa chamador, arrays, telas, relatórios ou simples variáveis de trabalho. Dados estruturados Os dados utilizados por um programa COBOL são organizados numa hierarquia. Basicamente essa hierarquia é formada por itens de grupo e itens elementares. Em termos bem simples, um item elementar éuma variável. Um item de grupo é um conjunto de itens elementares. Vamos detalhar esse conceito através de um exemplo prático. A figura abaixo mostra um registro de dados. Você pode pensar num registro como se fosse uma linha num arquivo texto. Figura 6. Exemplo de registro de dadfos O registro Conta a Receber é formado pelos campos chave, código do cliente, data de emissão, data de vencimento, valor da duplicata, categoria e situação. O campo chave, por sua vez, é formado pelo número da fatura e pelo número da duplicata. Podemos visualizar essa estrutura como uma hierarquia de dados: Conta a Receber Chave Número da Fatura Número da Duplicata Código do Cliente Data de Emissão Data de Vencimento Valor da Duplicata Categoria Situação Para representar essa hierarquia no COBOL precisamos estabelecer níveis para cada “camada” de informação. Esses níveis são números que vão de 1 a 49, onde 01 é o nível mais alto e 49 o nível mais baixo possível. Assim, usando a notação do COBOL, nossa hierarquia de dados ficaria assim: 01 Conta a Receber 03 Chave 05 Número da Fatura 05 Número da Duplicata 03 Código do Cliente 03 Data de Emissão 03 Data de Vencimento 03 Valor da Duplicata 03 Categoria 03 Situação Repare que o registro Conta a Receber recebe o nível mais alto (01). As informações que compõem esse registro estão num nível mais baixo (03). O campo chave, por sua vez, é formado por itens elementares que estão num nível ainda mais baixo (05). Número da Fatura e Número da Duplicata são chamados de itens elementares, pois eles não se subdividem. Conta a Receber e Chave são chamados de itens de grupos, pois são formados por itens elementares. Alguns detalhes são importantes sobre a numeração de hierarquias: • O nível mais alto sempre deve receber o número 01. Abaixo dele, você pode escolher qualquer número entre 02 e 49. • Nesse exemplo, usamos os números 01, 03 e 05, mas poderíamos ter escolhido 01, 02 e 03; ou 01, 05, 10; ou 01, 10, 20… Desde que o nível de baixo tenha um número maior que o nível de cima, quaisquer números entre 02 e 49 seria válido. No entanto, é uma boa prática de programação numerar os níveis de dois em dois, ou cinco em cinco, deixando “espaço” para a criação de itens de grupo intermediários no futuro. • Não é obrigatório, mas é uma prática altamente recomendável, que todos os itens de um mesmo nível tenham a mesma numeração. No nosso exemplo, chave, código do cliente, data de emissão, data de vencimento, valor da duplicata, categoria e situação estão no mesmo nível hierárquico (imediatamente abaixo do registro conta a receber). Por esse motivo esses itens receberam o mesmo número de nível (03). • Quem determina a hierarquia entre os itens é o número de nível. A edentação procura apenas facilitar a leitura dos programadores. Dando nomes às variáveis A maioria dos compiladores exige que os nomes das variáveis na DATA DIVISION sejam formados por letras, números, alguns caracteres especiais (como hífen e underscore). O primeiro caracter desses nomes deve necessariamente ser alfabético. Muitos compiladores atualmente permitem o uso de letras maiúsculas e minúsculas na formação dos nomes, mas na grande maioria das vezes você verá apenas nomes formados por letras maiúsculas e hífens. Supondo que quiséssemos definir em nosso programa o registro conta a receber, do exemplo anterior, poderíamos adotar os seguintes nomes para os itens de grupo e itens elementares: 01 CONTA-RECEBER 03 CHAVE 05 NUMERO-FATURA 05 NUMERO-DUPLICATA 03 CODIGO-CLIENTE 03 DATA-EMISSAO 03 DATA-VENCIMENTO 03 VALOR-DUPLICATA 03 CODIGO-CATEGORIA 03 SITUACAO-DUPLICATA Cada empresa estabelece suas próprias convenções de nomenclatura para definição de variáveis. É comum, por exemplo, que alguns nomes mais frequentes sejam abreviados seguindo sempre um mesmo padrão. Por exemplo: NUMERO: NR CODIGO: CD DATA: DT VALOR: VL SITUACAO: ST NOME: NM MATRICULA: MT DESCRICAO: DS TIPO: TP Seguindo essa norma, nosso exemplo ficaria assim: 01 CONTA-RECEBER 03 CHAVE 05 NR-FATURA 05 NR-DUPLICATA 03 CD-CLIENTE 03 DT-EMISSAO 03 DT-VENCIMENTO 03 VL-DUPLICATA 03 CD-CATEGORIA 03 ST-DUPLICATA Tipos de dados O COBOL trabalha basicamente com dois tipos de dados: numérico e alfanumérico. Existe um terceiro tipo, chamado de alfabético, que só aceita letras e espaços. Por ser mais limitado, esse tipo raramente é utilizado, sendo quase sempre substituído pelo tipo alfanumérico. O que define o tipo de uma variável, seu tamanho e seu formato é a cláusula picture (PIC) codificada após o nome de cada variável. Seu formato mais simples é: • PIC 9(n), para variáveis numéricas, onde “n” deve ser substituído pelo tamanho da variável • PIC X(n), para variáveis alfanuméricas, onde “n” também deve ser substituído pelo tamanho da variável. Exemplos: Figura 7. Alguns exemplos com a cláusula picture Os dois últimos exemplos mostrados na figura anterior mostram algumas variações do tipo numérico. Usar um S na frente da picture indica que a variável pode ser sinalizada. Um V no meio da picture separa a parte inteira da parte decimal. Vale a pena salientar que o ponto ou vírgula decimal é apenas posicional: ele não ocupa espaço na variável. Voltemos ao exemplo do registro de conta a receber. Vamos supor que as variáveis tivessem as seguintes características: Figura 8: Características das variáveis do exemplo Itens de grupo não possuem cláusula picture, uma vez que seu tipo, tamanho e formato será determinado pelo tipo, tamanho e formato dos seus itens elementares. A variável NR-FATURA só receberá valores numéricos, de 000001 a 999999. Seis dígitos, portanto. Sua picture será 9(006). Já a variável NR-DUPLICATA também é numérica, mas receber valores que só vão de 00 a 99. Sua picture será 9(002). Costuma-se dizer que a primeira é uma variável “9 de 6”, e a segunda é uma variável “9 de 2”. A variável CD-CLIENTE receberá letras e/ou números, e pode ter no máximo 6 caracteres. Sua picture, portanto, será X(006). Costuma-se dizer que ela é uma variável “X de 6”. A variável VL-FATURA parece ser diferente, mas já vimos sua picture em um exemplo anterior. Como ela receberá valores com 13 dígitos na parte inteira e 2 dígitos na parte decimal, sua picture será 9(013)V9(002), ou S9(013)V9(002). O S, como já vimos, informa que a variável também poderá receber valores negativos. Não faz muito sentido um valor de duplicata ser menor que zeros, mas existe uma convenção de se usar variáveis sinalizadas para valores monetários. Declarado dessa forma, o sinal não ocupa espaço na variável; esta variável ocupa, na prática, 15 posições. Com a cláusula picture, nosso exemplo ficaria assim: 01 CONTA-RECEBER. 03 CHAVE. 05 NR-FATURA PIC 9(006). 05 NR-DUPLICATA PIC 9(002). 03 CD-CLIENTE PIC X(006). 03 DT-EMISSAO PIC 9(008). 03 DT-VENCIMENTO PIC 9(008). 03 VL-DUPLICATA PIC S9(013)V9(002). 03 CD-CATEGORIA PIC X(003). 03 ST-DUPLICATA PIC X(003). O alinhamento das pictures não é exigido pela linguagem, mas facilita a leitura do programador. Como não vamos colocar nada depois da picture, temos que encerrar cada sentença com um ponto. As variáveis DT-EMISSAO e DT-VENCIMENTO merecem um comentário adicional. Não existem variáveis do tipo date no COBOL; todas as variáveis ou são numéricas ou alfanuméricas. O formato AAAAMMDD, citado no exemplo, implica em quatro dígitos numéricos para ano, dois dígitos numéricos para mês e dois dígitos numéricos para dia, totalizando oito dígitos numéricos. Por esse motivo, nossas datas foram codificadas com picture 9(008). Se precisássemosfazer referencias específicas a dia, mês e/ou ano, poderíamos transformar essas datas em itens de grupo e incluir itens elementares sob elas, como no exemplo abaixo: 01 CONTA-RECEBER. 03 CHAVE. 05 NR-FATURA PIC 9(006). 05 NR-DUPLICATA PIC 9(002). 03 CD-CLIENTE PIC X(006). 03 DT-EMISSAO. 05 AA-EMISSAO PIC 9(004). 05 MM-EMISSAO PIC 9(002). 05 DD-EMISSAO PIC 9(002). 03 DT-VENCIMENTO. 05 AA-VENCIMENTO PIC 9(004). 05 MM-VENCIMENTO PIC 9(002). 05 DD-VENCIMENTO PIC 9(002). 03 VL-DUPLICATA PIC S9(013)V9(002). 03 CD-CATEGORIA PIC X(003). 03 ST-DUPLICATA PIC X(003). Um item de grupo se comporta como uma variável alfanumérica (PIC X) cujo tamanho é igual à soma dos tamanhos de seus itens elementares. No exemplo acima, CONTA- RECEBER tem tamanho 51, CHAVE tem tamanho 8, DT-EMISSAO e DT-VENCIMENTO também. Por se comportar como uma variável PIC X, é possível mover conteúdo para um item de grupo e recuperar parte desse seu conteúdo usando as variáveis elementares. Para dar um exemplo, considere o seguinte item de grupo 01 ENDERECO. 03 LOGRADOURO PIC X(020). 03 BAIRRO PIC X(010). 03 CIDADE PIC X(010). 03 ESTADO PIC X(002). 03 CEP PIC X(008). Se preenchermos ENDERECO com algum conteúdo, digamos… MOVE “RUA DO IMPERADOR 101 CENTRO PETROPOLISRJ24340000” TO ENDERECO …o valor da variável ESTADO será RJ. Detalhamento de arquivos convencionais Já vimos que a ENVIRONMENT DIVISION é a divisão onde declaramos todos os arquivos convencionais que serão acessados pelo programa. A ENVIRONMENT, no entanto, não informa quais são os registros de cada arquivo, nem que campos eles possuem. Esta é uma das funções da DATA DIVISION. Todos os arquivos declarados na ENVIRONMENT DIVISION precisam ser detalhados na DATA DIVISION, numa seção específica chamada FILE SECTION. A FILE SECTION deve ser declarada na coluna 8, logo depois do nome da divisão: *======================================================================* DATA DIVISION. *----------------------------------------------------------------------* FILE SECTION. Para mostrar como os arquivos são detalhados, partiremos da ENVIRONMENT DIVISION que codificamos no capítulo anterior: *======================================================================* ENVIRONMENT DIVISION. *----------------------------------------------------------------------* CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. INPUT-OUTPUT SECTION. FILE-CONTROL. *----------------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------------* SELECT CRA0205 ASSIGN TO “../dat/cra0205.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0205. *----------------------------------------------------------------------* * DUPLICATAS ATIVAS EMITIDAS NO PERIODO *----------------------------------------------------------------------* SELECT CRA0206 ASSIGN TO “../dat/cra0206.dat” ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0206. Vamos detalhar primeiro o arquivo CRA0205. Ele é um arquivo sequencial linear (um arquivo texto), cujos registros (linhas) possuem o seguinte layout: Figura 9. Layout do arquivo CRA0205 Para detalhar esse arquivo, incluiremos um parágrafo de file description (FD) na FILE SECTION. Dentro desse parágrafo colocaremos a definição do registro (um item de grupo com nível 01) e dentro do registro colocaremos as variáveis correspondentes a cada campo mostrado na figura anterior. O detalhamento do arquivo ficaria assim: *======================================================================* DATA DIVISION. *----------------------------------------------------------------------* FILE SECTION. *----------------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------------* FD CRA0205. 01 CRA0205-REGISTRO. 03 CRA0205-NR-FATURA PIC 9(006). 03 CRA0205-NR-DUPLICATA PIC 9(002). 03 CRA0205-CD-CLIENTE PIC X(006). 03 CRA0205-DT-EMISSAO PIC 9(008). 03 CRA0205-DT-VENCIMENTO PIC 9(008). 03 CRA0205-VL-FATURA PIC S9(013)V9(002). 03 CRA0205-CD-CATEGORIA PIC X(003). 03 CRA0205-ST-FATURA PIC X(003). Repare alguns detalhes sobre essa codificação: • É uma boa prática inserir comentários que descrevam o arquivo. Basicamente copiamos os mesmos comentários que já havíamos inserido na ENVIRONMENT DIVISION. • O parágrafo FD possui uma grande quantidade de opções e cláusulas adicionais que permitem ao programador descrever o tamanho do registro (em bytes), o tamanho de blocos (em quantidades de registros), o formato dos registros (se fixos ou variáveis), e assim por diante. No nosso exemplo, não usamos nada disso. O programa assumirá que os registros têm todos o mesmo tamanho (formato fixo) e que o tamanho dos registros será igual ao somatório dos tamanhos de cada campo. • Abaixo da declaração do arquivo (FD) temos um único item de grupo (nível 01). Isso acontece porque todas as linhas (registros) do nosso arquivo têm o mesmo layout. Se o arquivo tivesse linhas com layouts diferentes, teríamos um nível 01 para cada layout; • O COBOL exige que todas as declarações de variáveis, inclusive a declaração do registro, terminem com um ponto; • Todos os campos do registro são itens elementares (possuem pictures). Nada impediria que o layout tivesse itens de grupo agrupado alguns itens elementares, mas isso não foi necessário nesse exemplo; • Usar o nome do arquivo como prefixo dos campos (CRA0205-…) não é obrigatório; é apenas um dos muitos padrões de nomenclatura que as empresas adotam e é uma boa prática de programação. Mais adiante, quando estivermos codificando o algoritmo na PROCEDURE DIVISION, será importante identificar rapidamente se estamos trabalhando com uma variável de trabalho, com um campo de arquivo, com um parâmetro externo etc. • O detalhamento do arquivo na FILE SECTION não diz se o programa vai ler, gravar, atualizar ou excluir registros. Isso será feito na PROCEDURE DIVISION. Vamos seguir o mesmo princípio para detalhar o segundo arquivo, CRA0206. Apenas para facilitar o exemplo, usaremos o mesmo layout do primeiro. Logo, as declarações serão praticamente iguais. Copiaremos as linhas anteriores e alteraremos apenas o comentário, o nome do arquivo e o prefixo das variáveis. Nossa FILE SECTION ficaria assim: *======================================================================* DATA DIVISION. *----------------------------------------------------------------------* FILE SECTION. *----------------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------------* FD CRA0205. 01 CRA0205-REGISTRO. 03 CRA0205-NR-FATURA PIC 9(006). 03 CRA0205-NR-DUPLICATA PIC 9(002). 03 CRA0205-CD-CLIENTE PIC X(006). 03 CRA0205-DT-EMISSAO PIC 9(008). 03 CRA0205-DT-VENCIMENTO PIC 9(008). 03 CRA0205-VL-FATURA PIC S9(013)V9(002). 03 CRA0205-CD-CATEGORIA PIC X(003). 03 CRA0205-ST-FATURA PIC X(003). *----------------------------------------------------------------------* * DUPLICATAS ATIVAS EMITIDAS NO PERIODO *----------------------------------------------------------------------* FD CRA0206. 01 CRA0206-REGISTRO. 03 CRA0206-NR-FATURA PIC 9(006). 03 CRA0206-NR-DUPLICATA PIC 9(002). 03 CRA0206-CD-CLIENTE PIC X(006). 03 CRA0206-DT-EMISSAO PIC 9(008). 03 CRA0206-DT-VENCIMENTO PIC 9(008). 03 CRA0206-VL-FATURA PIC S9(013)V9(002).03 CRA0206-CD-CATEGORIA PIC X(003). 03 CRA0206-ST-FATURA PIC X(003). Variáveis e constantes de trabalho Dificilmente você codificará (ou modificará) um programa que não precise de algumas variáveis de trabalho. Normalmente elas são utilizadas para armazenar informações temporárias (contadores, acumuladores, resultados intermediários…), sinalizar estados do programa (flags), ou formatar saídas para telas e relatórios. Todas as variáveis de trabalho do COBOL são declaradas na segunda seção da DATA DIVISION, que se chama WORKING-STORAGE SECTION. Essa seção também precisa ser codificada na coluna 8: *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* As regras para formação de nomes, a estrutura hierárquica em níveis, e as pictures que vimos até aqui são as mesmas que utilizaremos na criação de variáveis de trabalho, com alguns poucos recursos adicionais. Vamos supor que precisemos de dois contadores em nosso programa. Um para contar a quantidade de registros lidos e outro para contar a quantidade de registros gravados. Para isso, criaremos duas variáveis numéricas de trabalho, que comportem até seis dígitos (valor máximo 999.999) e que poderemos chamar de WT-CT-LIDOS e WT-CT-GRAVADOS. Uma das muitas opções possíveis para declarar essas variáveis é: *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* 01 WT-CT-LIDOS PIC 9(006). 01 WT-CT-GRAVADOS PIC 9(006). No entanto, não é comum criar itens elementares no nível 01. O COBOL permite a criação de itens elementares isolados (que não fazem parte de nenhum item de grupo) com um nível especial, de número 77. *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* 77 WT-CT-LIDOS PIC 9(006). 77 WT-CT-GRAVADOS PIC 9(006). Frequentemente encontramos programas com variáveis de trabalho criadas no nível 77. Mas essa não é uma boa prática de programação. Um programa grande tende a ter muitas variáveis, e colocá-las indistintamente, uma embaixo da outra, pode dificultar a leitura do programa no futuro. Por esse motivo, é recomendável agrupar nossos itens elementares em itens de grupo que destaquem a finalidade de suas variáveis: *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* 01 WT-CONTADORES. 03 WT-CT-LIDOS PIC 9(006). 03 WT-CT-GRAVADOS PIC 9(006). Quando um programa COBOL é carregado, suas variáveis de trabalho não têm valores iniciais; normalmente seu conteúdo está preenchido com o que chamamos de “lixo de memória”. Isso pode ser um problema principalmente para variáveis numéricas, pois um lixo alfanumérico numa variável numérica certamente fará o programa encerrar imediatamente, de forma anormal. Para evitar que isso aconteça é altamente recomendável que todas as variáveis de trabalho da WORKING-STORAGE SECTION sejam iniciadas com algum valor, compatível com seus tipos. Na declaração de nossos contadores devemos colocar uma cláusula VALUE após a picture: *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* 01 WT-CONTADORES. 03 WT-CT-LIDOS PIC 9(006) VALUE ZEROS. 03 WT-CT-GRAVADOS PIC 9(006) VALUE ZEROS. A constante figurativa ZEROS é autoexplicativa: indica que queremos que as variáveis sejam iniciadas com valor zero. Para variáveis alfanuméricas normalmente usamos a constante figurativa SPACES, que preenche a variável com espaços em branco. Quando declaramos nossos arquivos na ENVIRONMENT DIVISION dissemos que os códigos de retorno (file status) dos arquivos CRA0205 e CRA0206 ficariam nas variáveis WT-ST-CRA0205 e WT-ST-CRA0206, respectivamente. Variáveis para file status são alfanuméricas com dois caracteres. Vamos criar um item de grupo específico essas variáveis: *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* 01 WT-CONTADORES. 03 WT-CT-LIDOS PIC 9(006) VALUE ZEROS. 03 WT-CT-GRAVADOS PIC 9(006) VALUE ZEROS. 01 WT-FILE-STATUS. 03 WT-ST-CRA0205 PIC X(002) VALUE SPACES. 03 WT-ST-CRA0206 PIC X(002) VALUE SPACES. Aqui, estamos colocando um prefixo WT- antes do nome das variável. Quando encontrarmos uma delas em nossa PROCEDURE DIVISION, ficará óbvio que se trata de uma variável de trabalho definida na WORKING-STORAGE. Diversos outros prefixos do tipo W?- são recomendáveis para a declaração de variáveis. Podemos usar, por exemplo, WS- para variáveis que serão usadas em telas, WR- para variáveis que serão usadas em relatórios, e assim por diante. Cada empresa estabelece seu próprio padrão de nomenclatura e é importante que ele seja sempre respeitado para garantir a coesão semântica de todos os sistemas. Exemplo completo Neste capítulo, pouco a pouco, codificamos a DATA DIVISION de um programa que contém arquivos convencionais e seus campos (na FILE SECTION) e variáveis de trabalho (na WORKING-STORAGE SECTION). A versão completa da DATA DIVISION ficou assim: *======================================================================* DATA DIVISION. *----------------------------------------------------------------------* FILE SECTION. *----------------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------------* FD CRA0205. 01 CRA0205-REGISTRO. 03 CRA0205-NR-FATURA PIC 9(006). 03 CRA0205-NR-DUPLICATA PIC 9(002). 03 CRA0205-CD-CLIENTE PIC X(006). 03 CRA0205-DT-EMISSAO PIC 9(008). 03 CRA0205-DT-VENCIMENTO PIC 9(008). 03 CRA0205-VL-FATURA PIC S9(013)V9(002). 03 CRA0205-CD-CATEGORIA PIC X(003). 03 CRA0205-ST-FATURA PIC X(003). *----------------------------------------------------------------------* * DUPLICATAS ATIVAS EMITIDAS NO PERIODO *----------------------------------------------------------------------* FD CRA0206. 01 CRA0206-REGISTRO. 03 CRA0206-NR-FATURA PIC 9(006). 03 CRA0206-NR-DUPLICATA PIC 9(002). 03 CRA0206-CD-CLIENTE PIC X(006). 03 CRA0206-DT-EMISSAO PIC 9(008). 03 CRA0206-DT-VENCIMENTO PIC 9(008). 03 CRA0206-VL-FATURA PIC S9(013)V9(002). 03 CRA0206-CD-CATEGORIA PIC X(003). 03 CRA0206-ST-FATURA PIC X(003). *======================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------------* 01 WT-CONTADORES. 03 WT-CT-LIDOS PIC 9(006) VALUE ZEROS. 03 WT-CT-GRAVADOS PIC 9(006) VALUE ZEROS. 01 WT-FILE-STATUS. 03 WT-ST-CRA0205 PIC X(002) VALUE SPACES. 03 WT-ST-CRA0206 PIC X(002) VALUE SPACES. No próximo capítulo, veremos como esses dados serão efetivamente processados pelo programa. 6. Procedure Division Até aqui vimos três das quatro divisões que compõem um programa COBOL, na ordem em que elas devem ser codificadas. A última divisão, que veremos neste capítulo, é onde ficam as instruções que serão executadas pelo programa. Toda a lógica programação estará nessas instruções. Recapitulando, a IDENTIFICATION DIVISION contém informações documentacionais sobre o programa. A ENVIRONMENT descreve o ambiente em que o programa será executado, indicando também os arquivos que serão acessados. A DATA DIVISION detalha esses arquivos e declara variáveisde trabalho. É na PROCEDURE DIVISION, finalmente, que os arquivos são lidos e processados para produzir alguma informação de saída. Neste capítulo veremos como abrir arquivos de entrada e saída, como ler e escrever informações nesses arquivos, como atribuir valores aos campos dos arquivos e às variáveis de trabalho, como realizar operações aritméticas, como controlar o fluxo de execução do programa e encerrar sua execução. O conhecimento dessas instruções é suficiente para construção de programas completos, ainda que elementares. Parágrafos e sentenças Como em todas as outras divisões, a PROCEDURE é dividida em parágrafos. Cada parágrafo deve ter um nome atribuído pelo programador, e esse nome deve ser único dentro do programa. Os nomes dos parágrafos podem ser formados por letras, números e hífens. E, naturalmente, cada empresa estabelece seu próprio padrão de nomenclatura. Dentro de cada parágrafo estarão as sentenças (ou instruções) do programa. Toda sentença começa com um verbo em inglês: READ, MOVE, WRITE, ADD… A única exceção para essa regra é a instrução que usamos para testar condições (IF). Os nomes dos parágrafos devem ser codificados a partir da coluna 8 (área A) e terminar obrigatoriamente com um ponto. As sentenças devem ser codificadas a partir da coluna 12 (área B). Apenas a última sentença de um parágrafo precisa de um ponto final. O COBOL permite que se use várias sentenças numa única linha de programa, mas essa prática não é recomendada pois dificulta a leitura do programa. Parágrafos assumem papeis diferentes, dependendo do paradigma de codificação que será usado pelo programador. Na programação linear (em desuso), parágrafos funcionam como labels ou tags que marcam um ponto para onde o fluxo de execução do programa pode ser desviado. Na programação estruturada (praticamente obrigatória em todas as instalações) parágrafos atuam como rotinas que têm uma finalidade específica, como se fossem métodos ou funções (ainda que esses dois conceitos não se apliquem diretamente ao COBOL). Falaremos sobre programação linear e programação estruturada mais adiante. Por ora, iremos apenas ilustrar esses modelos com dois exemplos simples. PARAGRAFO-1. SENTENÇA-1 SENTENÇA-2 SENTENÇA-3. PARAGRAFO-2. SE CONDIÇAO-1 GO TO PARAGRAFO-3 FIM-SE SENTENÇA-4 SENTENÇA-5 SENTENÇA-6 GO TO PARAGRAFO-2. PARAGRAFO-3. SENTENÇA-7 SENTENÇA-8 SENTENÇA-9 FIM DO PROGRAMA. O pseudocódigo acima mostra como os parágrafos são usados na programação linear. Perceba que PARAGRAFO-2 e PARAGRAFO-3 são apenas pontos de referência para onde o fluxo de execução é desviado com um comando GO TO. PARAGRAFO-2 claramente é um loop, que termina quando a CONDIÇAO-1 é satisfeita. Na programação estruturada, por outro lado, parágrafos são usados para organizar o programa em blocos que possuem uma finalidade única, (preferencialmente), como veremos no trecho a seguir: INICIO. EXECUTE PARAGRAFO-1 EXECUTE PARAGRAFO-2 ATE’ CONDIÇAO-1 EXECUTE PARAGRAFO-3 FIM DO PROGRAMA. PARAGRAFO-1. SENTENÇA-1 SENTENÇA-2 SENTENÇA-3. PARAGRAFO-2. SENTENÇA-4 SENTENÇA-5 SENTENÇA-6. PARAGRAFO-3. SENTENÇA-7 SENTENÇA-8 SENTENÇA-9. Repare que estamos executando as mesmas instruções que vimos no modelo linear (SENTENÇA-1, SENTENÇA-2…). Mas agora essas sentenças estão organizadas em blocos que são executados no início do programa. PARAGRAFO-2 é executado até que a CONDIÇÃO-1 seja satisfeita: é o mesmo loop que vimos anteriormente mas, nesse caso, não precisamos usar o comando GO TO. É possível perceber que um grande programa linear, com diversos GO TO’s para todo lado, pode ser muito fácil de codificar, mas muito mais difícil de entender no futuro. A programação estruturada, porém, exige que o programador “pense” um pouco mais antes de começar a codificar, mas o entendimento do programa fica muito mais fácil no futuro. Nas próximas seções, apenas para efeito didático, codificaremos nosso primeiro programa seguindo uma lógica linear. No capítulo seguinte falaremos mais sobre programação estruturada e reconstruiremos nosso programa usando esse modelo. Construindo o primeiro programa Vamos imaginar um programa que tenha por objetivo ler um arquivo sequencial, selecionar alguns registros e gravar os registros selecionados num arquivo sequencial de saída. Para isso aproveitaremos tudo o que fizemos nos capítulos anteriores. Juntando a IDENTIFICATION, a ENVIRONMENT e a DATA DIVISION nosso programa, neste momento, estaria assim: *================================================================* IDENTIFICATION DIVISION. *----------------------------------------------------------------* PROGRAM-ID. CRP0206. AUTHOR. PAULO ANDRE DIAS. DATE-WRITTEN. 23/12/2016. REMARKS. *----------------------------------------------------------------* * SISTEMA: CR - CONTAS A RECEBER * JOB: 02 - GERACAO DE FLUXO DE CAIXA * PROGRAMA: 06 - SELECIONA DUPLICATAS ATIVAS * * OBJETIVO: GERAR ARQUIVO DE SAIDA QUE CONTEM APENAS AS DU- * PLICATAS QUE NAO FORAM CANCELADAS (SITUACAO DA * DUPLICATA DEVE SER DIFERENTE DE "CNC") * * VERSOES: DATA DESCRICAO * ------ --------------------------------------- * XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX * *----------------------------------------------------------------* *================================================================* ENVIRONMENT DIVISION. *----------------------------------------------------------------* CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. INPUT-OUTPUT SECTION. FILE-CONTROL. *----------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------* SELECT CRA0205 ASSIGN TO "../dat/cra0205.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0205. *----------------------------------------------------------------* * DUPLICATAS ATIVAS EMITIDAS NO PERIODO *----------------------------------------------------------------* SELECT CRA0206 ASSIGN TO "../dat/cra0206.dat" ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS WT-ST-CRA0206. *================================================================* DATA DIVISION. *----------------------------------------------------------------* FILE SECTION. *----------------------------------------------------------------* * UNLOAD DA TABELA DE DUPLICATAS *----------------------------------------------------------------* FD CRA0205. 01 CRA0205-REGISTRO. 03 CRA0205-NR-FATURA PIC 9(006). 03 CRA0205-NR-DUPLICATA PIC 9(002). 03 CRA0205-CD-CLIENTE PIC X(006). 03 CRA0205-DT-EMISSAO PIC 9(008). 03 CRA0205-DT-VENCIMENTO PIC 9(008). 03 CRA0205-VL-FATURA PIC S9(013)V9(002). 03 CRA0205-CD-CATEGORIA PIC X(003). 03 CRA0205-ST-DUPLICATA PIC X(003). *----------------------------------------------------------------* * DUPLICATAS ATIVAS EMITIDAS NO PERIODO *----------------------------------------------------------------* FD CRA0206. 01 CRA0206-REGISTRO. 03 CRA0206-NR-FATURA PIC 9(006). 03 CRA0206-NR-DUPLICATA PIC 9(002). 03 CRA0206-CD-CLIENTE PIC X(006). 03 CRA0206-DT-EMISSAO PIC 9(008). 03CRA0206-DT-VENCIMENTO PIC 9(008). 03 CRA0206-VL-FATURA PIC S9(013)V9(002). 03 CRA0206-CD-CATEGORIA PIC X(003). 03 CRA0206-ST-DUPLICATA PIC X(003). *================================================================* WORKING-STORAGE SECTION. *----------------------------------------------------------------* 01 WT-CONTADORES. 03 WT-CT-LIDOS PIC 9(006) VALUE ZEROS. 03 WT-CT-GRAVADOS PIC 9(006) VALUE ZEROS. 01 WT-FILE-STATUS. 03 WT-ST-CRA0205 PIC X(002) VALUE SPACES. 03 WT-ST-CRA0206 PIC X(002) VALUE SPACES. A PROCEDURE DIVISION começa imediatamente depois da WORKING-STORAGE SECTION, e como todas as divisões ela deve ser declarada a partir da coluna 8. Logo em seguida, criaremos o primeiro parágrafo do programa, que chamaremos de INICIO-DO- PROGRAMA, também na coluna 8: *================================================================* PROCEDURE DIVISION. *----------------------------------------------------------------* INICIO-DO-PROGRAMA. Nosso programa vai ler todos os registros do arquivo de entrada (CRA0205), selecionar apenas os registros cujo campo ST-DUPLICATA seja diferente de “CNC” (cancelado) e gravar os registros selecionados no arquivo de saída (CRA0206). Antes de terminar, o programa deverá mostrar a quantidade de registros lidos e a quantidade de registros gravados. O fluxograma abaixo detalha um pouco mais essa lógica: Figura 10. Fluxo do programa CRP0206 Abertura de arquivos Todo arquivo precisa ser “aberto” pelo programa para que possamos ler ou gravar registros nele. Qualquer operação de leitura ou escrita de registros num arquivo que não foi previamente aberto provocará um erro de execução que será sinalizado no file status correspondente. A abertura de arquivos é comandada pela instrução OPEN, que tem o seguinte formato: OPEN modo nome-do-arquivo O operador “modo” informa se vamos acessar o arquivo para leitura (INPUT) ou gravação (OUTPUT). O “nome do arquivo” que aparece no comando OPEN deve ser igual ao nome informado na cláusula FD da FILE SECTION. Existem outros modos possíveis nesse comando. OPEN I-O abre um arquivo para leitura e gravação; esse é o modo que nos permite, por exemplo, atualizar (REWRITE) os registros de um arquivo. OPEN EXTEND nos permite inserir registros no final de um arquivo já existente. Falaremos mais sobre esses dois modos mais adiante neste livro. Por enquanto é importante notar que OPEN I-O e OPEN EXTEND preservam o conteúdo existente no arquivo. Já OPEN OUTPUT apaga todo o conteúdo existente e prepara o arquivo para a gravação de novos registros. O COBOL permite que um único comando OPEN seja usado para abrir vários arquivos de leitura e gravação ao mesmo tempo: OPEN INPUT arquivo1 arquivo2 arquivo3 OUTPUT arquivo4 arquivo5 arquivo6 I-O arquivo7 arquivo8 arquivo9 No exemplo acima, arquivo1, arquivo2 e arquivo3 estão sendo abertos para leitura; arquivo4, arquivo5 e arquivo6 estão sendo abertos para gravação; arquivo7, arquivo8 e arquivo9 estão sendo abertos tanto para operações de leitura quanto de gravação. Sabemos que nosso programa precisa ler todos os registros do arquivo CRA0205 e gravar os registros selecionados no arquivo CRA0206. Portanto, nossas primeiras instruções ficariam assim: *================================================================* PROCEDURE DIVISION. *----------------------------------------------------------------* INICIO-DO-PROGRAMA. OPEN INPUT CRA0205 OPEN OUTPUT CRA0206 Que podem ser unidos num só comando... *================================================================* PROCEDURE DIVISION. *----------------------------------------------------------------* INICIO-DO-PROGRAMA. OPEN INPUT CRA0205 OUTPUT CRA0206 Leitura de arquivos READ é o comando COBOL responsável por ler o conteúdo de arquivos. Seu formato mais simples é: READ nome-do-arquivo O nome do arquivo fornecido ao comando deve ser igual ao nome que usamos no comando OPEN. Quando usado com arquivos sequenciais, a leitura acontece registro a registro, isto é, cada vez que o comando READ é executado, o programa busca o próximo registro disponível no arquivo e copia seu conteúdo para o item de grupo (nível 01) que definimos na FILE SECTION. Usando nosso programa como exemplo, o arquivo CRA0205 foi declarado na ENVIRONMENT DIVISION e apontado para um arquivo sequencial cujo nome real é “../dat/cra0205.dat”: SELECT CRA0205 ASSIGN TO "../dat/cra0205.dat" ORGANIZATION IS LINE SEQUENTIAL. Em seguida, detalhamos esse arquivo na FILE SECTION da DATA DIVISION: FD CRA0205. 01 CRA0205-REGISTRO. 03 CRA0205-NR-FATURA PIC 9(006). 03 CRA0205-NR-DUPLICATA PIC 9(002). 03 CRA0205-CD-CLIENTE PIC X(006). 03 CRA0205-DT-EMISSAO PIC 9(008). 03 CRA0205-DT-VENCIMENTO PIC 9(008). 03 CRA0205-VL-FATURA PIC S9(013)V9(002). 03 CRA0205-CD-CATEGORIA PIC X(003). 03 CRA0205-ST-DUPLICATA PIC X(003). Agora, na PROCEDURE DIVISION, codificaremos o comando READ da seguinte maneira: *================================================================* PROCEDURE DIVISION. *----------------------------------------------------------------* INICIO-DO-PROGRAMA. OPEN INPUT CRA0205 OUTPUT CRA0206 READ CRA0205 Quando este comando for executado pela primeira vez, o conteúdo do primeiro registro do arquivo “../dat/cra0205.dat” será copiado para o item de grupo CRA0205-REGISTRO. Já vimos que quando um item de grupo é preenchido, seus itens elementares assumem os valores que estão nas posições correspondentes. Se o primeiro registro do arquivo for… 11111122ABCDEF2015102520151125000000000012300QRTATV O registro inteiro será copiado para CRA0205-REGISTRO e, consequentemente, seus itens elementares assumirão os seguintes valores: CRA0205-NR-FATURA = 111111 CRA0205-NR-DUPLICATA = 22 CRA0205-CD-CLIENTE = ABCDEF CRA0205-DT-EMISSAO = 20151025 CRA0205-DT-VENCIMENTO = 20151125 CRA0205-VL-FATURA = 123,00 CRA0205-CD-CATEGORIA = QRT CRA0205-ST-DUPLICATA = ATV Cada vez que o comando READ CRA0205 for executado, o programa buscará o próximo registro do arquivo e copiará o conteúdo desse registro para CRA0205-REGISTRO, substituindo os valores anteriores. Testando condições O IF é o comando que utilizamos quando queremos testar uma condição em COBOL. Seu formato mais simples é: IF condição Comando(s) ELSE Comando(s) END-IF A cláusula END-IF pode ser substituída por um ponto e talvez você ainda encontre programas assim, principalmente se foram escritos para compiladores anteriores ao COBOL/85. No entanto, o uso de END-IF é preferível pois aumenta a flexibilidade para a construção de IFs aninhados: IF condição-1 Comando(s) IF condiçãoo-2 Comando(s) ELSE Comando(s) END-IF ELSE Comando(s) IF Condição-3 Comando(s) ELSE Comando(s) END-IF END-IF As condições testadas pelo IF normalmente envolvem dois operandos (variáveis, literais ou fórmulas) e um conector de relacionamento: GREATER THAN (>), LESS THAN (<) ou EQUAL TO (=). Exemplos: IF CRA0205-VL-FATURA > ZEROS IF CRA0205-VL-FATURA IS GREATER THAN ZEROS Essas duas linhas estão fazendo exatamente o mesmo tipo de teste; a única diferença é que na linha de baixo se escreve mais… resquícios da época em que o COBOL queria se parecer com um texto escrito em inglês. É possível também “negar” esses conectores colocando a palavra NOT na frente deles. Por exemplo: IF CRA0205-VL-FATURA NOT > 1000 IF CRA0205-DT-EMISSAO NOT = ZEROS IF CRA0205-CD-CATEGORIA
Compartilhar