Il COBOL - Jurassic News
Transcript
Il COBOL - Jurassic News
Tullio Nicolussi Il COBOL J urassic B ook s Jurassic Book - Tullio Nicolussi - Il COBOL Title: Il COBOL Author: Tullio Nicolussi Acquisitions Editor: Bes Delsec Technical Editor: Tullio Nicolussi Production Editor:Bes Delsec Production Manager: Tullio Nicolussi Book Designer: Anna Cover Designer: Anna Copyright © 2008 by Jurassic News Published in Italy First edition 2009 ISBN: na This publication may be reproduced, stored in a retrieval system or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, scanning or otherwise, only in integral form. Distribution on-line from http://www.jurassicnews.com Limit of Liability/Disclaimer of Warranty: The publisher and the author make no representations or warranties with respect to the accuracy or completeness of the contents of this work and specifically disclaim all warranties, including without limitation warranties of fitness for a particular purpose. For general information on our other products and services or to obtain technical support, please contact our Customer Care Department at [email protected] Library of Congress Cataloging-in-Publication Data Nicolussi, Tullio. Il COBOL / Tullio Nicolussi. - 1st ed. ISBN na 1. Computer programming 2. Computer language 3. Computer manual. TRADEMARKS: Jurassic News, is not associated with any product or vendor mentioned in this book. 10 9 8 7 6 5 4 3 2 1 0 2 Jurassic Book - Tullio Nicolussi - Il COBOL Sommario Introduzione .........................................................................................................................4 Overview .........................................................................................................................6 Il primo programma .......................................................................................................................10 Il Bubble Sort in COBOL .......................................................................................................................12 Le Variabili Strutturate .......................................................................................................................19 La Gestione dei File .......................................................................................................................26 La Gestione del Video .......................................................................................................................32 Conclusione .......................................................................................................................37 3 Jurassic Book - Tullio Nicolussi - Il COBOL COBOL Introduzione R ileggendo la prima stesura di questo articolo ho visto (con orrore) che avevo scritto le solite cose che si dicono quando si spolvera un vecchio software e in particolare un linguaggio di programmazione che non gode più dei favori degli sviluppatori, cioè qualcosa come: -“che questo è un peccato, che in realtà il linguaggio non ha nulla da invidiare ai più moderni idiomi, che ancora viene usato con profitto,...” e via di questo passo fra un rammarico e un sospiro. Il bello è che per il COBOL tutto questo corrisponde alla verità! Ma perché allora quando se ne sussurra il nome gli studenti sghignazzano, i guro della programmazione si fanno due volte il segno della croce (che vuol dire che invocano il dio C++) e i colleghi più giovani scuotono il capo e mentre si allontanano si coglie chiara la frase “...pronto per la pensione...”? Ehi, un po’ di rispetto, che diamine! Per essere onesti non si deve negare che qualche acciacco ahinoi il linguaggio per eccellenza della programmazione gestionale non riesce a nasconderlo. Qualche iniezione di “Gerovital” in forma di query SQL è valsa a migliorarne taluni aspetti nascondendo le artri4 ti reumatoidi dei file indexed. Parimenti le stampelle della programmazione per eventi sono valse a traghettare l’idioma nelle acque assai agitate della programmazione Windows. Per finire la clonazione sotto forma di linguaggi embedded nei sistemi ERP (vedi ad esempio SAP), hanno arginato il fuggi fuggi generale dei cervelli programmatoidi che rischiava di lasciare milioni di righe di codice prive di qualsiasi possibilità di manutenzione. Eppure ancora oggi dove l’idea di classe regna indiscussa, il COBOL rimane una buona scelta in molte circostanze. Questa considerazione è valida per la quasi totalità dei linguaggi di programmazione che sono stati inventati nella storia dell’informatica (parecchie centinaia se contiamo anche i dialetti). Dipende tutto dalle circostanze in cui si opera, dai sistemi di cui si dispone e dalle prestazioni dei tool di sviluppo dei quali possiamo avvalerci. La fortuna di un linguaggio è determinata da una serie di circostanze contingenti che dipendono molto anche dalle mode, oltre che naturalmente dallo scopo con il quale esso viene progettato. L’Assembly ad esempio nasce con i microprocessori e rimane l’indiscusso re della programmazione a basso livello. Non è stato inventato niente di meglio perché è perfetto Jurassic Book - Tullio Nicolussi - Il COBOL così com’è. I problemi di concorrenza si pongono quando più linguaggi si sovrappongono per funzionalità specifiche dell’ambiente in cui operano. Ad esempio VBSCRIPT piuttosto che PHP, Python piuttosto che Ruby, etc, nella programmazione Web. Il COBOL ha rappresentato per un paio di decenni la soluzione indiscussa nell’ambito della programmazione gestionale e rimane tutt’ora uno strumento molto usato in questo ambito. Fino a pochi anni fa si calcolava esistessero molte più righe di COBOL al mondo di quante ne potesse vantare il C. Non sono a conoscenza del rapporto esistente in questo momento ma credo che sebbene il C possa vantare la palma del vincitore in questa gara, il COBOL non sia molto distante dal podio. 5 Jurassic Book - Tullio Nicolussi - Il COBOL COBOL - Overview L ’insegnamento del linguaggio COBOL è stato per anni appannaggio della scuola secondaria a indirizzo tecnico. Qualunque istituto pretendesse di sfornare programmatori doveva tenerne conto ed approntare per esso specifici corsi. Le banche e la finanza in genere hanno assorbito moltissima forza lavoro dedicata al settore dell’elaborazione dei dati e se andavi a lavorare lì non avevi speranza: era COBOL a pranzo e cena! Appena possibile le scuole si sono liberare da questo fardello, perché? A mio giudizio le cause sono diverse ma fra le principali non mancano le seguenti: - una pretesa di modernità, visto che ad un certo punto, come detto prima, se parlavi di COBOL venivi deriso; - la mancanza di insegnanti preparati unita ad una certa difficoltà, peraltro obiettiva, di insegnare la programmazione usando questo linguaggio; - la diffusione del Personal Computer e la conseguente diffusione di linguaggi più semplici, anche e meno potenti, come ad esempio il Basic. Delle tre a mio giudizio l’ultima è quella chiave: se trovi il Basic nella macchina finirai per usare solo quello! Che dire della difficoltà di apprendimento della quale il linguaggio è stato accusato? Il problema nasce 6 tutto dalla sua prolissità. Infatti il COBOL nasce con intenti molto ambiziosi come la cross-compilation ad esempio; è possibile sviluppare su un sistema e trasferire su un’altra macchina, purché supportata. Il contesto dove viene messo a punto è quello dei sistemi mainframe e mini dipartimentali e soprattutto per i primi la cross-compilation è essenziale. La pesantezza della sintassi viene, diciamo così, aggravata dalla ricchezza delle estensioni. Una istruzione può essere usata in forma semplice ma può essere estremamente strutturata per svolgere molteplici compiti, essenzialmente di tipo ripetitivo. Facciamo un esempio per capire meglio questo punto. Prendiamo l’istruzione di addizione che si può scrivere con l seguente sintassi: ADD A TO B. che tradotto sarebbe somma il contenuto della variabile A con il contenuto della variabile B e metti il risultato in B. Qualcosa come: B = B + A Per incrementare un contatore di una unità si userebbe: ADD 1 TO INDICE Fino a qui nulla di particolarmente sconvolgente, la sintassi è leggermente diversa rispetto ai linguaggi correnti che per la maggior parte Jurassic Book - Tullio Nicolussi - Il COBOL utilizzano una notazione “tipo formula”, che fra l’altro è possibile utilizzare anche in COBOL scrivendo l’istruzione precedente come: ADD 123,67 TO R1 ROUNDED R2 R3. Ancora, è anche possibile che COMPUTE IND = IND + 1. non si voglia “sporcare” il valore dell’operando ottenendo un comE se dobbiamo sommare una se- portamento più classico che preverie di numeri? de lo store del risultato in una variabile a parte. Per fare ciò si usa una ADD N1 N2 N3 TO RIS. variante dell’istruzione ADD: Che, come avrete certo capito significa: RIS = RIS + N1 + N2 + N3 Ma le possibilità non si esauriscono qui. Consideriamo lo statement seguente: ADD A1 A2 A3 TO B1 B2 B3 B4. Questa sintassi è meno intuibile e significa: somma i valori A1, A2 e A3 poi aggiungi questo risultato alle variabile B1, B2, B3 e B4. Ovviamente è sempre possibile espandere l’istruzione in più statement ottendeno ad esempio: ADD A1 A2 A3 TO R. ADD R TO B1. ADD R TO B2. ADD R TO B3. ADD R TO B4. Qualcuno degli operandi che accoglieranno il risultato possono essere arrotondati aggiungendo la specifica opzione ROUNDED dopo i nome, come in: ADD IMPORTO IVA GIVING IMPORTO-IVATO. Si capisce che la sintassi del linguaggio è molto articolata e questo mette sicuramente in difficoltà chi cerchi di utilizzarlo leggendo un manuale. L’istruzione MOVE è l’esempio più eclatante, se vogliamo, ad onta della sua semplicità (serve per caricare i valori nelle variabili), infatti essa è ricchissima di varianti, al punto che le pagine dei manuali ad essa dedicata scoraggiano il malcapitato che volesse imparare il linguaggio da autodidatta basandosi solo sulla documentazione tecnica. L’istruzione MOVE carica i valori nelle variabili, come in: MOVE 1 TO INDICE. MOVE N1 TO R2. Niente di più semplice, apparentemente. Però qualsiasi manuale COBOL che ne riporta la descrizione e sintassi completa occuperà pagine e pagine! Un’altro aspetto del linguaggio può essere chiamato in causa per 7 Jurassic Book - Tullio Nicolussi - Il COBOL giustificarne la difficoltà di apprendimento, ed è la sintassi rigida detta in gergo informatico “a campi”. Significa che ogni elemento del linguaggio deve stare in certe zone definite della riga. Retaggio derivato dall’uso delle schede perforate come la lunghezza di 72 caratteri massima e la necessità di distinguere fisicamente gli elementi di un programma. Per creare un programmatore COBOL professionista una azienda deve essere disposta ad investire almeno tre anni di formazione/ affiancamento e questo oggigiorno viene considerato un costo, piuttosto che un investimento. C’è da dire un’ultima cosa sull’uso del linguaggio, che è la seguente: pochi, se non addirittura pochissimi, programmatori utilizzano la ricchezza sintattica del linguaggio. Nel tempo si è creato in tutte le aziende una sorta di “lessico famigliare”, per dirla alla Gizburg, che prevede l’utilizzo di costrutti il più elementare possibile, anche per una ragione di manutenzione del software stesso. Le nuove generazioni di programmatori e i tempi di consegna sempre più stringenti non lasciano speranze di procedere altrimenti. Forse esiste un assioma che implica la longevità di un linguaggio di programmazione direttamente correlata con la ricchezza sintattica. Succede che all’inizio esce una versione spartana e minimale, poi a furia di aggiungere features si finisce per snatuare l’idea originale e si 8 rende la curva di apprendimento sempre più ripida e lunga. Autorevoli esempi li troviamo nel Perl, nel PHP e nel Basic. Dovuta alla ricchezza della sintassi deriva la difficoltà nel costruire un compilatore, aumentata dal fatto che il linguaggio possiede obbligatoriamente embedded capacità di gestione per i file indicizzati (che come vedremo nel prosieguo di questa serie è la vera forza del COBOL). I compilatori professionali sono costosi e inizialmente indisponibili sulle piattaforme micro, con la lodevole eccezione dei sistemi che supportano il CP/M. La diffusione del personal computer in ambito professionistico ha cambiato molto le cose. In fondo una rete di PC vale quanto un mainframe (non sempre, ma è un discorso che ci porterebbe lontano). Per quanto accennato sopra il COBOL si è fatta una cattiva fama e gli ambienti, diciamo così, progressisti non hanno esitato a vituperarne l’utilizzo. Se questo è stato un bene o il contrario non sta a me decidere. Da un lato si è persa una professionalitè elevata, dall’altro i nuovi idiomi, più facili all’approccio, hanno permesso a molte persone l’avvicinarsi alla programmazione. Ci sono dei pro e dei contro, come in tutte le cose. Dopo questa lunga ma doverosa panoramica sulla filosofia del linguaggio COBOL veniamo a parlare di cose pratiche. Prima di tutto Jurassic Book - Tullio Nicolussi - Il COBOL bisogna procurarsi un compilatore se si vuole seguire con profitto il corso che proponiamo. -”Bravo! E dove ne trovo uno?”. Tranquilli, è più semplice di quanto si creda. Rivolgendosi all’Open Source è possibile recuperare un buon compilatore che gira con GCC (che erroneamente viene considerato un compilatore di codice C, in realtà è uno dei cross compiler più flessibili che ci sono in giro). Se decidete di seguire questa strada il prodotto si chiama OpenCobol e si possono scaricare i sorgenti da questo link: http://www.opencobol.org/modules/mydownloads/ Scelte alternative possono essere le versioni datate che qualche utente a volte svende (anche se teoricamente non sarebbe legalmente ineccepibile) su eBay. La Microsoft ha commercializzato per un certo tempo un compilatore per Windows chiamato Microsoft COBOL. Altra ditta specializzata è la MicroFocus che costruisce compilatori per tutte le piattaforme ed ha anche una versione educational molto bella chiamata “Personal COBOL” che viene venduta in libreria (non in Italia). Si veda la prova software in questo fascicolo. Un compilatore molto diffuso all’epoca delle reti Novell era un certo “MBP COBOL”, prodotto da una ditta tedesca (la MBP, appunto), il cui acronimo non chiedetemi per cosa sta :-). Una fonte alternativa ma molto valida è fornita dal retro computing (se no che ci staremmo a fare?). E’ possibile che se il vostro retro com- puter preferito supporta il CP/M, troviate in giro le immagini di un compilatore. magari non sarà una scheggia, ma che importa? Ad esempio per Apple IIe sotto CP/M la Microsoft (sì, sempre lei) ha commercializzato un compilatore chiamato COBOL-80, elemento di una serie di prodotti il cui esponente più famoso è il BASIC-80. Su SurgeForce.org si possono reperire vari progetti che hanno a che fare con l’argomento. Uno di questi propone un compilatore minimale per Windows, chiamato Tiny Cobol. Lo abbiamo scaricato e provato trovandolo per la verità non troppo esaltante... Ancora, all’indirizzo: http://www.netcobol.com/products/windows/netcobol.html si trova un prodotto commerciale chiamato NETCobol, adatto all’ambiente .NET che sfrutta la IDE di Visual Studio. Ne esiste anche una versione “Student”, se volete provarci... Insomma non ci sono scuse del tipo “non trovo un compilatore in giro” :-) 9 Jurassic Book - Tullio Nicolussi - Il COBOL Il primo programma Abbiamo scritto il classico proseconda dell’ambien- gramma “hello World” e come si te operativo che avete vede l’idea della prolissità colpisce scelto dovete comincia- abbastanza. Rispetto ad un Basic re a scrivere il sorgente dei pro- che con una semplice istruzione: grammi. Alcuni tools prevedono 10 PRINT “HELLO WORLD” un input guidato, ad esempio con i tab impostati per muoversi fra le avrebbe fornito lo stesso risultato, varie zone nelle quali è divisa la in COBOL sono state necessarie riga. Vi ricordo che i primi sei ca- molte più righe. L’utilità dell’orgatarreri della riga sono riservati alle nizzazione del sorgente con mollabel. Il settimo carattere contie- te parti dichiarative sarà molto più ne un eventuale controllo di riga: chiara nel prosieguo del corso che il simbolo “-” per la continuazione abbiamo per ora solo introdotto. dalla riga precedente, “*” per una C’è da dire comunque, a consoriga di commento (da qui il verbo lazione di chi si è spaventato da “asteriscare” che usano i “veri” subito, che i programmatori si limiprogrammatori), “/” per ordinare il tano fare un copia incolla da un salto pagina alla stampante sulla template. Oserei dire che moltisquale andiamo a ottenere il listing simi di essi nemmeno sarebbero del sorgente. Dall’ottavo carattere capaci di scrivere da zero l’intera inizia la “ZONA A” e al 12 carattere parte dichiarativa: semplicemente non la possono ricordare, dopo la “ZONA B”. anni che non se ne preoccupano! A Il primo programma è visibile nel riquadro “Listato 1” che ora andiamo ad eseminare in dettaglio. 0-----78---2-------2---------3---------4---------AAAABBBBBBBBBBBBBBBBBBBB... IDENTIFICATION DIVISION. PROGRAM-ID HELLOWORLD. ENVIRONMENTAL DIVISION. CONFIGURATION SECTION. SPECIAL-NAMES. DECIMAL POINT IS COMMA. DATA DIVISION. PROCEDURE DIVISION. MAIN SECTION. INIZIO. DISPLAY “HELLO WORLD”. 10 Esaminando il primo sorgente evidenziamo gli aspetti essenziali del linguaggio. Prima di tutto il token di chiusura di uno statement è il punto e ogni riga, come si diceva, deve concludersi entro 72 caratteri, punto compreso. La regola dei compilatori è ignorare tutto ciò che eccede il 72-simo carattere. Il sorgente è diviso in DIVISION che ne indi- Jurassic Book - Tullio Nicolussi - Il COBOL viduano le quattro parti principali. L’IDENTIFICATION DIVISION come dice il nome è deputata a contenere delle meta-istruzioni che servono all’identificazione del programma. Una di queste informazioni è il nome del programma stesso la cui composizione segue le regole dell’ambiente operativo. Non necessariamente il PROGRAM-ID corrisponde al nome del binario compilato sul file system, esso è un nome interno al quale fare riferimento ad esempio se il sorgente fosse in una libreria di funzioni. La ENVIRONMENT DIVISION specifica l’ambiente dove il programma viene sviluppato rispetto alla sua destinazione finale. Ricordate che il COBOL è crossplatform? In ambiente Personal Computer queste specifiche hanno ormai poco senso e anzi i compilatori sono stati di fatto alleggeriti della capacità di compilare per diversa piattaforma. Rimane quindi sostanzialmente una divisione figurativa che serve al più per specificare alcune particolarità che si intendono usare, come ad esempio l’utilizzo della virgola come separatore dei decimali. Infine la PROCEDURE DIVISION ospita il codice che viene organizzato in sezioni. Tradizionalmente si nomina la prima sezione “MAIN SECTION”, anche se il nome “MAIN” non è obbligatorio (potrebbe essere chiamata INIZIO o qualsiasi altra cosa piaccia). Poi abbiamo inserito anche la parola “INIZIO” che funge da label. Si usa, ma anche questo non è obbligatorio. Per completare la disamina del primo sorgente diciamo che l’istruzione DISPLAY stampa a video una costante letterale (è il nostro caso) o il valore di una variabile. Il programma viene eseguito dalla prima sezione che si incontra fino al termine della stessa o fino alla conclusione del sorgente. Esiste una specifica istruzione STOP PROGRAM o semplicemente STOP che conclude l’elaborazione. Tradizionalmente i sorgenti vengono scritti in maiuscolo in omaggio ai vecchi terminali dei mainframe anni ‘60. I compilatori oggigiorno accettano anche il minuscolo che negli ultimi anni è diventata una pratica seguita da moltissimi programmatori, specialmente se appartenenti alle nuove generazioni, abituati ai linguaggi correnti. Il Cobol rimane però unsensitive, come il Basic: non distingue fra maiuscole e minuscole. La DATA DIVISION non è altro che la parte di sorgente dove si dichiarano le variabili. In COBOL variabili e costanti devono essere dichiarate tutte in questa divisione dove trovano posto anche altre strutture informative come ad esempio i file Pur esistendo qualche approccio sequenziali o con chiave, le specifi- alla pratica dell’interpretazione, il che di ordinamento, etc... COBOL nasce come linguaggio 11 Jurassic Book - Tullio Nicolussi - Il COBOL compilato. La rigida organizzazione dei sorgenti è a supporto della creazione del codice binario. Il COBOL si presenta quindi praticamente sempre con la classica configurazione di sviluppo editorcompilazione-esecuzione. L’ambiente di eccellenza per l’esecuzione di programmi COBOL è l’interfaccia a caratteri, proprio per la forma spartana dell’I/O tipica del linguaggio. Come abbiamo detto nell’introduzione non mancano comunque implementazioni “a finestre” realizzate con opportune estensioni del linguaggio stesso che dimostra una certa dose di adattabilità grazie soprattutto alle estensioni “ad-hoc” che le aziende produttrici vi inseriscono “a forza” per dare al loro prodotto una parvenza di modernità. Già dalla nascita comunque è stata prevista una sorta di gestione “a form” del video. Una specifica SECTION, esattamente la SCREEN SECTION, è deputata alla descrizione dell’interfaccia. Il bubble sort in COBOL Un esempio più articolato è riportato per intero nei box delle pagine seguenti. Si tratta di una implementazione dell’algoritmo classico di bubble sort. Penso sia noto a tutti il meccanismo di questo semplice algoritmo di ordinamento: si tratta di spostare degli elementi in un vettore effettuando dei ripetuti scambi con gli elementi adiacenti fino ad ottenere un vettore ordinato. Maggiori approfondimenti si possono trovare sul fascicolo numero 1 di Jurassic News. Commentiamo ora le righe che incontriamo nel sorgente per introdurre le novità rispetto a quanto visto finora. Nella WORKING-STORAGE SECTION abbiamo dichiarato due costanti (in realtà non esiste una dichiarazione speciale per variabili immodificabili, il fatto che siano costanti lo decidiamo noi). 01 MAX COMP-1 VALUE 3. 01 LIMITE COMP-1 VALUE 10000. Il tipo COMP-1 è il classico Integer che occupa una o più coppie di byte a seconda dell’implementazione del compilatore. Sono variabili numeriche senza una definizione di formato. A cominciare dalla variabile VETTORE abbiamo il primo esempio di variabile strutturata. VETTORE è il nome della nostra variabile dichiarata a livello 01 che contiene un sotto-livello, individuato dal livello 12 Jurassic Book - Tullio Nicolussi - Il COBOL 05 che ne rappresenta il contenuto 01 VETTORE. 10 ELEMENTO strutturato. 01 VETTORE. 05 EL-VETTORE COMP-1 OCCURS 10000. EL-VETTORE è vettore di 10.000 elementi di tipo COMP-1. Quando in una istruzione ci si riferisce alla variabile VETTORE si sta parlando dell’intera struttura; quando ci si riferisce a EL-VETTORE si sta parlando di una componente che andrà individuata tramite il classico meccanismo degli indici: COMP-1 OCCURS 1000. Un altro esempio di variabile strutturata è quella che contiene un orario: 01 ORA. 05 05 05 05 ORA-HH ORA-MM ORA-SS ORA-CC COMP-1. COMP-1. COMP-1. COMP-1. In questo caso quattro variabili semplici di tipo COMP-1 sono raggruppate al solo fine di chiarezza, ma verranno elaborate singolarmente. MOVE 12 TO EL-VETTORE(34) In questo specifico caso, cioè nella necessità di dichiarare vettori o matrici la strutturazione è obbligatoria. Infatti lo standard prevede che una variabile di livello 01 non possa essere indicizzata. C’è un motivo pratico per questo: il livello 01 indica al compilatore anche la classe di storage della variabile, cioè i livelli 01 sono immagazzinati a partire dall’indirizzo intero di memoria, cosa che non succede per i sotto-livelli. Se avessimo ad esempio un ambiente a 64 bit, quindi con word di quattro byte e il tipo COMP-1 fosse un intero da due byte, allora ogni dichiarazione di COMP-1 a livello 01 occuperebbe comunque una word, sprecando due byte di memoria. Una dichiarazione Nella dichiarazione della variabile TOT-SECONDI troviamo un’altra forma di dichiarazione di variabile numerica. 01 TOT-SECONDI PIC 9(12)V9(2) VALUE ZERO. PIC 9(12)V9(2) significa 12 cifre intere seguite da due decimali. Passiamo ora alla desamina del codice premettendo che esso è stato strutturato in maniera molto spinta (tipo Pascal per intenderci) cercando di introdurre i concetti di esecuzione dei singoli pezzi come fossero parti staccate (procedure o funzioni). INIZIO. * --- loop iterazioni PERFORM ESEGUI THRU ESEGUI-EXIT MAX TIMES. * --- calcolo della media 01 VETTORE COMP-1 OCCURS 1000 COMPUTE MEDIA = TOT-SECONDI / MAX. * --- display dei risultati. occuperebbe 4000 byte di memoDISPLAY ria, contro i 2000 occupati dalla di“TOTALE SECONDI IMPIEGATI: “ TOT-SECONDI. chiarazione: DISPLAY 13 Jurassic Book - Tullio Nicolussi - Il COBOL IDENTIFICATION DIVISION. 01 PROGRAM-ID. BUBBLE. *********************************** * Titolo : Bubble Sort *********************************** DATE-WRITTEN. DATE-COMPILED. DIC/97. GEN/98. *********************************** ENVIRONMENT DIVISION. *********************************** CONFIGURATION SECTION. *---------------------------------SOURCE-COMPUTER. PENTIUM-PC166. OBJECT-COMPUTER. PENTIUM-PC166. SPECIAL-NAMES. DECIMAL-POINT IS COMMA. * --- calcolo della media COMPUTE MEDIA = TOT-SECONDI / MAX. * --- display dei risultati. DISPLAY “TOTALE SECONDI IMPIEGATI: “ TOT-SECONDI. DISPLAY “MEDIA PER VETTORE “ MEDIA ESEGUI. PERFORM CARICA-VETTORE THRU CARICA-VETTORE-EXIT. * --- esecuzione sort VETTORE. 05 EL-VETTORE COMP-1 OCCURS 10000. 01 I COMP-1. 01 SCAMBI COMP-1. 01 TOT-ITERAZIONI PIC 9(12). 01 J COMP-1. 01 TOT-SCAMBI PIC 9(12). 01 TEMP COMP-1. 01 01 ORA. ORA-HH ORA-MM ORA-SS ORA-CC COMP-1. COMP-1. COMP-1. COMP-1. 05 05 05 05 ORA-I. ORA-I-HH ORA-I-MM ORA-I-SS ORA-I-CC COMP-1. COMP-1. COMP-1. COMP-1. 05 05 05 05 ORA-F. ORA-F-HH ORA-F-MM ORA-F-SS ORA-F-CC COMP-1. COMP-1. COMP-1. COMP-1. CALL “GTIME” USING ORA-I. display “ora iniziale: “ ORA-I-HH “:” ORA-I-MM “:” ORA-I-SS “:” ORA-I-CC. MOVE 1 TO SCAMBI. PERFORM LOOP-SCAMBIO THRU LOOP-SCAMBIO-EXIT UNTIL SCAMBI IS EQUAL ZERO. CALL “GTIME” USING ORA-F. display “ora finale : “ ORA-F-HH “:” ORA-F-MM “:” ORA-F-SS “:” ORA-F-CC. MOVE ZERO TO DIFF-SECONDI. PERFORM CALCOLA-SECONDI THRU CALCOLA-SECONDI-EXIT. 01 TOT-SECONDI PIC 9(12)V9(2) VALUE ZERO. 01 MEDIA PIC 9(5)V9(2) VALUE ZERO. 01 01 01 DIFF-SECONDI PIC 9(12). SECONDI-INIZIALI SECONDI-FINALI 14 COMPUTE TOT-SECONDI = TOT-SECONDI + (DIFF-SECONDI / 100). DISPLAY “TOTALE SECONDI : “ TOT-SECONDI. PIC 9(12). PIC 9(12). * ---- Variabili per il generatore di numeri casuali 01 MODULO COMP-1 VALUE 36456. 01 MOLTIPLICATORE COMP-1. 01 INCREMENTO COMP-1. : USCITA. STOP RUN. 01 05 05 05 05 COMP-1. /**************************************** PROCEDURE DIVISION. **************************************** MAIN SECTION. **************************************** INIZIO. **************************************** * --- loop iterazioni PERFORM ESEGUI THRU ESEGUI-EXIT MAX TIMES. /********************************** DATA DIVISION. *********************************** WORKING-STORAGE SECTION. *********************************** * ---- costanti 01 MAX COMP-1 VALUE 3. 01 LIMITE COMP-1 VALUE 10000. * --- variabili 01 SEME ESEGUI-EXIT. EXIT. LOOP-SCAMBIO. MOVE ZERO TO SCAMBI. PERFORM CONFRONTA THRU CONFRONTA-EXIT Jurassic Book - Tullio Nicolussi - Il COBOL VARYING I FROM 1 BY 1 UNTIL I = LIMITE. LOOP-SCAMBIO-EXIT. EXIT. CONFRONTA. IF EL-VETTORE( I + 1 ) IS < EL-VETTORE( I ) MOVE EL-VETTORE( I + 1 ) TO TEMP MOVE EL-VETTORE( I ) TO EL-VETTORE( I + 1 ) MOVE TEMP TO EL-VETTORE( I ) MOVE 1 TO SCAMBI. CONFRONTA-EXIT. EXIT. CARICA-VETTORE. CALL “GTIME” USING ORA. COMPUTE MOLTIPLICATORE = ORA-SS * ORA-MM. COMPUTE SEME = ORA-CC * ORA-SS. COMPUTE INCREMENTO = ORA-CC * ORA-MM. PERFORM NUMERO-RANDOM THRU NUMERO-RANDOM-EXIT VARYING I FROM 1 BY 1 UNTIL I > LIMITE. CARICA-VETTORE-EXIT. EXIT. NUMERO-RANDOM. MOVE SEME TO EL-VETTORE(I). COMPUTE SEME = (MOLTIPLICATORE * SEME + INCREMENTO). COMPUTE SEME = MODULO - (SEME / MODULO) * SEME. IF SEME < 0 COMPUTE SEME = -SEME. NUMERO-RANDOM-EXIT. EXIT. CALCOLA-SECONDI. * --- calcola il numero di secondi occorsi fra i due orari. COMPUTE SECONDI-INIZIALI = ORA-I-HH * 3600 + ORA-I-MM * 60 + ORA-I-SS. COMPUTE SECONDI-INIZIALI = SECONDI-INIZIALI * 100 + ORA-I-CC. COMPUTE SECONDI-FINALI = ORA-F-HH * 3600 + ORA-F-MM * 60 + ORA-F-SS. COMPUTE SECONDI-FINALI = SECONDI-FINALI * 100 + ORA-F-CC. COMPUTE DIFF-SECONDI = SECONDI-FINALI SECONDI-INIZIALI. CALCOLA-SECONDI-EXIT. EXIT. 15 Jurassic Book - Tullio Nicolussi - Il COBOL “MEDIA PER VETTORE: “ MEDIA. USCITA. STOP RUN. C’è una iterazione iniziale che richiama la sezione ESEGUI. La sintassi PERFORM ESEGUI THRU ESEGUIEXIT MAX TIMES. scambio. Le istruzioni di iterazione innescate dall’istruzione PERFORM vengono eseguite continuamente fino a che non si verifica la condizione descritta nell’UNTIL. Si noti la sintassi usata per controllare la condizione di uscita. Si sarebbe potuto anche scrivere: UNTIL SCAMBI = 0 Concedendo un certo vantaggio ai programmatori “moderni”, ma perché dovremmo? La sintassi usata qui è molto più chiara per chi è avvezzo a leggere i sorgenti COBOL, infatti se ci pensate asso- Significa: esegui un numero di iterazioni pari al valore contenuto in MAX (che abbiamo dichiarato nella Working al valore 10.000) delle istruzioni comprese nella sezione INIZIO per finire con quelle nella sezione ESEGUI-EXIT. Fatta questa iterazione c’e’ un calcolo dei secondi medi impiega- miglia molto di più ad una sintassi ti, la stampa a video dei risultati e letterale. E’ dimostrato inoltre che molti errori di codifica nei programl’uscita dal programma. mi derivano dalla scrittura di conLa sezione ESEGUI, che abbia- dizioni al contorno errate dovute mo visto viene iterata 10.000 volte, ad una errata interpretazione delle per avere un risultato medio atten- specifiche o all’impiego di operatori dibile, prevede i seguenti passag- di confronto simbolici che richiedono un quid di attenzione maggiore gi: caricamento del vettore con nu- a chi codifica. meri pseudo-casuali, la rilevazione del tempo iniziale, il sort del vettore, la rilevazione del tempo impiegato. L’algoritmo di ordinamento vero e proprio è costituito dai seguenti statement: MOVE 1 TO SCAMBI. PERFORM LOOP-SCAMBIO THRU LOOP-SCAMBIO-EXIT UNTIL SCAMBI IS EQUAL ZERO. Se vi è chiaro come procede il bubble sort, semplicemente si continua a fare scambi di elementi fino a che una “spazzolatura” finale del vettore non da luogo a nessuno 16 Il caricamento dei dati nel vettore avviene nella form CARICA-VETTORE chiamata dallo statement: PERFORM CARICA-VETTORE THRU CARICA-VETTORE-EXIT. Essa contiene un loop che interessa uno ad uno gli elementi del vettore e vi inserisce un numero pseudo-casuale. L’istruzione che effettua il loop di caricamento è la seguente: PERFORM NUMERO-RANDOM THRU NUMERO-RANDOM-EXIT VARYING I FROM 1 BY 1 UNTIL I > LIMITE. Jurassic Book - Tullio Nicolussi - Il COBOL Questa sintassi prevede l’incremento automatico di un indice rappresentato dalla variabile I che viene incrementato partendo dal valore 1 fino a superare il limite previsto, che è la dimensione del vettore stesso. Implicitamente abbiamo introdotto un ulteriore concetto: le variabili indicizzate hanno indice che inizia da 1. altri linguaggi. Una particolarità che vale la pena spiegare è l’utilizzo dello statement MOVE 1 TO SCAMBI All’interno della form di confronto. Un valore diverso da zero della variabile SCAMBI serve per ordinare un ulteriore loop sugli elementi del vettore. Infatti l’algoritmo si basa proprio sull’iterazione dei confronti elemento per elemento del vettore fino a che un’ultima iterazione non Il cuore dell’algoritmo di bubble effettua alcuno scambio, segno che sort è contenuto nella form CON- il vettore è ordinato. FRONTA: Non sarebbe stato meglio increCONFRONTA. mentare il valore di SCAMBI con IF EL-VETTORE( I + 1 ) una istruzione del tipo: IS < EL-VETTORE( I ) MOVE EL-VETTORE( I + 1 ) • ADD 1 TO SCAMBI TO TEMP MOVE EL-VETTORE( I ) TO EL-VETTORE( I + 1 ) In effetti se servisse anche tracMOVE TEMP ciare quanti scambi vengono fatti in TO EL-VETTORE( I ) MOVE 1 TO SCAMBI. ogni iterazione, allora l’istruzione di CONFRONTA-EXIT. EXIT. Qui si vede come l’indicizzazione delle variabili avviene indicando l’elemento con indice fra parentesi, eventualmente calcolando il valore stesso dell’indice. Gli operatori di confronto in COBOL sono quelli classici: =, <, >, >=, <=, <>. Esiste tuttavia una forma “letterale” di questi operatori: incremento sarebbe stata necessaria. In caso contrario è inutile una istruzione matematica, che consuma certo più tempo, rispetto ad una istruzione di assegnazione. • = IS EQUAL • > IS GREATHER THAN • < IS LESS THAN • >= IS GREATHER OR EQUAL, IS NOT LESS • <= IS LESS OR EQUAL, IS NOT GREATHER • <> IS NOT EQUAL La forma “prolissa” della sintassi è poco usata attualmente, dato che le nuove generazioni di programmatori sono ormai abituate alle forme “matematiche” più simili agli 17 Jurassic Book - Tullio Nicolussi - Il COBOL legato alla strutturazione del dato è la possibilità di ridefinire la memoria indirizzata da una variabile in modo che questa sia usabile con due o più nomi. Ad esempio: Variabili strutturate L ’uso di variabili strutturate, come matrici e vettori, è incoraggiata in COBOL. C’è chi addirittura struttura tutto, perfino i semplici contatori interi. 01 CODICE. Qualcosa come: 02 COD-FIS 01 CONTATORE. 10 CONT PIC COMP-1. La multidimensionalità si ottiene inserendo una dichiarazione strutturata in un’altra. Ecco un esempio: 01 MATRICE. 10 RIGA-MATRICE OCCURS 100. 20 EL-MATRICE PIC 9(5) OCCURS 100. 02 PIC X(16). PARTITA-IVA REDEFINES COD-FIS. 05 P-IVA PIC 9(12). 05 FILLER X(4). Incontriamo per la prima volta una parola chiave molto usata nella definizione delle variabili strutturate del COBOL: “FILLER”. Questa viene utilizzata come riempitivo. Nel nostro esempio, dato che la ridefinizione di un’area di memoria deve essere coerente, cioè utilizzare tutto lo spazio, riempiamo con un nome simbolico FILLER quella parte di dato che nel caso stessimo trattando una partita IVA non ci interessa. E’ chiaro che COD-FIS e PARTITA-IVA condividono lo stesso spazio di memoria, è lo stesso meccanismo implementato con le union nel linguaggio C. Nel listato numero 2 riportiamo un esempio di definizione di un record anagrafico che contiene un po’ tutte le cose viste finora nella definizione dei tipi di dato in COBOL. Qui abbiamo dichiarato una matrice di dimensione 100 per 100 i cui elementi sono dei valori numerici di cinListato 1 que ci/**************************************** fre. PROCEDURE DIVISION. Ecco **************************************** MAIN SECTION. un loop **************************************** INIZIO. che ca**************************************** rica gli PERFORM SCAN-RIGHE THRU SCAN-RIGHE-EXIT elemen VARYING RIGA FROM 1 BY 1 ti della UNTIL RIGA <= 10. matrice USCITA. STOP RUN. c o m e fosse SCAN-RIGA. una ta PERFORM SCAN-COL 01 REC-ANAG. THRU SCAN-COL-EXIT vola pi VARYING COLONNA FROM 1 BY 1 UNTIL COLONNA <= 10. tagorica è la definizione del livello base, SCAN-RIGHE-EXIT. ( l i s t a t o appunto 01, che identifica l’inizio EXIT. 1). di un dato strutturato. SCAN-COL. COMPUTE EL-MATRICE(RIGA, COLONNA) = RIGA * COLONNA. 18 SCAN-COL-EXIT. EXIT. 05 Un’alt r o aspetto TIPO-RECORD PIC XX. è un tipo di secondo livello di formato due caratteri alfanumerici. Jurassic Book - Tullio Nicolussi - Il COBOL MATRICOLA è un dato strutturato formato da due sotto-livelli che nell’esempio sono identificato dal numero di livello 10. Ci si potrà riferire a questo dato indicando il singolo sotto-livello o il dato intero MATRICOLA. Ad esempio: Purtroppo il COBOL non prevede un meccanismo di dereferenziazione del dato, come succede nei linguaggi di programmazione più moderni. Ad esempio nel C si usa il punto come separatore e indicatore di riferimento per il cosidetto “Spazio di validità” del dato. In C si scriverebbe qualcosa come: MOVE ‘12345A’ TO MATRICOLA. MOVE ‘12345’ TO NUMERO. MOVE ‘A’ TO CONTROLLO. REC-ANAG.ASSUNZIONE.DATA-ASSUNZIONE.ANNO = 1975. 05 10 10 MATRICOLA. NUMERO CONTROLLO PIC 9(5). PIC X. Dato che il COBOL non dispone di questo meccanismo è fortemente consigliato differenziare i nomi dei campi in maniera nativa, cioè chiamandoli diversamente. Quando questo non è possibile si ricorre alla clausula “OF” come nell’esempio seguente: I due campi GENERALITA e NOMINATIVO sono ridefiniti, cioè identificano la stessa locazione di memoria per una lunghezza di 50 caratteri alfanumerici. Mentre GENERALITA è stato sotto specificato in due sottocampi NOME e COGNOME, il campo NOMINATIVO, che possiamo pensare come un MOVE 1975 TO ANNO OF DATA-NASCITA. Listato 2 alias del campo GENERALITA, è Sembra definito come unico. compli01 REC-ANAG. 05 TIPO-RECORD PIC XX. cato ma 05 MATRICOLA. Seguono tre livelli chiamati rispetti 10 NUMERO PIC 9(5). non lo è 10 CONTROLLO PIC X. vamente NASCITA, ASSUNZIONE affatto, 05 GENERALITA. 10 NOME PIC X(25). e DIMISSIONI. Tutti e tre contengoanche 10 COGNOME PIC X(25). no una data definita con sottocampi 05 NOMINATIVO consi REDEFINES GENERALITA. che hanno lo stesso nome: ANNO, 10 FILLER PIC X(50). derando 05 SESSO PIC X. MESE e GIORNO. 05 NASCITA. che la 10 DATA-NASCITA. sintassi 15 ANNO PIC 9999. 15 MESE PIC 99. 10 DATA-NASCITA. mantie 15 GIORNO PIC 99. 15 ANNO PIC 9999. 10 LUOGO-DI-NASCITA. 15 MESE PIC 99. ne una 15 CITTA PIC X(25). 15 GIORNO PIC 99. 15 CAP PIC Z(5). ottima 15 PROVINCIA PIC XX. 10 DATA-ASSUNZIONE. 15 NAZIONE PIC X(25). leggibili15 ANNO PIC 9999. 05 ASSUNZIONE. 15 MESE PIC 99. tà. 10 DATA-ASSUNZIONE. 15 ANNO PIC 99. 15 ANNO PIC 9999. Nel re 15 MESE PIC 99. 10 DATA-DIMISSIONI. 15 ANNO PIC 99. 15 ANNO PIC 9999. cord che 05 DIMISSIONI. 15 MESE PIC 99. 10 DATA-DIMISSIONI. 15 ANNO PIC 99. abbia 15 ANNO PIC 9999. 15 MESE PIC 99. mo esa15 ANNO PIC 99. Come si fa a riferirsi ad un particominato lare anno, mese o giorno? c o m e 19 Jurassic Book - Tullio Nicolussi - Il COBOL esempio è presente una dichiarazione di USAGE PIC Z. Il tipo Z è un numerico che mantiene gli zeri non significativi. Serve nei casi in cui, come in questo, il valore numerico sia in realtà un alfabetico di sole cifre. Possiamo assegnare al campo il valore 00103 e la stampa ci mostrerebbe anche i due zeri “leading”, cioè davanti. Per chiudere il discorso sulla rappresentazione dei dati e cioè sull’uso della specifica USAGE, che a volte viene omessa facciamo questo altri esempi significativi: USAGE IS PIC 9(5)V99. E’ in valore numerico con segno con cinque cifre intere e due cifre decimali. USAGE IS PIC AAAXX999. E’ un campo misto lungo otto caratteri dei quali i primi tre sono alfabetici (solo lettere), seguono due caratteri alfanumerici (lettere e numeri) e infine tre caratteri numerici. Infine USAGE IS PIC A(5)9(3)X(2). PIC 999.999.999. indica che vogliamo una rappresentazione con numeri di separazione per le migliaia. PIC 999-. indica che il dato è rappresentato con il segno alla fine (trailing), un uso molto comune nelle liste di cifre dei bilanci e il simbolo sarà un meno se il dato è negativo, uno spazio altrimenti. PIC 999+. indica che vogliamo il segno in coda al numero ma questa volta il segno esisterà sia per i valori positivi che per quelli negativi. C’è un’altra forma possibile per la rappresentazione dei valori positivi e negativi, anche se non molto usata in Italia, ed è quella di indicare due lettere “CR” che starebbe per “credito” e “DB” per debito. PIC 999CR. PIC 999DB. La stampa di “CR” e “DB” avviene solo se il dato è negativo e non come si potrebbe pensare DB se negativo e CR se positivo. PIC 999Z. sta ad indicare che vogliamo stampare la cifra zero a fronte di un valore nullo. E’ un valore che contiene cinque caratteri alfabetici, seguiti da tre cifre ed infine due ulteriori caratteri alfanumerici. Nell’assegnazione dei valori sono La clausula PICTURES, abbre- consentite delle abbreviazioni e viata in PIC, serve anche per defi- l’uso di due costanti figurative per nire una rappresentazione del dato lo spazio (blank) e per lo zero. su video al momento dell’output o VALUE IS ZERO. della stampa. VALUE IS ZEROES. VALUE IS SPACE. 20 Jurassic Book - Tullio Nicolussi - Il COBOL VALUE IS ALL SPACE. COPY (che è l’equivalete dell’include presente in molti altri linguaggi). La COPY permette di includere nel sorgente un file esterno che deve essere ovviamente ben formato. L’uso prevalente è quello dell’inclusione di strutture dati che sono comuni in un progetto e che più comodo condividere fra i sorgenti. Ad esempio la descrizione di un record da scrivere in una tabella. La sintassi è molto semplice, la parola COPY va inserita all’inizio della zona B, seguita dal nome del file da includere. Nei moderni compilatori l’assegnazione di una stringa vuota ad una variabile alfanumerica già la riempie di spazi (si dice in gergo che la “filla”, dalla parola chiave FILLER), ma i programmatori COBOL amano abbastanza queste forme che possiamo considerare prolisse ed obsolete ma di facile lettura. Ecco, una delle cose affascinanti del COBOL è che i sorgenti si possono leggere. Attenzione, non “interpretare”, dico proprio leggere nel senso letterale del termine. Gli COPY ‘SCRNSELE.SKL’. statement, se ben scritti, vanno a comporre dei veri paragrafi in ingle- Una variante molto comoda perse che hanno un senso compiuto. mette di sostituire un pattern duAd esempio: rante la copia. Ad esempio sostituire tutte le occorrenze di una PERFORM CALCOLA THRU CALCOLA-EXIT sottostringa, operazione utilissima VARYING INDEX FROM 1 BY 1 UNTIL INDEX IS perché abbiamo visto che la defe GREATER THAN MAX. renziazione dei nomi deve essere esplicitata. Facciamo un esempio. è certamente più leggibile di un Supponiamo di dover realizzare un C: programma che legge i recod di un file e li scrive in un altro file, elabofor(i=1; i<=max; i++){ ... randoli ma lasciando invariata la }; struttura del record stesso. Il C ha dalla sua la compattezza, Se la descrizione del primo record questo è certo, il COBOL invece è qualcosa del tipo: assicura che fra venti anni chi legge 01 TR01. 02 TR01-CHIAVE. il sorgente capirà benissimo cosa 02 TR01-VALORE. diavolo il programma combina! Si La descrizione del secondo record può dire la stessa cosa del C o di sarà ad esempio: Java? Ne dubito molto... 01 TR02. 02 TR02-CHIAVE. 02 TR02-VALORE. Il precompilatore. I compilatori COBOL dispongono Se abbiamo registrato la descriziodi un pre-compilatore che viene ne della variabile strutturata TR01 usato quasi esclusivamente per la su un file esterno, all’interno del norisoluzione della pseudo istruzione 21 Jurassic Book - Tullio Nicolussi - Il COBOL stro sorgente possiamo scrivere: COPY ‘TR01.TRC’. COPY ‘TR01.TRC’ REPLACING ‘TR01’ BY ‘TR02’. e sarà come avessimo definito le due variabili nel sorgente in maniera esplicita. cide con il loro ordine. L’accesso ai file byte-stream o testo avviene per riga (se è un testo) o per lettura a blocchi di lungezza fissa. L’uso dei file va dichiarato in due divisioni diverse: nella ENVIRONMENT DIVISION e precisamenL’uso dei file. te nella sezione INPUT-OUTPUT Veniamo ora a parlare dell’argo- SECTION si dichiara una specie mento clou che riguarda il COBOL: di puntatore al file stabilendo le la gestione dei dati su file. sue caratteristiche e la modalità di Il linguaggio nasce con l’inten- accesso. to di fornire in maniera integrata Ad esempio: gli strumenti adatti al trattamento delle registrazioni commerciali. E’ environment division. configuration section. stato il primo linguaggio (e forse source-computer. mds-800. object-computer. mds-800. anche l’ultimo) che nelle specifi- special-names. console is crt. che del compilatore richiede una input-output section. file-control. gestione interna dei file indicizzaselect stock-file assign to “stock.it” ti, cioè gestibili come le classiche organization indexed (ora) tabelle dei database. access dynamic record key stock-code. I file gestibili sono di due tipi: file senza indici (classico file di testo o La sezione input-output section file sequenziale binario) e file indicontiene una sotto-sezione chiacizzati. In questa ultima categoria mata file-control nella quale si ditroviamo due tipi di organizzazioni: chiarano tutti i file che si useranno gestione sequenziale delle infornel programma. La dichiarazione mazioni e gestione a chiave. La avviene per mezzo della parola gestione a chiave è un concetto “select” seguita dal nome con il moderno che significa in pratica quale si identifica il file nel sorgenche i record presenti sono accessite e si “assegna” ad un file effettivo bili in maniera dinamica attraverso la cui sintassi dipende dalla piattal’uso di chiavi di ricerca (che per il forma e dal compilatore. COBOL coincidono con uno o più campi della tabella). organization indexed access dynamic L’accesso sequenziale alle inforrecord key stock-code. mazioni significa invece che i record presenti nella registrazione Con la dichiarazione sopra risono numerati e vi si accede attra- portata diciamo al sistema che il verso la chiave numerica che coin- nostro file è di tipo indexed, cioè 22 Jurassic Book - Tullio Nicolussi - Il COBOL con chiave, vi accederemo in maniera dinamica attraverso la chiave (i file indexed potrebbero essere acceduti anche sequenzialmente). Infine abbiamo anche informato il compilatore che la chiave è un certo campo del record. La dichiarazione di record, proprio perché dichiarata nella DATA DIVISION può usarsi tranquillamente come area di lavoro. L’idea è la seguente: si apre in Input/Output il file, si valorizzano i campi della struttura record e infine si scrivono nel file. La struttura del record si andrà a procedure division. dichiarare nella DATA DIVISION sr1. display space. in una speciale sezione chiamata open i-o stock-file. move ‘0001’ to stock-code. FILE SECTION: move ‘Computer’ data file fd 01 02 02 02 division. section. stock-file record is stock-item. stock-item. stock-code pic x(4). product-desc pic x(24). unit-size pic 9(4). “fd” è la parola chiave “file description”, stiamo descrivendo il file, dichiarato nella precedente sezione con nome “stock-file”, appunto. Diciamo al sistema che il record si trova in una struttura il cui livello 01 si chiama “stock-item”. Sotto si trova la descrizione di questo dato strutturato che è in pratica il record della tabella. Si noti che il campo “stock-code” del record è il campo che sarà usato come chiave di accesso per i record. Attenzione: la dichiarazione senza ulteriori specificazioni implica che la chiave è univoca. Un eventuale errore potrà essere gestito da programma, attraverso un meccanismo che assomiglia alle eccezioni. In COBOL non esiste il concetto di “campo contatore”, deve essere gestito “a mano”, cioè è il programmatore che deve preoccuparsi di assegnare ad ogni record una chiave diversa. to product-desc. move 25 to unit-size. write stock-item invalid key go to errore close stock-file. stop run. errore. display ‘Chiave non valida’. stop run. Il frammento di codice sopra riportato effettua il lavoro che ci eravamo prefissi. Lo statement WRITE che scrive il record nel file contiene la gestione dell’errore. Una scrittura in file a chiave può fallire per duplicazione della chiave. Se questo succede viene invocata il blocco di gestione dell’errore, che nell’esempio specifico si limita a stamtare a video un messaggio prima di terminare. Per quanto riguarda la gestione del file, come si vede dal codice c’è l’azione di apertura che può essere di tre tipi “input”, “output” e “i-o” per stabilire rispettivamente che useremo il file come solo input, come output o in maniera dinamica con operazioni di leggi/scrivi a piacere. Ovviamente si può sempre aprire un file indexed in i-o per qualunque 23 Jurassic Book - Tullio Nicolussi - Il COBOL job intendiamo portare a termine. Si rente. intuisce però che la gestione della Forse vi sarà capitato di vedere, modalità i-o sarà più pesante per il probabilmente in qualche film, le sistema. Oggigiorno è abbastanza torri di lettura di nastri dei mainfuori uso la pratica di ottimizzare il frame con i nastri che ginvece di codice, dato che CPU e canali di girare sempre in uno stesso verso, i-o sono diventati enormemente come ci sia aspetterebbe, vanno più performanti rispetto al passato, avanti ed indietro in una sorta di tuttavia bisogna anche considera- balletto. Bene, questi movimenti re che negli ambienti transazionali sono dati proprio dalle istruzioni di dove si opera con il COBOL ci si lettura avanti e indietro comandate potrebbe trovare difronte a file con dal sorgente COBOL. milioni di record e risparmiare due Di riflesso anche l’istruzione di millisecondi a record equivalgono chiusura CLOSE ha clausole anaad una mezzoretta in meno di ela- loghe ad esempio per riavvolgere o meno il nastro a fine lettura. borazione! Il linguaggio COBOL conserva nel Un’altra “strana” caratteristica del suo DNA dei geni che appartengo- COBOL è la lettura a blocchi dei no ad un lontano passato, come dati. ad esempio la gestione dei nastri Vediamo un esempio: magnetici. Osservate questa for- ... input-output section. ma dell’istruzione OPEN: file-control. OPEN INPUT magazzino REVERSED Stiamo dicendo al sistema che ci interessa aprire in input un flusso di dati posizionando il cursore in fono al flusso e leggendo all’indietro. Questo ha un senso per i file sequenziali e in particolare ai dati conservati su un nastro magnetico, periferica usatissima nelle sale macchine dove prosperano i mainframe. Un’altra clausola utile nei flussi su nastro è espliccitata nell’istruzione seguente: OPEN INPUT magazzino WITH NO REWIND Che evita il riavvolgomento del nastro e quindi la lettura del flusso dati partendo dalla posizione cor24 select stock-file assign to “stock.it” organization sequential access mode is sequential. ... data division. file section. fd stock-file label record is standard block contain 5 records data record is stock. 01 02 stock. product-desc pic x(20). working-storage section. 01 deposito. 02 dep-01 pic x(20). 02 dep-02 pic x(20). 02 dep-03 pic x(20). 02 dep-04 pic x(20). 02 dep-05 pic x(20). procedure division. ... read stock INTO deposito at end go to fine-input. L’uso dell’input blocchi rende più efficiente la fase di lettura, come chiunque abbia avuto a che fare con massicce dosi di dati da leg- Jurassic Book - Tullio Nicolussi - Il COBOL gere saprà certamente. A proposito di movimento a blocchi di dati incontriamo un’altra particolarità del linguaggio che è stata conservata successivamente da pochissimi idiomi della programmazione moderna. Stiamo parlando della specifica CORRESPONDING che si può usare tutte le volte che si dovrebbero fare operazioni uguali su dati che “si assomigliano”. L’uso più facile da capire è all’interno dell’istruzione MOVE. Quante volte vi sarà capitato di dover spostare selettivamente dei dati da un record all’altro e di dover predisporre n istruzioni diverse. Vediamo un esempio pratico. Dichiariamo due record che contengano campi con lo stesso nome: to cognome of rec-02. Come dovrebbe apparire chiaro da questo esempio, lo svolgimento dell’istruzione si basa sulla corrispondenza dei nomi nelle due strutture. Invece il campo “cod-fis” non è stato copiato in “c-fis” del secondo record, anche se tipo, lunghezza e posizione, suggeriscono che si tratta di due campi omologhi. La clausola CORRESPONDING funziona anche con istruzioni matematiche. Ad esempio: ADD CORRESPONDING X TO Y. prende dalla struttura X i campi numerici e li somma ai corrispondenti campi nella struttura Y. 01 rec-01. 02 nome pic x(20). 02 cognome pic x(25). 02 cod-fis pic x(16). 01 rec-02. 02 nome pic x(20). 02 cognome pic x(25). 02 c-fis pic x(16). Supponiamo ora di aver caricato i dati nella struttura rec-01, ad esempio da una lettura da file. L’istruzione: move corresponding rec-01 to rec-02. copia i due campi “nome” e “cognome” del record numero 1 nel record numero 2. Corrisponde quindi a scrivere due istruzioni di MOVE: move nome of rec-01 to nome of rec-02. move cognome of rec-01 25 Jurassic Book - Tullio Nicolussi - Il COBOL La gestione dei file to, basti ricordare che il Wirth vi ha dedicato un intero volume “Sorting l fatto che il COBOL nasca con & Searching”. l’intenzione di manipolare i file La supponenza è un pessimo diorganizzati in file (sequenzia- fetto, soprattutto per un programli o a indice, come abbiamo avuto matore, che dovrebbe secondo il modo di spiegare), spiega l’atten- sottoscritto, conservare sempre zione dei progettisti del linguaggio una buona dose di umiltà davanti verso quelle procedure ricorrenti al codice. Fatto sta, per farla breche riguardano la manipolazione ve, che dopo un mese di lavoro dei dati nelle strutture organizzate non ne era ancora uscito, anche perché fui proprio io a fare le pulci quali appunto i file a disco. Una delle pratiche giornaliere che al suo codice e a scoprire i ripesi incontra nella gestione dei dati tuti bug e cali di prestazioni. Queè sicuramente quella dell’ordina- sta vicenda insegnò molto al mio mento. Ecco allora che il COBOL collega, ma anche al sottoscritto. I ha implementato le procedure di sort in maniera nativa, cioè senza ricorrere a librerie esterne o, peggio, ad implementazioni di algoritmi che hanno due essenziali sfortune: di solito riescono male e in ogni caso impiegano tempo ed energie per essere messi a punto. Questo anche per dire che le prestazioni delle routine di sort implementate nei compilatori COBOL sono molto efficenti ed è difficile fare meglio... Vediamo quali sono le linee guida per l’implementazione di un ordinamento all’interno del codice A questo proposito voglio raccon- COBOL. tare le vicende di un collega (si Prima di tutto va rilevato che la parla di oltre quindici anni fà) che procedura funziona grosso modo si ostinò a voler fare da solo per- nella seguente maniera: si apre il ché, secondo lui, sarebbe riuscito file da ordinare (file di input), ogni ad avere maggiori prestazioni ri- record letto viene dato in pasto ad spetto a quelle fornite dal compi- una routine di sort che può esselatore. Difronte ai miei consigli di re personalizzata, infine al termine ripensarci fece spallucce e, errore della lettura dei record si fa il promadornale, non volle nemmeno cesso inverso e attraverso un loop seguire la mia indicazione di con- di chiamate al sort si ottengono i sultare almeno la letteratura in me- record ordinati da scrivere su un rito, per farsi suggerire un algorit- file di output (se si vuole). mo consolidato da implementare. Il primo passo consiste nel diC’è da dire in proposito che il sor- chiarare un file di appoggio che ting è probabilmente la più studia- sarà usato dal SORT come area ta procedura algoritmica in assolu- di lavoro. E’ impensabile infatti che 26 Jurassic Book - Tullio Nicolussi - Il COBOL tutto possa svolgersi in memoria, qualunque sia la dimensione e il numero di record da elaborare (riga 000042)Il nome del file di sort non è significativo (al termine dell’operazione viene comunque cancellato); è sufficente che punti ad un nome di file valido per il file system (e che ci siano i necessari privilegi di scrittura, ovviamente!). Nella DATA DIVISION (riga 000015) troviamo la definizione del file di input e del file di sort, che nella maggior parte dei casi avranno la stessa struttura del record (ma non è obbligatorio). Queste parti dichiarative (file di input e file di sort) sono sufficienti per procedere con l’effettiva operazione di ordinamento che andrà specificata all’interno della PROCEDURE DIVISION, come nelle righe di esempio che seguono la riga 000068 del listato 1. Questo è un primo esempio che non manipola i record, si limita a restituire un file ordinato. La parola chiave SORT da inizio al procedimento che prende in input il file da ordinare e restituisce lo stesso file ordinato secondo le chiavi specificate come parametri del SORT. Ovviamente è possibile un ordinamento discendente specificando la clausola “DESCENDING KEY” invece di “ASCENDING KEY”. ... 000005 Environment Division. 000006 Configuration Section. 000007 Source-Computer. IBM-PC. 000008 Object-Computer. IBM-PC. 000009 Input-Output Section. 000010 File-Control. 000011 Select Dealer-Text Assign To “Dealer.TXT” 000012 Organization Line Sequential 000013 Access Sequential. 000014 Select Sort-Work Assign To “work.txt”. ... 000015 Data Division. 000016 File Section. 000017 Fd Dealer-Text. 000018 01 Dealer-Record. 000019 03 Dealer-Number Pic X(8). 000020 03 Dealer-Name. 000021 05 Last-Name Pic X(25). 000022 05 First-Name Pic X(15). 000042 Sd Sort-Work. 000043 01 Sort-Record. 000044 03 Dealer-Number Pic X(8). 000045 03 Dealer-Name. 000046 05 Last-Name Pic X(25). 000047 05 First-Name Pic X(15). ... 000067 Working-Storage Section. 000068 Procedure Division. 000070 Sort Sort-Work Ascending Key Last-Name Of Sort-Record 000071 First-Name Of Sort-Record 000072 Middle-Name Of Sort-Record 000073 Using Dealer-Text 000074 Giving Dealer-Text 000075 000076 Display “Sort Complete” Stop Run. In quest’altro esempio che mostriamo si ottiene un file indicizzato partendo da un file sequenziale. La procedura potrebbe essere eseguita in modo più tradizionale, ma vogliamo mostrare come il SORT può essere usato anche in maniera “non ortodossa” per fare un trasferimento di record fra due file. Dichiariamo nella sezione FILECONTROL della INPUT-OUTPUT Quello mostrato è il caso più sem- SECTION il file index che sarà il riplice in assoluto; non c’è bisogno sultato finale del lavoro (Listato 2, di aprire e chiudere file, ci pensa il righe da 000014 a 000018). SORT a compiere queste operazio- Nella DATA DIVISION descriviani. mo l’FD e il record del file con chia27 Jurassic Book - Tullio Nicolussi - Il COBOL ve (righe da 000020 a 000027). L’istruzione che effettua il sort non è dissimile da quella vista precedentemente per il file sequenziale: Un file a chiave “Dealer-File” sarà restiruito ordinato in un file sequenziale “Address-File” passando attraverso un ordinamento che fa uso di un file di appoggio “Sort-Work”. Il caso più generale e anche più interessante si presenta qualora si debbano ordinare i record ma- Abbiamo aggiunto la parte “DEnipolando in qualche modo i dati o CLARATIVES” per la gestione devolendo avere pieno controllo su gli errori sui file. Lo statement SORT specifica che cosa si intende per “odinamento”. In questo caso è necessario im- l’ordinamento sarà fatto sui campi plementare una procedura di IN- “nomi” del record di sort. Si noti PUT che sarà responsabile del che rispetto agli esempi precedenti passaggio del record da elaborare non viene specificato il file di input ma al suo posto una “procedura alla routine di SORT. di input” che sarà usata dal SORT Per procedere a piccoli passi moper la lettura dei dati da ordinare. striamo l’esempio del listato 3 che consiste nell’elaborare un odina- Il nome di questa procedura non mento ottenendo un file sequen- è significativo, l’importante è che ziale ordinato, partendo questa essa sia dichiarata nella PROCEvolta da un file a chiave e utilizzan- DURE DIVISION (riga 000083 e seguenti del listato). do una INPUT PROCEDURE. ... 000014 Select Dealer-File Assign To “Dealer.Dat” 000015 Organization Is Indexed 000016 Record Key Dealer-Number Of Dealer-Record 000017 Alternate Key Dealer-Name Of Dealer-Record 000018 Access Is Sequential. ... 000020 Data Division. 000021 File Section. 000022 Fd Dealer-File. 000023 01 Dealer-Record. 000024 03 Dealer-Number Pic X(8). 000025 03 Dealer-Name. 000026 05 Last-Name Pic X(25). 000027 05 First-Name Pic X(15). ... 000067 Working-Storage Section. 000068 Procedure Division. 000070 Sort Sort-Work Ascending Key Dealer-Number Of Sort-Record 000072 Using Dealer-Text 000074 Giving Dealer-File 000075 Display “Sort Complete” 000076 Stop Run. La procedura SORT-IN apre il file di Input ed effettua un loop di lettura di tutti i record spostando i dati letti nel record di SORT. Il fatto che la SORT-IN contenga l’istruzione di apertura del file di input dovrebbe suggerire che essa non viene eseguita n-volte in loop, ma solamente all’inizio. Questo è un errore molto comune fra i principianti, cioè il ritenere che ci siano esecuzioni multiple della routine e quindi inserire in essa contatori o altro da elaborare. Seguire l’esecuzione in debug è molto istruttivo in questo come in altri casi. In effetti seguire l’esecuzione in 28 Jurassic Book - Tullio Nicolussi - Il COBOL ... 000002 000003 000005 000006 000007 000008 000009 000010 000011 000012 000013 000014 000015 000016 000017 000018 000019 000020 000021 000022 000023 000024 000025 000026 000027 000028 000030 000031 000032 000033 000034 000048 000049 000050 000051 000052 000053 000054 000055 000056 000057 000058 000059 000060 000061 000062 000063 000064 000065 000066 000067 000068 000069 000070 000071 000072 000073 000074 Identification Division. Program-Id. SORT03. Environment Division. Configuration Section. Source-Computer. IBM-PC. Object-Computer. IBM-PC. Input-Output Section. File-Control. Select Dealer-File Assign To “Dealer.Dat” Organization Indexed Record Key Dealer-Number Of Dealer-Record Alternate Record Key Dealer-Name Of Dealer-Record Access Sequential File Status Dealer-Status. Select Address-File Assign To “Address.Txt” Organization Line Sequential Access Sequential. Select Sort-Work Assign To Dealer-Sort-Work. Data Division. File Section. Fd Dealer-File. 01 Dealer-Record. 03 Dealer-Number Pic X(8). 03 Dealer-Name. 05 Last-Name Pic X(25). 05 First-Name Pic X(15). 03 Address-Line-1 Pic X(50). 03 Address-Line-2 Pic X(50). 03 City Pic X(40). 03 State-Or-Country Pic X(20). 03 Postal-Code Pic X(15). Sd Sort-Work. 01 Sort-Record. 03 Dealer-Name. 05 Last-Name Pic X(25). 05 First-Name Pic X(15). 05 Middle-Name Pic X(10). 03 Address-Line-1 Pic X(50). 03 Address-Line-2 Pic X(50). 03 City Pic X(40). 03 State-Or-Country Pic X(20). 03 Postal-Code Pic X(15). Fd Address-File. 01 Address-Record Pic X(225). Working-Storage Section. 01 Done-Flag Pic X Value Spaces. 88 All-Done Value “Y”. 01 Dealer-Status Pic XX Value “00”. Procedure Division. Declaratives. Dealer-File-Error Section. Use After Standard Error Procedure On Dealer-File. Dealer-Error. Display “Unhandled error on Dealer File “ Dealer-Status Set All-Done To True . End Declaratives. SORT03-Start. 29 Jurassic Book - Tullio Nicolussi - Il COBOL ... 000074 SORT03-Start. 000075 Sort Sort-Work Ascending Key Last-Name Of Sort-Record 000076 First-Name Of Sort-Record 000077 Middle-Name Of Sort-Record 000078 Input Procedure Sort-In 000079 Giving Address-File 000080 Display “Sort Complete” 000081 Stop Run 000082 . 000083 Sort-In. 000084 Open Input Dealer-File 000085 Perform Until All-Done 000086 Read Dealer-File 000087 At End Set All-Done To True 000088 Not At End 000089 If State-Or-Country Of Dealer-Record = “CA” 000090 Move Corresponding Dealer-Record To Sort-Record 000091 Release Sort-Record 000092 End-If 000093 End-Read 000094 End-Perform 000095 Close Dealer-File 000096 . debug del proprio codice è un consiglio che do sempre ai miei allievi: serve ad acquisire una consapevolezza di come vengono interpretate le sequenze di istruzioni che abbiamo impostato nel codice. E’ più un aspetto psicologico che pratico e mi sono fatta la convinzione che serva a far capire come la macchina sia una estensione delle nostre capacità mentali e non un oggetto staccato dalle nostre percezioni. Un punto chiave della routine SORT-IN è l’istruzione “RELEASE” che invia il record da elaborare al sort. Qui si capisce come sia possibile pre-elaborare i dati di input prima di decidere se passarli al sort oppure eventualmente scartarli del tutto. E’ anche possibile elaborare i record al termine del sort; in questo caso si costruisce una routine di 30 OUTPUT. Nel listato 4 abbiamo modificato lo statement SORT inserendo la routine personalizzata di output SORT-OUTPUT. L’esempio non usa un SORT-IN, ma potrebbe farlo. Le due routines SORT-IN e SORT-OUT possono tranquillamente convivere. Lo statement chiave è RETURN: Return Sort-Work Into DealerRecord Esso riceve dal SORT un record alla volta secondo l’ordinamento stabilito ed è quindi l’occasione per procedere ad una elaborazione dei record ordinati, non necessariamente con una scrittura su file. Jurassic Book - Tullio Nicolussi - Il COBOL ... 000072 SORT04-Start. 000073 Sort Sort-Work Ascending Key Dealer-Number Of Sort-Record 000074 Using Dealer-Text 000075 Output Procedure Sort-Out 000076 Display “Sort Complete with “ Record-Count “ Records.” 000077 Stop Run 000078 . 000079 Sort-Out. 000080 Open Output Dealer-File 000081 Perform Until All-Done 000082 Return Sort-Work Into Dealer-Record 000083 At End Set All-Done To True 000084 Not At End 000085 Add 1 To Record-Count 000086 Move Zeros To Last-Sold-Amount 000087 Last-Sold-Date 000088 Sold-To-Date 000089 Commission-To-Date 000090 Write Dealer-Record 000091 End-Return 000092 End-Perform 000093 Close Dealer-File 000094 . 31 Jurassic Book - Tullio Nicolussi - Il COBOL La gestione del video U na delle cose che non si è potuto standardizzare nel linguaggio e che di fatto ha impedito al COBOL di diventare una vera applicazione cross-platform è la gestione del video. La nascita del linguaggio risale all’epoca in cui il batch la faceva da padrone e l’input dell’utente veniva limitato di proposito, proprio per la difficoltà e il costo di questo tipo di elaborazione. Quindi ad esempio era uso prendere i parametri dall’esterno prima del lancio dell’eseguibile vero e proprio; non per nulla i sistemi IBM usano linguaggi di shell molto articolati e potenti (capaci ad esempio di creare file a chiave). Questo sotto-standard ha teorizzato l’esistenza di una sezione chiamata SCREEN SECTION nella quale si descrive il video, o meglio i campi di input-output che si vogliono rappresentare in esso. A questo punto una unica istruzione DISPLAY stampa a video l’intera immagine della sezione e un ACCEPT FROM attiverà il dialogo user-oriented. Chiaro che l’avvento di sistemi graphics-enabled e dei PC in particolare ha complicato la vita dei produttori che infatti hanno scelto ognuno per conto proprio delegando la user interface a librerie proprietarie più o meno complete. Torniamo alla nostra “quasi standard” SCREEN SECTION per definirne le caratteristiche. La SCREEN SECTION viene inserita all’interno della DATA DIVIIl verbo ACCEPT sembrava l’uni- SION subito dopo la WORKINGca possibilità di implementare il STORAGE SECTION. Ecco un classico dialogo utente, se pur con esempio nel listato 1. le limitazioni che potete immaginaIl listato 1 mostra in realtà solo la re. Anche il più recente BASIC si parte di definizione generale della è scontrato con questa difficoltà e sezione. Si intuisce che i parameinfatti le varie istruzioni di INPUT, tri specificano alcune caratteristiINKEY, etc... sono proprietarie di che come la pulizia del video priogni sistema. ma dell’emissione (Blank Screen), Da questo scenario si sono di- il colore di sfondo e quello dei castaccati i compilatori eseguibili su ratteri, etc... UNIX, grazie ad un accordo extraI colori sono standardizzati seansi fra i produttori e naturalmente condo la tabella seguente: grazie al fatto che UNIX viene naBlack 0 tivo con una sua gestione video a Blue 1 finestre (le classiche librerie CurGreen 2 ses, oltre alla standardizzazione Cyan 3 dei caratteri di controllo sul termiRed 4 nale). 32 Jurassic Book - Tullio Nicolussi - Il COBOL Magenta Brown White 5 6 7 000020 Screen Section. 000021 01 My-Main-Screen 000022 Blank Screen, Auto, Required, 000023 Foreground-Color is 7, 000024 Background-Color is 1. Mentre la seguente tabella riporta il significato degli attributi generali: Blank Screen Foreground-Color Background-Color Sign Usage Auto Full Secure Required Listato 1 Pulisce lo schermo prima dell’emissione Imposta il colore dei caratteri Inposta il colore di sfondo definizione di come saranno mostrati i campi numerici con segno Impostazione globale dei campi numerici per l’intero screen Il cursore si sposta sul prossimo campo quando si è riempito quello precedente Tutti i campi del livello devono essere riempiti I caratteri digitati non sono mostrati (stile password) I campi sono obbligatori Nel listato 2 sono state aggiunte due definizioni di campi alla section. Oltre alle “label”, cioè alle scritte fisse, i campi di input sono in questo caso due: PREZZO e DESCRIZIONE. I campi devono essere descritti nella Working-Storage Section in maniera opportuna. Nel listato 3 un esempio completo di utilizzo della Screen Section. Listato 2 000020 Screen Section. 000021 01 My-Main-Screen 000022 Blank Screen, Auto, Required, 000023 Foreground-Color is 7, 000024 Background-Color is 1. 000025 03 Line 01 Column 27 Value “Name and Address Entry” 000026 Underline. 000027 03 Line 3 Column 5 Value “Last Name “ Highlight Bell. 000019 03 Line 3 Column 16 Pic $$,$$$.99 From Prezzo. 000020 03 Line 5 Column 5 Value “Item Description” Highlight. 000021 03 Line 5 Column 22 Pic x(10) From Descrizione. 33 Jurassic Book - Tullio Nicolussi - Il COBOL 000002 Identification Division. 000003 Program-Id. Lezione05. 000004 000005 000006 000007 Environment Division. Configuration Section. Source-Computer. IBM-PC. Object-Computer. IBM-PC. 000008 Data Division. 000009 Working-Storage Section. 000010 01 Prezzo Pic 9(5)v99 Value 12.99. 000011 01 Descrizione Pic X(10) Value “Gold Coins”. 000012 Screen Section. 000013 01 Main-Screen 000014 Blank Screen, Auto, Required, 000015 Foreground-Color is 7, 000016 Background-Color is 1. 000017 03 Line 1 Column 35 Value “Item Entry”. 000018 03 Line 3 Column 5 Value “Item Value “ Highlight Bell. 000019 03 Line 3 Column 16 Pic $$,$$$.99 From Prezzo. 000020 03 Line 5 Column 5 Value “Item Description” Highlight. 000021 03 Line 5 Column 22 Pic x(10) From Descrizione. 000025 Procedure Division. 000026 Lezione05-Start. 000027 Display Main-Screen. 000028 Stop Run. Listato 3 esterne attraverso la parola chiaDiverso, come dicevamo, il caso ve “CALL”, hanno potuto dotare i dei compilatori per PC che sono loro prodotti di una gestione video apparsi dopo il 1980. Per qualche “decente”. ragione le ditte leader nel settore Nella pratica in dotazione al commainframe (ad esempio la IBM o pilatore era dato un “disegnatore la Microfocus per Unix), non pen- di maschere video”. La schermasarono subito al trasporto dei loro ta così costruita viene salvata in compilatori nell’ambiente personal qualche formato in una libreria di che si stava profilando. Questo a maschere o anche come file sinpermesso la comparsa di altri at- golo, aperta e inizializzata al motori che si sono presto specializza- mento dell’utilizzo ed infine chiusa ti (la Microsoft è stata fra questi, anche se nella “seconda ondata”). Questi si sono inventati di sana pianta una gestione del video più confacente all’ambiente interattivo di una macchina personale, anche per adeguare la loro offerta con altri compilatori meglio dotati in questo senso (basta pensare al Turbo Pascal, tanto per menzionarne uno). Sfruttando le chiamate a librerie 34 e rilasciata. I campi definiti a livello di disegno corrispondono ad altrettante aree video della WorkingStorage (più raramente della Screen Section). Vediamo un frammento di codice (listato 4) che esplica quanto detto. Il sorgente è “castrato” per mostrare solo le parti che interessano la gestione della maschera video. Sono dichiarate due strutture: la Jurassic Book - Tullio Nicolussi - Il COBOL 1 1 /***************************************************************** DATA DIVISION. ****************************************************************** WORKING-STORAGE SECTION. ***************************************************************** 01 FILETAB. 02 FILETAB-NFILE <COMP5> VALUE 5. 02 MASKLIB-FCB. 03 MASKLIB-DDNAME PIC X(10) VALUE ‘MASKLIB’. 03 MASKLIB-DSNAME PIC X(72) VALUE SPACES. 03 MASKLIB-HANDLE PIC X(4) VALUE LOW-VALUES. 03 MASKLIB-STATUS <COMP5> VALUE ZERO. 01 02 02 03 03 03 03 02 03 03 03 03 03 02 03 03 04 04 04 04 04 03 04 05 06 06 03 04 MASK-1. M1-NOME-MASK PIC X(8) VALUE ‘UT0115M1’. M1-WTRD. M1-CURSORE PIC 9(4). M1-ULT-CAMPO PIC 9(4). M1-RET-CODE PIC 9. M1-FUNCT-KEY PIC 99. M1-INIZ REDEFINES M1-WTRD. M1-RIG <COMP5>. M1-COL <COMP5>. M1-COLORE <COMP5>. M1-MODO <COMP5>. FILLER PIC 9(3). M1-DATI. M1-OPCODE PIC X(3). M1-TESTATA. M1-MODALITA PIC X(10). M1-COLLEZ-NAME PIC X(10). M1-CODICE PIC X(8). M1-DESCRIZIONE PIC X(40). M1-MODE PIC X(3). M1-TABELLA. FILLER OCCURS 20. M1-RIGA-SEL. M1-RS-FIRSTCHAR PIC X. FILLER PIC X(79). M1-TAB-RED REDEFINES M1-TABELLA. M1-TAB-CHAR OCCURS 1600 PIC X. /**************************************************************** PROCEDURE DIVISION. * --------------------------------------------------------------MAIN SECTION. INIZIO. CALL ‘SCRNOPEN’ USING MASKLIB-DSNAME RET-CODE. CALL ‘SCRNINIT’ USING MASK-1. CALL ‘SCRNWTRD’ USING MASK-1. PERFORM ELABORA THRU ELABORA-EXIT. CALL ‘SCRNCLOSE’. USCITA. STOP RUN. ELABORA. ...... ELABORA-EXIT. EXIT. Listatop 4 35 Jurassic Book - Tullio Nicolussi - Il COBOL Lo splash screen del tool SMSED, lo screen editor in dotazione al Visual Cobol della MBP. prima è la libreria delle maschere dove è stata preparata quella che andremo ad usare nel codice; la seconda struttura è la parte dati della maschera stessa, generata dal programma di disegno video e importata nel sorgente. breria. La chiamata SCRNWTRD apre il dialogo, nel senso che emette la maschera a video ed aspetta l’input. Il dialogo viene interrotto dall’uso di un tasto funzione che andrà poi testato nel successivo loop di elaborazione. Nella PROCEDURE DIVISION si inizia aprendo la librerie e inizializ- Al termine del programma si chiuzando il video. Sono le due CALL de il video e... “si va a casa” con la iniziali a routines predisposte nelle SCRNCLOSE. librerie del compilatore. Come si vede una modalità abE’ facile intuire che la funzio- bastanza agevole nell’utilizzo, tanne SCRNOPEN sta per “screen to efficace da essersi poi imposta Open” e la SCRNINIT effettua le come normale dotazione dei comoperazioni di inizializzazione della pilatori su PC. maschera video il cui nome MASKPer la cronaca questo esempio è 1 è stato inserito nella struttura di stato tratto da un compilatore chiadescrizione della maschera stesmato Visual Cobol della tedesca sa, esattamente nel campo M1MBP. NOME-MASK che è valorizzato a “UT0115M1” (il nome con il quale è stata salvata la maschera nella li36 Jurassic Book - Tullio Nicolussi - Il COBOL Due fasi della creazione di una maschera video. Sotto la scelta del nome e della libreria, sopra l’editor full screen. Siamo quindi giunti alla conclusione di questa stringata ma completa presentazione di uno dei più diffusi linguaggi di programmazione del passato. Riprendendo il discorso iniziale mi piace ribadire la validità tuttora presente di un idioma che ha saputo superare più di una moda e, seppure con notevole sforzo, adattarsi ai nuovi paradigmi della programmazione visuale, per eventi ed infine ad oggetti. Tullio Nicolussi 37