VERSIONI COBOL & DIALETTI

COBOL (COmmon Business-Oriented Language) nasce nel 1959 per iniziativa del DoD statunitense e del comitato CODASYL. È il linguaggio più longevo in ambito business/finanziario; si stima che oltre il 70% delle transazioni finanziarie globali tocchi codice COBOL.

STANDARD COBOL — EVOLUZIONE
VersioneAnnoStandardNovità Principali
COBOL-60 1960 CODASYL (informale) Prima specifica. 4 divisioni, PICTURE, MOVE, ADD/SUBTRACT, READ/WRITE. Fixed format (schede perforate). Nessun IF annidato, nessun PERFORM inline.
COBOL-61 / -61 Ext. 1961–63 CODASYL revisioni Aggiunta SORT, Report Writer, tabelle OCCURS. Correzioni alla specifica originale.
COBOL-68 1968 ANSI X3.23-1968 Primo standard ANSI ufficiale. Inter-program communication (CALL). EXAMINE (predecessore di INSPECT). Struttura definita in 3 livelli (nucleo, tabelle, I/O sequenziale).
COBOL-74 1974 ANSI X3.23-1974 File I/O indexed e relative (ISAM). PERFORM ... UNTIL. INSPECT completo (TALLYING, REPLACING, CONVERTING). DELETE/REWRITE su file indexed. STRING/UNSTRING. Moduli funzionali (11 moduli opzionali).
COBOL-85 1985 ANSI X3.23-1985 / ISO 1989:1985 Rivoluzione strutturale: scope terminators (END-IF, END-PERFORM, END-READ, ecc.), PERFORM inline, EVALUATE (switch), NOT AT END/INVALID KEY, CONTINUE, INITIALIZE, reference modification var(start:len), nested programs. De facto standard per decenni.
COBOL 2002 2002 ISO/IEC 1989:2002 OO COBOL (CLASS-ID, METHOD-ID, OBJECT REFERENCE, INVOKE). Free-format source. User-defined functions. TYPEDEF. Locale support (NATIONAL/UTF-16). Boolean data type. Binary/alphanumeric truncation. VALIDATE statement. Molte feature rimaste non implementate nei compilatori.
COBOL 2014 2014 ISO/IEC 1989:2014 Dynamic tables (OCCURS DYNAMIC). ALLOCATE/FREE (heap memory). Float IEEE (FLOAT-SHORT, FLOAT-LONG, FLOAT-EXTENDED). FUNCTION-POINTER / PROGRAM-POINTER. Conditional compilation (>>DEFINE, >>IF). RAISE / RESUME exception handling. JSON/XML GENERATE/PARSE. RETRY su I/O.
COBOL 202x ~2025 ISO/IEC 1989 (in sviluppo) In corso: miglioramenti OO, UTF-8 nativo, iteratori moderni, miglioramenti ai container, allineamento con pratiche moderne.
DIALETTI COBOL — COMPILATORI E VARIANTI
Dialetto / CompilatorePiattaformaStandardEstensioni Caratteristiche
IBM Enterprise COBOL z/OS (mainframe) COBOL 85 + estensioni COMP-5, XML GENERATE/PARSE, DB2 embedded SQL, CICS (EXEC CICS), JCL integration, EBCDIC nativo, AMODE 31/64. De facto standard mainframe.
IBM COBOL for AIX/Linux AIX, Linux on Z COBOL 2002 parziale Simile a Enterprise COBOL, ma su Unix. Supporta DB2, CICS TX. ASCII nativo.
Micro Focus COBOL
(ora Rocket Software)
Windows, Linux, Unix COBOL 2002 + 2014 parziale COMP-X, COMP-5, screen handling avanzato, .NET/JVM interop, embedded SQL, XML/JSON. IDE Visual COBOL. Gestione mainframe migration. Il più completo su piattaforme distribuite.
GnuCOBOL
(ex OpenCOBOL)
Linux, macOS, Windows, BSD COBOL 85 + 2002/2014 parziale Open source (GPL). Compila COBOL → C → eseguibile nativo. BINARY-CHAR/SHORT/LONG/DOUBLE, FLOAT-SHORT/LONG/EXTENDED, SCREEN SECTION con ncurses, COMP-X, interop C nativa. Flag -std=ibm|mf|cobol2014 per compatibilità.
ACUCOBOL-GT
(Micro Focus)
Multi-piattaforma COBOL 85 + estensioni GUI nativa, thin client, runtime interpretato. Usato in ambito PMI. ACCEPT/DISPLAY estesi con controlli grafici. Ora parte di Micro Focus extend.
Fujitsu NetCOBOL Windows, Linux, Solaris COBOL 2002 parziale Supporto Unicode nativo, PowerCOBOL (visual IDE), form printing, .NET interop, Web services. Usato in Giappone e Asia.
RM/COBOL
(Micro Focus)
Multi-piattaforma COBOL 85 Runtime interpretato leggero. Popolare nelle PMI americane anni '80-'90. Ora parte di Micro Focus.
COBOL-IT Linux, Unix, Windows COBOL 85 + 2002 parziale Compilatore commerciale alternativo. Compatibile con IBM/MF. Supporto embedded SQL (Oracle, DB2).
DIFFERENZE CHIAVE TRA DIALETTI
FeatureIBM Ent.Micro FocusGnuCOBOLStandard
COMP-3 (packed decimal)PACKED-DECIMAL
COMP-5 (native binary)No (estensione)
COMP-X (unsigned binary)NoNo (estensione)
SCREEN SECTIONNoSì (ncurses)COBOL 2002+
Embedded SQL (EXEC SQL)DB2 nativoSì (preprocessore)No (via OCESQL)No
CICS (EXEC CICS)Sì (emulato)NoNo
OO COBOL (CLASS-ID)ParzialeParzialeCOBOL 2002+
XML/JSON GENERATEJSON sì, XML parzialeCOBOL 2014
FLOAT-SHORT/LONGCOMP-1/2COBOL 2014
Free formatEnterprise V6+COBOL 2002+
ALLOCATE/FREENoParzialeNoCOBOL 2014
Codifica defaultEBCDICASCIIASCIIImpl. defined
Per la migrazione mainframe → open: GnuCOBOL con -std=ibm copre ~85% della sintassi IBM. Per copertura completa, Micro Focus è lo standard de facto nella mainframe modernization.
STRUTTURA DEL PROGRAMMA

Un programma COBOL è strutturato gerarchicamente: Program → Division → Section → Paragraph → Sentence → Statement.

*> Template minimo GnuCOBOL
       >>SOURCE FORMAT FREE

IDENTIFICATION DIVISION.
PROGRAM-ID.    nome-programma.
AUTHOR.        Nome Autore.
INSTALLATION.  Nome computer.
DATE-WRITTEN.  01 Jan 2025.
DATE-COMPILED. 01 Jan 2025.
SECURITY.      Confidential.

ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. Nome computer.
OBJECT-COMPUTER. Nome computer
    MEMORY SIZE dimensione-memoria [CHARACTERS | WORDS | MODULES]
    PROGRAM COLLATING SEQUENCE IS nome-alfabeto *> Stabilisce l'ordine di "valore" dei caratteri (MERGE e SORT)
    SEGMENT-LIMIT IS limite.
SPECIAL-NAMES.
    *> Classificazioni personalizzate
    CLASS nome IS val1, val2, ...
    DECIMAL-POINT IS COMMA
    CURRENCY SIGN IS carattere
    ALPHABET nome-alfabeto IS [ASCII | EBCDIC | NATIVE | STANDARD-1/2].
REPOSITORY.
    FUNCTION ALL INTRINSIC.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    *> Associazione file
I-O-CONTROL.

DATA DIVISION.
FILE SECTION.
    *> Descrittori FD/SD
WORKING-STORAGE SECTION.
    *> Variabili globali del programma
LOCAL-STORAGE SECTION.
    *> Variabili locali (reinizializzate ad ogni CALL)
LINKAGE SECTION.
    *> Parametri passati da programma chiamante
SCREEN SECTION.
    *> Definizioni schermi interattivi

PROCEDURE DIVISION [USING param1 param2] [RETURNING ret].
DECLARATIVES.
      *> Gestione degli errori
END DECLARATIVES.

    *> Logica del programma
    STOP RUN.
END PROGRAM nome-programma.
LE 4 DIVISIONI
DivisioneScopoSezioni principali
IDENTIFICATIONMetadati del programmaPROGRAM-ID, AUTHOR, DATE-WRITTEN, SECURITY
ENVIRONMENTAmbiente HW/SW, fileCONFIGURATION, INPUT-OUTPUT
DATADefinizione datiFILE, WORKING-STORAGE, LOCAL-STORAGE, LINKAGE, SCREEN
PROCEDURELogica elaborazioneParagrafi, Sezioni, Statements
SOURCE FORMAT — COLONNE
Fixed Format (default)
Col.Uso
1-6Numero sequenza (punch card)
7* commento, - continuazione, / form feed
8-11Area A: DIVISION, SECTION, FD, livello 01/77
12-72Area B: istruzioni, livelli 02-49
73-80Identificazione (ignorato)
Free Format (raccomandato)
>>SOURCE FORMAT FREE   *> riga 1
*> o in alternativa:
cobc -free ...
Con FREE non ci sono vincoli di colonna. I commenti usano *> ovunque nella riga.
PIC / PICTURE CLAUSE
SimboloSignificatoEsempioNote
9Cifra numerica (0-9)PIC 9(4)4 cifre intere
XQualsiasi caratterePIC X(20)Stringa alfanumerica
ASolo lettere e spaziPIC A(10)Alfabetico
SSegno (±)PIC S9(4)Prefix, non occupa byte extra a meno di SIGN SEPARATE
VPunto decimale virtualePIC 9(4)V99Non memorizza il punto fisicamente
PScaling positionPIC 9PPPMoltiplicazione/divisione per 10n
NDBCS national charPIC N(10)Caratteri nazionali (DBCS)
1Bit (boolean)PIC 1Con USAGE BIT
Esempi PIC
01 Nome        PIC X(30)  VALUE "Mario".
01 Eta         PIC 99     VALUE 0.
01 Stipendio   PIC 9(6)V99 VALUE ZEROS.
01 Temperatura PIC S9(3)V9.
01 Codice      PIC X(8).
01 Lettera     PIC A      VALUE 'A'.
PIC con SIGN
*> Segno incorporato (default)
01 N1 PIC S9(4).
*> Segno come carattere separato
01 N2 PIC S9(4) SIGN LEADING SEPARATE.
01 N3 PIC S9(4) SIGN TRAILING SEPARATE.
*> +0012  oppure  0012+
LEVEL NUMBERS
LivelloUso
01Record (Group item o Elementary item)
02-49Campi subordinati (Group o Elementary)
66RENAMES — rinomina range di campi
77Elementary item standalone (non in gruppo)
78Costante (GnuCOBOL: 78 PI VALUE 3.14159)
88Condition name — valori speciali per condizioni booleane
01 Cliente.
   02 IDCliente    PIC 9(5).
   02 NomeCliente.
       03 Cognome  PIC X(20).
       03 Nome     PIC X(20).
   02 DataNascita.
       03 Giorno   PIC 99.
       03 Mese     PIC 99.
       03 Anno     PIC 9(4).
*> FILLER: campo senza nome (placeholder)
   02 FILLER       PIC X(5) VALUE SPACES.

*> CONSTANT (GnuCOBOL)
01 MAX-SIZE     CONSTANT AS 100.
78 PI-VALUE     VALUE 3.14159265.

*> RENAMES (66)
01 DataRec.
   02 Anno  PIC 9(4).
   02 Mese  PIC 99.
   02 Giorno PIC 99.
66 MeseGiorno RENAMES Mese THRU Giorno.
COSTANTI E FIGURATIVE CONSTANTS
FigurativaSignificato
ZERO / ZEROS / ZEROESCaratteri '0': riempie PIC 9 con zero numerico, PIC X con carattere '0'
SPACE / SPACESTutti i caratteri = spazio
HIGH-VALUE / HIGH-VALUESValore massimo del tipo (x'FF')
LOW-VALUE / LOW-VALUESValore minimo del tipo (x'00')
QUOTE / QUOTESCarattere doppio apice
ALL "x"Ripete il carattere x fino a riempire
NULL / NULLSPuntatore null (per USAGE POINTER)
MOVE ZEROS  TO Stipendio.
MOVE SPACES TO Nome.
MOVE HIGH-VALUES TO EOF-Flag.
MOVE ALL "*" TO SeparatorLine.
*> Letterali numerici e alfanumerici
MOVE 42      TO Numero.
MOVE "ciao"  TO Testo.
MOVE 3.14   TO PiGreco.
*> Esadecimale
MOVE X"41"  TO CarattereA.
*> Booleano (BIT)
MOVE B"1010" TO Flags.
COMP / USAGE CLAUSE — RAPPRESENTAZIONE INTERNA
USAGEAliasRappresentazioneNote
DISPLAYdefaultEBCDIC/ASCII zoned decimal1 byte per cifra, stampa diretta
COMPUTATIONALCOMPBinario (dipende dal compilatore)GnuCOBOL = binario nativo
COMP-1Float a singola precisione (32-bit IEEE 754)Equivalente a float C
COMP-2Float a doppia precisione (64-bit IEEE 754)Equivalente a double C
COMP-3PACKED-DECIMALDecimale compresso (BCD): 2 cifre per byteComune nei mainframe IBM
COMP-4BINARYBinario intero puro2, 4 o 8 byte secondo PIC
COMP-5Binario nativo (endianness host)Usa tutti i bit, non solo quelli definiti in PIC
COMP-6Packed decimal senza segnoCome COMP-3 ma unsigned
COMP-XDipendente dal compilatore/mainframeVedi sezione dedicata ↓
POINTERPuntatore di memoria (4 o 8 byte)Per interop C
FUNCTION-POINTERPuntatore a funzionePer callback C
OBJECT REFERENCERiferimento oggetto OOSolo OO COBOL
01 ContBin    PIC 9(4)  USAGE BINARY.         *> int16
01 ContBin4   PIC 9(9)  USAGE BINARY.         *> int32
01 ValFloat   USAGE COMP-1.                   *> float C
01 ValDouble  USAGE COMP-2.                   *> double C
01 ValPacked  PIC S9(7)V99 USAGE COMP-3.     *> packed dec
01 Puntatore  USAGE POINTER.                 *> void* C
La dimensione in byte di COMP/BINARY dipende dal numero di cifre PIC:
1-4 cifre → 2 byte | 5-9 cifre → 4 byte | 10-18 cifre → 8 byte
COMP-X — DETTAGLIO ESTESO

COMP-X è una clausola USAGE specifica di GnuCOBOL e Micro Focus. Il comportamento dipende dal contesto:

COMP-X con PIC X(n) — Intero unsigned n byte
DichiarazioneByteRangeEquiv. C
PIC X(1) COMP-X10 – 255uint8_t
PIC X(2) COMP-X20 – 65535uint16_t
PIC X(4) COMP-X40 – 4294967295uint32_t
PIC X(8) COMP-X80 – 264-1uint64_t
COMP-X con PIC 9(n) — Binario unsigned (stile MF)
DichiarazioneByteNote
PIC 9(1) COMP-X10-255, come COMP-5 ma unsigned forced
PIC 9(4) COMP-X20-65535
PIC 9(9) COMP-X40-4294967295
PIC 9(18) COMP-X80-18446744073709551615
COMP-X speciali (GnuCOBOL esteso)
TipoDescrizione
USAGE BINARY-CHAR1 byte signed (int8_t)
USAGE BINARY-CHAR UNSIGNED1 byte unsigned (uint8_t)
USAGE BINARY-SHORT2 byte signed (int16_t)
USAGE BINARY-SHORT UNSIGNED2 byte unsigned (uint16_t)
USAGE BINARY-LONG4 byte signed (int32_t)
USAGE BINARY-LONG UNSIGNED4 byte unsigned (uint32_t)
USAGE BINARY-DOUBLE8 byte signed (int64_t)
USAGE BINARY-DOUBLE UNSIGNED8 byte unsigned (uint64_t)
USAGE FLOAT-SHORT32-bit IEEE 754 (float)
USAGE FLOAT-LONG64-bit IEEE 754 (double)
USAGE FLOAT-EXTENDED80/128-bit extended (long double)
*> Esempio pratico: buffer di byte per interop C
01 RawByte    PIC X(1) COMP-X VALUE 0.
01 Word16     PIC X(2) COMP-X.
01 DWord32    PIC X(4) COMP-X.
01 QWord64    PIC X(8) COMP-X.
01 Cnt8s      USAGE BINARY-CHAR.       *> int8_t
01 Cnt8u      USAGE BINARY-CHAR UNSIGNED. *> uint8_t
01 IntVal     USAGE BINARY-LONG.       *> int32_t
01 BigVal     USAGE BINARY-DOUBLE.     *> int64_t
01 FltVal     USAGE FLOAT-LONG.        *> double
⚠ COMP-X con PIC X(n) usa big-endian su alcuni sistemi mainframe. GnuCOBOL usa l'endianness nativo dell'host (little-endian su x86). Verificare con -fcomp-version o test espliciti.
EDITED PICTURES — FORMATTAZIONE OUTPUT
SimboloEffettoEsempioInput → Output
ZSopprime zero a sinistra (sostituisce con spazio)ZZZ90012 → " 12"
*Riempie zero a sinistra con asterisco***90012 → "**12"
$Simbolo valuta mobile$$,$$$,$$9.991234.56 → "$1,234.56"
+Mostra segno + o -+9(4)+1234 → "+1234"
-Mostra - se negativo, spazio se positivo-(5)-42 → " -42"
,Inserisce virgola9,9991234 → "1,234"
.Punto decimale fisico9(4).991234.56 → "1234.56"
/Inserisce slash99/99/999912212024 → "12/21/2024"
BInserisce spazio99B991234 → "12 34"
0Inserisce zero letterale in posizione9900991234 → "120034"
CRStampa CR se negativo9(6).99CR-100 → " 100.00CR"
DBStampa DB se negativo9(6).99DB
01 StartNum  PIC 9(8)V99  VALUE 1234.56.
01 Formattato PIC $$,$$$,$$9.99.   *> $1,234.56
01 Data       PIC 99/99/9999.      *> 12/21/2024
01 SenzaZeri  PIC ZZZZ9.99.        *>    1234.56 (no leading zeros)
MOVE StartNum TO Formattato
DISPLAY Formattato.
REDEFINES & FILLER — RI-MAPPATURA DELLA MEMORIA

REDEFINES permette di accedere alla stessa area di memoria con layout diversi (simile a union in C). Il campo ridefinito e quello originale condividono gli stessi byte fisici: scrivere in uno modifica l'altro.

Regole REDEFINES
RegolaDettaglio
Stesso livelloIl campo REDEFINES deve avere lo stesso numero di livello del campo originale
DimensioneIl campo ridefinente non deve essere piu' grande dell'originale (puo' essere uguale o piu' piccolo)
OrdineLa clausola REDEFINES deve seguire immediatamente il campo originale (senza campi intermedi allo stesso livello)
No VALUEUn campo con REDEFINES non puo' avere clausola VALUE (lo standard lo vieta; alcuni compilatori lo tollerano)
No su livello 01 in FILE SECTIONIn FILE SECTION, i record 01 sono gia' ridefinizioni implicite dello stesso buffer
No su 66, 77, 88REDEFINES non e' applicabile ai livelli speciali
REDEFINES multipliPiu' campi possono ridefinire lo stesso campo originale (catena di REDEFINES)
Esempi di REDEFINES
*> Stesso storage, visto come testo o come numero
01 DataGrezza    PIC X(8).
01 DataNum       REDEFINES DataGrezza PIC 9(8).
01 DataStruct    REDEFINES DataGrezza.
   02 Anno         PIC 9(4).
   02 Mese         PIC 99.
   02 Giorno       PIC 99.
*> MOVE "20241225" TO DataGrezza
*> DISPLAY Anno    -> "2024"
*> DISPLAY DataNum -> 20241225

*> Union-style: interpretare lo stesso dato come int o float
01 RawArea       PIC X(4).
01 IntView       REDEFINES RawArea USAGE BINARY-LONG.
01 FloatView     REDEFINES RawArea USAGE FLOAT-SHORT.

*> REDEFINES in strutture di gruppo (subordinati)
01 Indirizzo.
   02 CodicePostale PIC X(5).
   02 CPStrutturato REDEFINES CodicePostale.
       03 Regione      PIC XX.
       03 Comune       PIC X(3).
   02 Citta         PIC X(30).
Pattern: pre-riempimento tabella con REDEFINES + FILLER
*> Tecnica classica per inizializzare una tabella con valori noti
01 MesiTable.
   02 MesiData.
       03 FILLER PIC X(9) VALUE "Gennaio  ".
       03 FILLER PIC X(9) VALUE "Febbraio ".
       03 FILLER PIC X(9) VALUE "Marzo    ".
       03 FILLER PIC X(9) VALUE "Aprile   ".
       *> ... (12 FILLER totali)
   02 FILLER REDEFINES MesiData.
       03 NomeMese PIC X(9) OCCURS 12 TIMES.
*> DISPLAY NomeMese(3)  -> "Marzo    "
FILLER — Campi senza nome

FILLER e' un campo anonimo (senza nome referenziabile) che occupa spazio nel record ma non e' indirizzabile direttamente nel codice. Usi principali:

UsoDescrizioneEsempio
Spaziatura nei recordPadding tra campi per allineamento o formato fisso02 FILLER PIC X(5) VALUE SPACES.
Aree riservateByte riservati per future espansioni del tracciato02 FILLER PIC X(20).
Costanti in tabelleDati pre-caricati (vedi pattern REDEFINES sopra)03 FILLER PIC X(10) VALUE "Testo".
Label in SCREEN SECTIONTesto fisso sullo schermo non referenziabile02 FILLER VALUE "Titolo".
Record di outputSeparatori e decorazioni nelle righe di stampa02 FILLER PIC X VALUE "/".
*> Record con FILLER per formato tracciato fisso
01 RecordFisso.
   02 RF-Codice     PIC 9(5).
   02 FILLER        PIC X(3) VALUE SPACES.   *> separatore
   02 RF-Nome       PIC X(30).
   02 FILLER        PIC X(12).              *> riservato
   02 RF-Importo    PIC 9(7)V99.

*> Da COBOL-85: la parola FILLER e' opzionale
01 RecordModerno.
   02 PIC X(5) VALUE SPACES.  *> FILLER implicito
   02 RM-Nome PIC X(20).
INITIALIZE e FILLER: per default, INITIALIZE non tocca i campi FILLER. Per includerli: INITIALIZE Record WITH FILLER. Analogamente, MOVE CORRESPONDING ignora i FILLER.
LEVEL 88 — CONDITION NAMES

I livelli 88 definiscono nomi di condizione associati a un campo genitore. Non occupano memoria propria: sono alias booleani che testano se il genitore contiene determinati valori. Sono l'equivalente COBOL degli enum e dei flag booleani dei linguaggi moderni.

Sintassi e forme di VALUE
FormaSignificatoEsempio
VALUE literalSingolo valore88 Attivo VALUE 1.
VALUE lit1, lit2, ...Lista di valori (OR implicito)88 Errore VALUE 'E', 'F', 'G'.
VALUE lit1 THRU lit2Range continuo (estremi inclusi)88 Valido VALUE 1 THRU 99.
VALUES ARE lit1 THRU lit2, lit3Range + valori singoli combinati88 OK VALUES ARE 'A' THRU 'F', 'X'.
VALUE FALSE IS literalValore assegnato con SET ... TO FALSE88 Flag VALUE 'Y' FALSE 'N'.
Definizione — Esempi completi
*> Booleano semplice (flag On/Off)
01 WS-EOF       PIC 9 VALUE 0.
   88 EOF-Reached  VALUE 1.
   88 Not-EOF      VALUE 0.

*> Stato con valori multipli (lista)
01 Stato          PIC X.
   88 StApertura   VALUE 'A'.
   88 StChiusura   VALUE 'C'.
   88 StErrore     VALUE 'E', 'F', 'G'.
   *> StErrore e' TRUE se Stato = 'E' OR 'F' OR 'G'

*> Range continuo con THRU
01 Voto           PIC 99.
   88 Insufficiente VALUE 0 THRU 17.
   88 Sufficiente   VALUE 18 THRU 23.
   88 Buono         VALUE 24 THRU 27.
   88 Ottimo        VALUE 28 THRU 30.
   88 VotoValido    VALUE 0 THRU 30.

*> Range combinato con valori singoli
01 CodiceResp     PIC X(2).
   88 RespOK       VALUES ARE "00", "02", "04".
   88 RespWarning  VALUES ARE "10" THRU "19".
   88 RespError    VALUES ARE "20" THRU "49", "99".

*> FALSE IS: permette SET ... TO FALSE
01 WS-Switch      PIC X VALUE 'N'.
   88 Attivato     VALUE 'Y' FALSE 'N'.

*> Su campo alfanumerico (HIGH-VALUES per EOF)
01 WS-Flag        PIC X.
   88 EOF-Flag     VALUE HIGH-VALUES.
SET — Assegnamento tramite Condition Name

SET condizione TO TRUE scrive nel campo genitore il primo valore della lista VALUE. E' il modo idiomatico COBOL per modificare lo stato di un flag senza conoscere il valore concreto.

*> SET ... TO TRUE: assegna il primo VALUE al genitore
SET EOF-Reached TO TRUE.    *> WS-EOF diventa 1
SET StApertura  TO TRUE.    *> Stato diventa 'A'
SET StErrore    TO TRUE.    *> Stato diventa 'E' (primo della lista)
SET Sufficiente TO TRUE.    *> Voto diventa 18 (inizio del range)

*> SET ... TO FALSE: richiede clausola FALSE IS nella definizione
SET Attivato TO FALSE.       *> WS-Switch diventa 'N'
*> ERRORE se FALSE IS non dichiarato: SET StApertura TO FALSE
Uso nelle condizioni (IF / EVALUATE / PERFORM)
*> Test diretto: il livello 88 e' gia' una condizione booleana
IF EOF-Reached
    DISPLAY "Fine file"
END-IF.

*> Negazione
IF NOT StApertura
    DISPLAY "Non in stato aperto"
END-IF.

*> In EVALUATE TRUE (pattern switch idiomatico)
EVALUATE TRUE
    WHEN Insufficiente DISPLAY "Bocciato"
    WHEN Sufficiente   DISPLAY "Sufficiente"
    WHEN Buono         DISPLAY "Buono"
    WHEN Ottimo        DISPLAY "Ottimo"
END-EVALUATE.

*> In condizione di loop
PERFORM UNTIL EOF-Reached
    READ InputFile
        AT END SET EOF-Reached TO TRUE
        NOT AT END PERFORM ProcessaRecord
    END-READ
END-PERFORM.

*> Validazione input con range
ACCEPT Voto FROM CONSOLE.
IF NOT VotoValido
    DISPLAY "Voto non valido (0-30)"
END-IF.
Regole chiave:
• Un livello 88 non ha PIC proprio — eredita il tipo dal genitore.
SET x TO TRUE assegna il primo valore della clausola VALUE al campo genitore.
SET x TO FALSE e' legale solo se la definizione include FALSE IS.
• Un campo puo' avere un numero illimitato di livelli 88 associati.
• THRU segue l'ordinamento collating sequence (EBCDIC o ASCII) per i campi alfanumerici.
• I livelli 88 sono il meccanismo standard per evitare magic numbers nel codice COBOL.
LOCAL-STORAGE SECTION

La LOCAL-STORAGE SECTION, introdotta in COBOL 2002, e' una sezione della DATA DIVISION che dichiara variabili reinizializzate automaticamente ad ogni invocazione del programma (tramite CALL). La differenza fondamentale con la WORKING-STORAGE e' il ciclo di vita dei dati.

WORKING-STORAGE vs LOCAL-STORAGE
CaratteristicaWORKING-STORAGELOCAL-STORAGE
PersistenzaI dati persistono tra CALL successive allo stesso programmaI dati vengono reinizializzati (ai VALUE) ad ogni CALL
AllocazioneStatica: allocata una volta al primo caricamentoDinamica: allocata/deallocata ad ogni invocazione (stack-like)
VALUE inizialeAssegnato solo alla prima esecuzione (o dopo CANCEL)Assegnato ad ogni esecuzione
Senza VALUEContenuto indefinito (di solito zero-filled dalla prima volta)Contenuto indefinito ad ogni invocazione
Thread safetyCondivisa tra thread (non thread-safe)Ogni thread ha la propria copia (thread-safe)
Visibilita'Visibile per tutta la durata del programma in memoriaVisibile solo durante l'esecuzione corrente
Uso tipicoContatori persistenti, tabelle, configurazione, record bufferVariabili temporanee, contatori locali, flag di invocazione
Posizione nella DATA DIVISION
DATA DIVISION.
FILE SECTION.
    *> FD / SD
WORKING-STORAGE SECTION.
    *> Dati persistenti tra CALL
    01 WS-CallCount   PIC 9(5) VALUE 0.   *> inizializzato 1 volta
LOCAL-STORAGE SECTION.
    *> Dati reinizializzati ad ogni CALL
    01 LS-Temp        PIC X(50) VALUE SPACES. *> SPACES ad ogni CALL
    01 LS-Counter     PIC 9(3) VALUE 0.     *> 0 ad ogni CALL
    01 LS-NoValue     PIC X(10).              *> INDEFINITO ad ogni CALL
LINKAGE SECTION.
    *> Parametri dal chiamante
Esempio: differenza di comportamento
IDENTIFICATION DIVISION.
PROGRAM-ID. CONTATORE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-Count PIC 9(3) VALUE 0.
LOCAL-STORAGE SECTION.
01 LS-Count PIC 9(3) VALUE 0.

PROCEDURE DIVISION.
    ADD 1 TO WS-Count.
    ADD 1 TO LS-Count.
    DISPLAY "WS: " WS-Count " LS: " LS-Count.
    EXIT PROGRAM.

*> Risultato dopo 3 CALL consecutive:
*> CALL 1: WS: 001 LS: 001
*> CALL 2: WS: 002 LS: 001  (LS reinizializzato!)
*> CALL 3: WS: 003 LS: 001  (LS reinizializzato!)
Quando usare LOCAL-STORAGE
ScenarioSezione consigliataMotivazione
Sottoprogramma chiamato piu' volteLOCAL-STORAGEOgni invocazione parte da uno stato pulito, senza residui dalla CALL precedente
Programma multi-thread (COBOL in server application)LOCAL-STORAGEOgni thread ottiene la propria copia indipendente
Contatore che deve accumularsi tra CALLWORKING-STORAGEI dati devono persistere
Tabella di lookup caricata una sola voltaWORKING-STORAGEEvita di ricaricare ad ogni invocazione
Buffer temporaneo in un sottoprogrammaLOCAL-STORAGEGarantisce un buffer pulito ad ogni chiamata
⚠ Se un campo LOCAL-STORAGE non ha VALUE, il suo contenuto e' indefinito ad ogni invocazione (non e' garantito che sia zero o spaces). Sempre dichiarare VALUE per i campi LOCAL-STORAGE che verranno letti prima di essere scritti.
MOVE — ASSEGNAMENTO
MOVE sorgente TO dest1 [dest2 ...].
MOVE CORRESPONDING src TO dest.
*> Sposta campi con stesso nome

MOVE "Mario"  TO Nome.
MOVE 100     TO Eta, Conta.
MOVE ZEROS  TO Totale.
MOVE SPACES TO Linea.
*> MOVE per Group item: copia raw
MOVE RecordA TO RecordB.
Regole di troncamento e padding
Regole MOVE:
• Numerico → Numerico: allineamento al punto decimale; cifre in eccesso troncate a sinistra (interi) e a destra (decimali)
• Alfa → Alfa: allineamento a sinistra, troncamento a destra o padding con SPACES a destra
• Numerico → Alfa: converte in stringa, allineamento a sinistra
• Alfa → Numerico: converte se il contenuto è numerico valido, altrimenti risultato indefinito
• Group → Group: copia byte-per-byte (alphanumeric), nessuna conversione di tipo
*> Troncamento numerico: PIC 9(3) contiene max 999
MOVE 12345 TO Campo3Dig.  *> risultato: 345 (troncato a sx)

*> Troncamento decimale: PIC 9(3)V99
MOVE 3.14159 TO CampoDec.  *> risultato: 003.14 (troncato a dx)

*> Troncamento alfanumerico: PIC X(5)
MOVE "Hello World" TO Corto. *> risultato: "Hello" (troncato a dx)
MOVE "Hi"          TO Corto. *> risultato: "Hi   " (padding spazi)
Tabella compatibilità MOVE
Sorgente ↓ / Dest →AlphanumericNumeric displayNumeric editedAlpha editedGroup
AlphanumericOKOK (se numerico)OK (se numerico)OKOK
Numeric displayOKOKOKOKOK
Numeric editedOKNONOOKOK
Alpha editedOKNONOOKOK
GroupOKOK (come alfa)OK (come alfa)OKOK
MOVE CORRESPONDING — Dettaglio
*> MOVE CORR copia solo i campi con NOME identico
01 RecordA.
   02 Nome    PIC X(20) VALUE "Mario".
   02 Eta     PIC 99    VALUE 30.
   02 Codice  PIC X(5)  VALUE "AB123".
01 RecordB.
   02 Nome    PIC X(20).
   02 Eta     PIC 99.
   02 Indirizzo PIC X(30).

MOVE CORRESPONDING RecordA TO RecordB.
*> Copia solo Nome e Eta (nomi in comune)
*> Codice ignorato (non esiste in RecordB)
*> Indirizzo non toccato (non esiste in RecordA)
*> FILLER ignorato sempre da MOVE CORRESPONDING
MOVE CORRESPONDING confronta i nomi degli item elementari subordinati a tutti i livelli della gerarchia (non solo al primo livello). I campi vengono matchati se hanno lo stesso nome e la stessa struttura di qualificatori. FILLER e campi con REDEFINES sono sempre ignorati.
ARITMETICA
Verbi Aritmetici
ADD      A TO B.              *> B = B+A
ADD      A TO B GIVING C.    *> C = A+B
ADD      A, B, C TO D.       *> D = A+B+C+D
SUBTRACT A FROM B.           *> B = B-A
SUBTRACT A FROM B GIVING C. *> C = B-A
MULTIPLY A BY B.             *> B = A*B
MULTIPLY A BY B GIVING C.   *> C = A*B
DIVIDE   A INTO B.           *> B = B/A
DIVIDE   A INTO B GIVING C  *> C=B/A
         REMAINDER R.         *> R=B mod A
COMPUTE (espressioni)
COMPUTE C = A + B.
COMPUTE C = A - B.
COMPUTE C = A * B.
COMPUTE C = A / B.
COMPUTE C = A ** 2.    *> potenza
COMPUTE C = (A + B) * D.
COMPUTE C ROUNDED = A / B.
ADD 1 TO C ON SIZE ERROR
    DISPLAY "Overflow"
END-ADD.
Clausola ROUNDED: arrotondamento al più vicino (default NEAREST-EVEN). Varianti: ROUNDED MODE TRUNCATION, FLOOR, CEILING, TOWARD-GREATER, TOWARD-LESSER.
OPERAZIONI SU STRINGHE
STRING — Concatenazione
STRING Str1 DELIMITED BY SIZE
       Str2 DELIMITED BY SPACE
       Str3 DELIMITED BY "#"
       INTO Dest
       [WITH POINTER Ptr]
       [ON OVERFLOW ...]
END-STRING.
UNSTRING — Split
UNSTRING Sorgente
    DELIMITED BY "," OR " "
    INTO Parte1, Parte2
    [DELIMITER IN DelChar]
    [COUNT IN NumChar]
    [WITH POINTER Ptr]
    [TALLYING IN Count]
    [ON OVERFLOW ...]
END-UNSTRING.
Funzioni stringa intrinseche
FUNCTION UPPER-CASE(Str)       *> tutto maiuscolo
FUNCTION LOWER-CASE(Str)       *> tutto minuscolo
FUNCTION LENGTH(Str)           *> lunghezza in caratteri
FUNCTION TRIM(Str [LEADING|TRAILING]) *> rimozione spazi
FUNCTION REVERSE(Str)          *> inverti stringa
FUNCTION CONCATENATE(S1, S2)   *> join (GnuCOBOL)
FUNCTION SUBSTITUTE(Str, Da, A) *> replace
FUNCTION NUMVAL(Str)           *> stringa → numero
FUNCTION NUMVAL-C(Str [,Symbol]) *> stringa valuta → num
FUNCTION CHAR(N)               *> numero → ASCII char
FUNCTION ORD(Ch)               *> char → posizione
INSPECT — SCANSIONE E SOSTITUZIONE
*> Conta caratteri
INSPECT Str TALLYING
    Count1 FOR CHARACTERS
    Count2 FOR ALL 'e'
    Count3 FOR LEADING ' '.

*> Sostituisce caratteri
INSPECT Str REPLACING
    ALL     'a' BY '@'
    LEADING ' ' BY '0'
    FIRST   'X' BY 'Y'
    CHARACTERS BY '*'.

*> Combina TALLYING e REPLACING
INSPECT Str
    TALLYING  Cnt FOR ALL 'e'
    REPLACING ALL 'e' BY '3'.

*> CONVERTING (mappatura carattere per carattere)
INSPECT Str CONVERTING "aeiou" TO "AEIOU".

*> ─── BEFORE / AFTER INITIAL ───
*> Limita l'azione a una porzione della stringa

*> Conta le 'a' solo PRIMA della prima virgola
INSPECT Str TALLYING
    Cnt FOR ALL 'a' BEFORE INITIAL ','.

*> Conta le 'a' solo DOPO la prima virgola
INSPECT Str TALLYING
    Cnt FOR ALL 'a' AFTER INITIAL ','.

*> Sostituisci spazi con zeri solo prima del primo '.'
INSPECT NumStr REPLACING
    LEADING ' ' BY '0' BEFORE INITIAL '.'.

*> Conversione case solo dopo un separatore
INSPECT Str CONVERTING
    "abcdefghijklmnopqrstuvwxyz" TO
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    AFTER INITIAL ":".
BEFORE/AFTER INITIAL si applica a TALLYING, REPLACING e CONVERTING. INITIAL indica la prima occorrenza del delimitatore. Se il delimitatore non viene trovato: BEFORE opera sull'intera stringa, AFTER non opera su nulla. Si possono combinare BEFORE e AFTER nella stessa clausola per delimitare una sottostringa.
INITIALIZE — INIZIALIZZAZIONE STRUTTURATA

INITIALIZE imposta i campi ai valori di default per tipo: SPACES per alfanumerici, ZEROS per numerici. Molto più sicuro di MOVE SPACES su un intero gruppo.

*> Inizializza tutti i campi di un record ai default
INITIALIZE Cliente.
*> Equivale a: MOVE SPACES TO ogni PIC X, MOVE ZEROS TO ogni PIC 9

*> Inizializza solo i campi alfanumerici
INITIALIZE Cliente REPLACING ALPHANUMERIC DATA BY SPACES.

*> Inizializza solo i numerici con un valore specifico
INITIALIZE Tabella REPLACING NUMERIC DATA BY -1.

*> INITIALIZE con ALL (COBOL 2002+): resetta anche FILLER
INITIALIZE Record1 WITH FILLER.

*> Categorie disponibili per REPLACING:
*>   ALPHABETIC, ALPHANUMERIC, NUMERIC,
*>   ALPHANUMERIC-EDITED, NUMERIC-EDITED,
*>   NATIONAL, DBCS

*> DEFAULT (COBOL 2014+): usa i VALUE dichiarati nei campi
INITIALIZE Cliente TO VALUE.
*> Ripristina i VALUE originali dalla definizione in DATA DIVISION
INITIALIZE non tocca i campi FILLER (a meno di WITH FILLER). Non tocca i campi con REDEFINES. Non resetta gli indici (INDEX). Per azzerare una tabella intera: INITIALIZE TabRec è più sicuro di MOVE SPACES TO TabRec che corrompe i campi numerici.
IF / EVALUATE — CONDIZIONI
IF
IF Eta > 18
    DISPLAY "Maggiorenne"
ELSE
    IF Eta = 18
        DISPLAY "Appena maggiorenne"
    ELSE
        DISPLAY "Minore"
    END-IF
END-IF.

*> Operatori di confronto
*> =  EQUAL TO
*> >  GREATER THAN
*> <  LESS THAN
*> >= GREATER THAN OR EQUAL TO
*> <= LESS THAN OR EQUAL TO
*> NOT EQUAL TO
*> AND, OR, NOT (logici)
*> IS NUMERIC / ALPHABETIC
*> IS ALPHABETIC-UPPER/LOWER

*> ─── Class Conditions ───
IF Campo IS NUMERIC       *> solo 0-9, +, -, .
IF Campo IS ALPHABETIC    *> solo A-Z, a-z, spazi
IF Campo IS ALPHABETIC-UPPER
IF Campo IS ALPHABETIC-LOWER
IF Campo IS NOT NUMERIC

*> ─── Sign Conditions ───
IF Saldo IS POSITIVE     *> > 0
IF Saldo IS NEGATIVE     *> < 0
IF Saldo IS ZERO         *> = 0
IF Saldo IS NOT ZERO

*> ─── Abbreviated Conditions ───
*> Invece di: IF A = 1 OR A = 2 OR A = 3
IF A = 1 OR 2 OR 3
    DISPLAY "Valido".
*> Invece di: IF A > 5 AND A < 10
IF A > 5 AND < 10
    DISPLAY "Nel range".
EVALUATE (switch)
EVALUATE TRUE
    WHEN IsPrime    DISPLAY "Primo"
    WHEN IsOdd      DISPLAY "Dispari"
    WHEN IsEven     DISPLAY "Pari"
    WHEN OTHER      DISPLAY "Default"
END-EVALUATE.

EVALUATE Scelta ALSO Modo
    WHEN 1 ALSO 'A'  PERFORM ParagA
    WHEN 2 ALSO ANY  PERFORM ParagB
    WHEN 3 THRU 5
           ALSO ANY  PERFORM ParagC
END-EVALUATE.
PERFORM — LOOP E CHIAMATA PARAGRAFI
*> Chiama un paragrafo
PERFORM NomeParagrafo.
PERFORM NomeParagrafo THRU AltroParagrafo.

*> Ripeti N volte
PERFORM 5 TIMES
    DISPLAY "Loop"
END-PERFORM.

*> While (test prima)
PERFORM UNTIL Indice > 10
    ADD 1 TO Indice
END-PERFORM.

*> Do-While (test dopo)
PERFORM WITH TEST AFTER UNTIL Indice > 10
    ADD 1 TO Indice
END-PERFORM.

*> For loop
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 10
    DISPLAY I
END-PERFORM.

*> For loop annidato
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 3
    AFTER J FROM 1 BY 1 UNTIL J > 3
        DISPLAY I " " J
END-PERFORM.

*> PERFORM con paragrafo esterno e VARYING
PERFORM StampaRiga VARYING I FROM 1 BY 1 UNTIL I > 5.
GO TO — SALTO INCONDIZIONATO
GO TO Paragrafo.
*> DEPENDING ON: switch su variabile
GO TO Para1, Para2, Para3
    DEPENDING ON Scelta.
*> EXIT: uscita da paragrafo/sezione
EXIT PARAGRAPH. *> esce dal paragrafo corrente
EXIT PROGRAM.   *> ritorna al chiamante
EXIT SECTION.   *> esce dalla sezione corrente
STOP RUN.       *> termina il programma

*> ─── ALTER (COBOL-68/74 — OBSOLETO) ───
*> Modifica a runtime la destinazione di un GO TO
Dispatch.
    GO TO DefaultHandler.
DefaultHandler.
    DISPLAY "Nessun handler".
SpecialHandler.
    DISPLAY "Handler speciale".

*> Cambia la destinazione di Dispatch
ALTER Dispatch TO PROCEED TO SpecialHandler.
*> Ora GO TO in Dispatch salta a SpecialHandler
⚠ GO TO è sconsigliato nella programmazione strutturata moderna. Preferire PERFORM. ALTER è stato rimosso dallo standard COBOL 2002+ ed è considerato una delle feature più pericolose del linguaggio: rende il flusso di controllo non determinabile staticamente. Nessun codice nuovo dovrebbe usarlo.
PARAGRAFI, SEZIONI E GRAVITY

Gravity (fall-through): in COBOL, l'esecuzione scorre sequenzialmente da un paragrafo al successivo, senza fermarsi. Un paragrafo non è una funzione: senza STOP RUN, GO TO o EXIT, il controllo "cade" nel paragrafo seguente.

Gravity — Esempio critico
PROCEDURE DIVISION.
Main.
    DISPLAY "Inizio".
    PERFORM CalcolaIVA.
    DISPLAY "Fatto".
    STOP RUN.           *> SENZA questo, cade in CalcolaIVA!

CalcolaIVA.
    COMPUTE TotaleIVA = Imponibile * 1.22.
    *> Senza STOP RUN sopra, dopo Main il controllo
    *> cadrebbe qui per gravity, eseguendo CalcolaIVA
    *> DUE VOLTE: una via PERFORM, una via fall-through.

Stampa.
    DISPLAY "Totale: " TotaleIVA.
    *> Dopo CalcolaIVA, cade qui per gravity
PERFORM vs Gravity
MeccanismoComportamentoRitorno
PERFORM ParaEsegue il paragrafo e ritorna al chiamanteAutomatico alla fine del paragrafo
PERFORM Para THRU ParaFineEsegue da Para a ParaFine incluso, poi ritornaAlla fine di ParaFine
Gravity (fall-through)L'esecuzione scorre sequenzialmente senza ritornoNessuno — continua al paragrafo successivo
GO TO ParaSalto incondizionato, non ritornaNessuno
Sezioni nella PROCEDURE DIVISION
*> Una SECTION raggruppa più paragrafi
SezioneUno SECTION.
    ParagA.
        DISPLAY "A".
        *> Cade in ParagB per gravity
    ParagB.
        DISPLAY "B".
        EXIT SECTION.  *> Esce dalla sezione

*> PERFORM SezioneUno esegue TUTTI i paragrafi
*> della sezione (ParagA + ParagB) e poi ritorna.
Il pattern più sicuro per evitare errori di gravity: terminare sempre il paragrafo "main" con STOP RUN o GOBACK, e usare PERFORM per chiamare i paragrafi di servizio. Nei programmi legacy, il fall-through è intenzionale e il flusso è controllato con GO TO.
TABELLE (ARRAY)
*> Array 1D — subscript parte da 1!
01 Tabella1.
   02 Amico   PIC X(15) OCCURS 5 TIMES.

*> Array 2D
01 TabClienti.
   02 Cliente OCCURS 10 TIMES.
       03 CNome   PIC X(20).
       03 CEmail  PIC X(40).

*> Tabella con INDEX esplicito
01 OrdineTab.
   02 Prodotto OCCURS 5 TIMES INDEXED BY I.
       03 ProdNome PIC X(10).
       03 ProdSize OCCURS 3 TIMES INDEXED BY J.
           04 TipoTaglia PIC A.

*> OCCURS con range variabile (ODO)
01 MaxItems PIC 99 VALUE 10.
01 ListaDin.
   02 Elem PIC X(10) OCCURS 1 TO 20 TIMES
              DEPENDING ON MaxItems.

*> Accesso a elementi
MOVE 'Joy'    TO Amico(1).
DISPLAY        Amico(2).
SET I J TO 1.
MOVE 'S' TO   TipoTaglia(I, J).
SET I UP BY 1.   *> incremento index
SET I DOWN BY 1. *> decremento index

*> Tabella con ASCENDING/DESCENDING KEY (per SEARCH ALL)
01 CodTab.
   02 CodEntry OCCURS 100 TIMES
              ASCENDING KEY IS CodID
              INDEXED BY KI.
       03 CodID   PIC 9(5).
       03 CodDesc PIC X(30).
SEARCH — RICERCA IN TABELLA
SEARCH (lineare)
SET I TO 1.
SEARCH Prodotto
    AT END
        DISPLAY "Non trovato"
    WHEN ProdNome(I) = 'Blue'
        DISPLAY "Trovato"
END-SEARCH.
SEARCH ALL (binaria)
*> Richiede ASCENDING/DESCENDING KEY
SEARCH ALL CodEntry
    AT END
        DISPLAY "Codice non trovato"
    WHEN CodID(KI) = Cerca
        DISPLAY CodDesc(KI)
END-SEARCH.
Precondizioni per SEARCH ALL
*> 1. La tabella DEVE dichiarare ASCENDING/DESCENDING KEY
01 TabCodici.
   02 CodEntry OCCURS 100 TIMES
       ASCENDING KEY IS CodID
       INDEXED BY KI.
       03 CodID   PIC 9(5).
       03 CodDesc PIC X(20).

*> 2. I dati DEVONO essere pre-ordinati sulla KEY
*>    SEARCH ALL non ordina: esegue ricerca binaria
*>    su dati che ASSUME siano già ordinati.
*>    Dati non ordinati → risultati imprevedibili!

*> 3. La WHEN può usare SOLO = (non > o <)
*> 4. Non serve SET prima di SEARCH ALL (l'indice
*>    è gestito automaticamente dall'algoritmo binario)
*> 5. Condizioni multiple: solo AND, mai OR
SEARCH ALL CodEntry
    AT END DISPLAY "Non trovato"
    WHEN CodID(KI) = Cerca
      AND CodDesc(KI) = DescCerca
        DISPLAY "Trovato"
END-SEARCH.
SEARCH vs SEARCH ALL: SEARCH (lineare) è O(n) e richiede SET dell'indice prima della chiamata. SEARCH ALL (binaria) è O(log n) ma richiede dati pre-ordinati e ASCENDING/DESCENDING KEY nella definizione. Per tabelle piccole (<50 elementi) la differenza è trascurabile.
SORT / MERGE FILE
*> SORT: ordina un file tramite file di lavoro
SORT WorkFile
    ON ASCENDING KEY  WIDNum
    [ON DESCENDING KEY WNome]
    USING  OrgFile
    GIVING SortedFile.

*> SORT con INPUT/OUTPUT PROCEDURE
SORT WorkFile ON ASCENDING KEY WIDNum
    INPUT PROCEDURE  IS ReadAndFilter
    OUTPUT PROCEDURE IS WriteOutput.

*> MERGE: unisce file già ordinati
MERGE WorkFile ON ASCENDING KEY WIDNum
    USING  File1, File2
    GIVING NewFile.

*> RELEASE (dentro INPUT PROCEDURE) → aggiunge record al sort
RELEASE WStudData FROM StudData.
*> RETURN (dentro OUTPUT PROCEDURE) → legge record dal sort
RETURN WorkFile INTO StudData AT END MOVE 'Y' TO Done.
INPUT/OUTPUT PROCEDURE — Esempio completo

Le procedure permettono di filtrare/trasformare i record prima e dopo l'ordinamento.

SORT WorkFile ON ASCENDING KEY WIDNum
    INPUT PROCEDURE  IS FiltraInput
    OUTPUT PROCEDURE IS ScriviOutput.

*> ─── INPUT PROCEDURE: legge, filtra e passa al sort ───
FiltraInput.
    OPEN INPUT OrgFile.
    PERFORM UNTIL EOF
        READ OrgFile AT END SET EOF TO TRUE END-READ
        IF NOT EOF
            IF Stato = "A"              *> filtra: solo attivi
                RELEASE WStudData FROM StudData
            END-IF
        END-IF
    END-PERFORM.
    CLOSE OrgFile.

*> ─── OUTPUT PROCEDURE: legge dal sort e scrive ───
ScriviOutput.
    OPEN OUTPUT SortedFile.
    PERFORM UNTIL SortDone
        RETURN WorkFile INTO StudData
            AT END SET SortDone TO TRUE
        END-RETURN
        IF NOT SortDone
            ADD 1 TO RecCount       *> conteggio
            WRITE OutRec FROM StudData
        END-IF
    END-PERFORM.
    CLOSE SortedFile.
Regole: Dentro INPUT PROCEDURE si usa solo RELEASE (mai WRITE). Dentro OUTPUT PROCEDURE si usa solo RETURN (mai READ sul sort file). USING/GIVING e INPUT/OUTPUT PROCEDURE sono mutuamente esclusivi: non si possono combinare nella stessa clausola.
FILE MANAGEMENT — ARCHITETTURA SELECT / FD

La gestione file in COBOL si articola su tre livelli distribuiti tra le divisioni. Comprendere la relazione tra questi livelli e' fondamentale per qualsiasi programma batch o transazionale.

I tre livelli della gestione file
LivelloDoveClausolaScopo
1. Associazione logicaENVIRONMENT DIVISION → INPUT-OUTPUT SECTION → FILE-CONTROLSELECTAssocia un nome-file logico COBOL a un file fisico esterno, e dichiara organizzazione, modalita' di accesso e chiavi
2. Descrizione recordDATA DIVISION → FILE SECTIONFD / SDDefinisce la struttura (layout) dei record del file: campi, tipi, dimensioni
3. Operazioni I/OPROCEDURE DIVISIONOPEN, READ, WRITE, REWRITE, DELETE, START, CLOSEEsegue le operazioni fisiche di lettura/scrittura
SELECT (FILE-CONTROL) — Anatomia completa
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT [OPTIONAL] nome-file-logico
        ASSIGN TO "percorso-fisico"  *> o variabile WS
        ORGANIZATION IS tipo-org       *> SEQUENTIAL | LINE SEQUENTIAL | INDEXED | RELATIVE
        ACCESS MODE IS tipo-accesso     *> SEQUENTIAL | RANDOM | DYNAMIC
        [RECORD KEY IS campo-chiave]    *> solo INDEXED
        [ALTERNATE RECORD KEY IS campo
            [WITH DUPLICATES]]          *> solo INDEXED
        [RELATIVE KEY IS campo]         *> solo RELATIVE
        [FILE STATUS IS ws-status]      *> PIC XX per controllo errori
        [LOCK MODE IS tipo-lock]        *> MANUAL | AUTOMATIC | EXCLUSIVE
        .
FD (FILE SECTION) — Descrittore di file
FILE SECTION.
FD nome-file-logico                    *> DEVE corrispondere al nome nel SELECT
    [BLOCK CONTAINS n RECORDS]        *> blocco fisico (performance I/O)
    [RECORD CONTAINS n CHARACTERS]    *> lunghezza record fissa
    [RECORD IS VARYING IN SIZE
        FROM min TO max CHARACTERS
        DEPENDING ON ws-len]            *> record a lunghezza variabile
    [LABEL RECORDS ARE STANDARD]       *> label tape (obsoleto, ma richiesto in alcuni dialect)
    [DATA RECORD IS nome-record]       *> informativo
    [LINAGE IS n LINES]              *> per file di stampa
    [REPORT IS nome-report]            *> per Report Writer
    .
*> Segue la definizione dei record (uno o piu' 01)
01 NomeRecord.
   02 Campo1 PIC ...
   02 Campo2 PIC ...

*> SD: Sort/merge file Descriptor (per file di lavoro SORT)
SD WorkFile.
01 WorkRecord.
   02 WKey   PIC 9(5).
   02 WData  PIC X(75).
Relazione SELECT ↔ FD

Il legame e' basato sul nome-file-logico: il nome usato nel SELECT deve corrispondere esattamente a quello nell'FD. La SELECT definisce come si accede al file; la FD definisce cosa contiene il file.

*> ─── ENVIRONMENT DIVISION ───
FILE-CONTROL.
    SELECT ClienteFile               *> nome logico (1)
        ASSIGN TO "clienti.idx"      *> file fisico
        ORGANIZATION IS INDEXED        *> tipo organizzazione
        ACCESS MODE IS DYNAMIC         *> modalita' di accesso
        RECORD KEY IS CL-ID            *> chiave primaria (campo nel record FD)
        FILE STATUS IS WS-FS.

*> ─── DATA DIVISION ───
FILE SECTION.
FD ClienteFile                      *> stesso nome logico (1)
    RECORD CONTAINS 80 CHARACTERS.
01 ClienteRecord.
   02 CL-ID      PIC 9(5).          *> questa e' la RECORD KEY
   02 CL-Nome    PIC X(30).
   02 CL-Saldo   PIC S9(7)V99.
   02 FILLER     PIC X(36).
Tipi di organizzazione
ORGANIZATIONStrutturaAccesso consentitoUso tipico
SEQUENTIALRecord in sequenza binaria (record-length header)Solo SEQUENTIALFile batch, comunicazione inter-programma
LINE SEQUENTIALRighe di testo delimitate da newline (CR/LF)Solo SEQUENTIALFile di testo, log, CSV, interfaccia con Unix
INDEXEDRecord con indice B-tree su una o piu' chiaviSEQUENTIAL, RANDOM, DYNAMICAnagrafe, archivi, tabelle di lookup
RELATIVERecord identificati da numero di posizione (slot)SEQUENTIAL, RANDOM, DYNAMICHash table su disco, buffer circolare
Modalita' di accesso (ACCESS MODE)
ACCESS MODESignificatoOperazioni
SEQUENTIALI record vengono letti/scritti nell'ordine in cui sono memorizzatiREAD (next), WRITE (append), REWRITE (in-place)
RANDOMAccesso diretto tramite chiave (INDEXED) o numero relativo (RELATIVE)READ (per chiave), WRITE, REWRITE, DELETE
DYNAMICCombinazione: permette sia accesso sequenziale che random nello stesso OPENREAD, READ NEXT, WRITE, REWRITE, DELETE, START
Verbi I/O e modalita' di apertura
VerboINPUTOUTPUTI-OEXTEND
READSi'NoSi'No
WRITENoSi'Si' (solo INDEXED/RELATIVE)Si'
REWRITENoNoSi'No
DELETENoNoSi'No
STARTSi'NoSi'No
⚠ La clausola OPTIONAL nel SELECT permette di aprire un file inesistente senza errore (FILE STATUS "05"): il runtime lo crea vuoto. Senza OPTIONAL, un OPEN INPUT su file inesistente genera FILE STATUS "35" (file not found).
I-O-CONTROL — CONTROLLO I/O AVANZATO

Il paragrafo I-O-CONTROL nella INPUT-OUTPUT SECTION specifica informazioni sul buffering, la condivisione di aree di memoria tra file, e il checkpoint/restart. E' opzionale ma importante per le ottimizzazioni I/O nei batch mainframe.

Posizione nell'ENVIRONMENT DIVISION
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT FileA ASSIGN TO "filea.dat".
    SELECT FileB ASSIGN TO "fileb.dat".
I-O-CONTROL.
    *> clausole di controllo I/O
Clausole principali
ClausolaSintassiDescrizione
SAME RECORD AREASAME RECORD AREA FOR file1, file2I file condividono lo stesso buffer di record in memoria. Un READ su uno sovrascrive il buffer dell'altro. Ottimizza la memoria quando si elaborano file uno alla volta.
SAME AREASAME AREA FOR file1, file2I file condividono sia il buffer I/O che il record area. Piu' restrittivo: i file non possono essere aperti contemporaneamente.
SAME SORT AREASAME SORT AREA FOR sort-file1, sort-file2I file di lavoro SORT condividono la stessa area di lavoro. Utile quando i SORT sono eseguiti in sequenza, non in parallelo.
SAME SORT-MERGE AREASAME SORT-MERGE AREA FOR sm1, sm2Analogo a SAME SORT AREA, per file di MERGE.
MULTIPLE FILEMULTIPLE FILE TAPE CONTAINS file1, file2Piu' file logici risiedono sulla stessa unita' nastro. Rilevante in ambito mainframe legacy.
APPLY WRITE-ONLYAPPLY WRITE-ONLY ON file1Ottimizzazione: il buffer viene scritto su disco solo quando e' pieno (IBM). Riduce le operazioni I/O fisiche.
RERUNRERUN ON file EVERY n RECORDS OF file2Checkpoint/restart: salva lo stato ogni N record elaborati. Permette di riprendere un batch interrotto dal punto dell'ultimo checkpoint.
Esempi pratici
I-O-CONTROL.
    *> Condivisione buffer: File1 e File2 usano la stessa area record
    *> (non possono essere letti contemporaneamente)
    SAME RECORD AREA FOR File1, File2.

    *> Checkpoint ogni 1000 record elaborati (mainframe)
    RERUN ON CheckFile EVERY 1000 RECORDS OF InputFile.

    *> Ottimizzazione scrittura (IBM)
    APPLY WRITE-ONLY ON OutputFile.
In pratica: I-O-CONTROL e' usato principalmente in ambiente mainframe IBM per ottimizzazione I/O e checkpoint/restart nei job batch di lunga durata. In GnuCOBOL, molte clausole sono accettate sintatticamente ma possono non avere effetto operativo. Le clausole legate ai nastri (MULTIPLE FILE TAPE) sono obsolete.
FILE I/O — SEQUENZIALI
Definizione FILE-CONTROL
FILE-CONTROL.
SELECT ClienteFile
    ASSIGN TO "clienti.dat"
    ORGANIZATION IS LINE SEQUENTIAL
    ACCESS IS SEQUENTIAL
    [FILE STATUS IS WS-FileStatus].
FILE STATUS codes
CodiceSignificato
00OK
10End of file
22Chiave duplicata
23Chiave non trovata
30Errore I/O permanente
35File non trovato
41File già aperto
42File non aperto
47File non aperto in INPUT
48File non aperto in OUTPUT
*> Scrittura
OPEN OUTPUT ClienteFile.
    MOVE 1 TO IDNum.
    WRITE ClienteData [FROM WSCliente]
        [AFTER ADVANCING 1 LINE]
        [INVALID KEY DISPLAY "Errore"]
    END-WRITE.
CLOSE ClienteFile.

*> Lettura
OPEN INPUT ClienteFile.
PERFORM UNTIL EOF = 'Y'
    READ ClienteFile [INTO WSCliente]
        AT END MOVE 'Y' TO EOF
        NOT AT END DISPLAY WSCliente
    END-READ
END-PERFORM.
CLOSE ClienteFile.

*> Append
OPEN EXTEND ClienteFile.
    WRITE ClienteData.
CLOSE ClienteFile.
FILE I/O — INDEXED (ISAM)
FILE-CONTROL.
SELECT ClienteFile ASSIGN TO "clienti.idx"
    ORGANIZATION IS INDEXED
    ACCESS MODE IS RANDOM    *> o DYNAMIC o SEQUENTIAL
    RECORD KEY IS IDNum
    [ALTERNATE RECORD KEY IS Cognome WITH DUPLICATES]
    FILE STATUS IS FS.

*> Aggiunta (WRITE)
OPEN I-O ClienteFile.
MOVE 99 TO IDNum.
WRITE ClienteData INVALID KEY DISPLAY "ID duplicato" END-WRITE.

*> Lettura per chiave (RANDOM)
MOVE 5 TO IDNum.
READ ClienteFile INVALID KEY DISPLAY "Non trovato" END-READ.

*> Aggiornamento
REWRITE ClienteData INVALID KEY DISPLAY "Errore" END-REWRITE.

*> Cancellazione
DELETE ClienteFile INVALID KEY DISPLAY "Non trovato" END-DELETE.

*> Lettura sequenziale (ACCESS DYNAMIC)
START ClienteFile KEY GREATER THAN IDNum
    INVALID KEY DISPLAY "Errore" END-START.
READ ClienteFile NEXT RECORD INTO WSCliente
    AT END MOVE 'Y' TO EOF END-READ.
FILE I/O — RELATIVE

Organizzazione RELATIVE: ogni record ha un numero relativo (posizione). Accesso diretto per numero, utile per tabelle di lookup su disco.

FILE-CONTROL.
SELECT SlotFile ASSIGN TO "slot.dat"
    ORGANIZATION IS RELATIVE
    ACCESS MODE IS DYNAMIC    *> o SEQUENTIAL o RANDOM
    RELATIVE KEY IS WS-Slot
    FILE STATUS IS WS-FS.

DATA DIVISION.
FILE SECTION.
FD SlotFile.
01 SlotRecord  PIC X(80).

WORKING-STORAGE SECTION.
01 WS-Slot  PIC 9(4).
01 WS-FS    PIC XX.

PROCEDURE DIVISION.
OPEN I-O SlotFile.

*> Scrittura diretta nello slot 5
MOVE 5 TO WS-Slot.
MOVE "Dati slot 5" TO SlotRecord.
WRITE SlotRecord INVALID KEY DISPLAY "Slot occupato" END-WRITE.

*> Lettura diretta per slot
MOVE 3 TO WS-Slot.
READ SlotFile INVALID KEY DISPLAY "Slot vuoto" END-READ.

*> Cancellazione
DELETE SlotFile INVALID KEY DISPLAY "Errore" END-DELETE.

*> Lettura sequenziale (ACCESS DYNAMIC)
MOVE 1 TO WS-Slot.
START SlotFile KEY NOT LESS THAN WS-Slot
    INVALID KEY DISPLAY "Errore" END-START.
READ SlotFile NEXT RECORD
    AT END DISPLAY "Fine" END-READ.

CLOSE SlotFile.
ConfrontoSEQUENTIALRELATIVEINDEXED
AccessoSolo sequenzialePer numero recordPer chiave alfanumerica
ChiaveNessunaNumero relativo (PIC 9)Campo nel record
DELETENo
REWRITESì (stessa lunghezza)
BuchiNoSì (slot vuoti)No
Uso tipicoLog, batchLookup fisso, hashDatabase, anagrafe
REPORT WRITER

Il Report Writer (RW) automatizza intestazioni, piè pagina, subtotali e impaginazione. Richiede REPORT SECTION nella DATA DIVISION e verbi INITIATE/GENERATE/TERMINATE.

Definizione FILE-CONTROL e FD
FILE-CONTROL.
SELECT ReportFile ASSIGN TO "report.txt".

FILE SECTION.
FD ReportFile REPORT IS VenditeReport.
REPORT SECTION — Struttura RD
REPORT SECTION.
RD VenditeReport
    CONTROLS ARE FINAL WS-Regione
    PAGE LIMIT IS 60 LINES
    HEADING 1
    FIRST DETAIL 5
    LAST DETAIL 55
    FOOTING 58.

*> PAGE HEADING — stampato in cima a ogni pagina
01 TYPE PAGE HEADING.
   02 LINE 1.
       03 COLUMN 1  PIC X(20) VALUE "REPORT VENDITE".
       03 COLUMN 60 PIC X(8)  SOURCE WS-Data.
   02 LINE 3.
       03 COLUMN 1  PIC X(10) VALUE "Regione".
       03 COLUMN 15 PIC X(10) VALUE "Prodotto".
       03 COLUMN 30 PIC X(10) VALUE "Importo".

*> CONTROL HEADING — all'inizio di ogni gruppo
01 TYPE CONTROL HEADING WS-Regione.
   02 LINE PLUS 1.
       03 COLUMN 1  PIC X(20) SOURCE WS-Regione.

*> DETAIL — riga di dettaglio per ogni GENERATE
01 RigaDettaglio TYPE DETAIL.
   02 LINE PLUS 1.
       03 COLUMN 15 PIC X(15) SOURCE WS-Prodotto.
       03 COLUMN 30 PIC $$$,$$9.99 SOURCE WS-Importo.

*> CONTROL FOOTING — alla fine di ogni gruppo (subtotale)
01 TYPE CONTROL FOOTING WS-Regione.
   02 LINE PLUS 1.
       03 COLUMN 20 PIC X(10) VALUE "Subtot:".
       03 COLUMN 30 PIC $$$,$$9.99 SUM WS-Importo.

*> REPORT FOOTING (FINAL) — totale generale
01 TYPE CONTROL FOOTING FINAL.
   02 LINE PLUS 2.
       03 COLUMN 20 PIC X(10) VALUE "TOTALE:".
       03 COLUMN 30 PIC $$$$,$$9.99 SUM WS-Importo.

*> PAGE FOOTING — piè pagina
01 TYPE PAGE FOOTING.
   02 LINE 58.
       03 COLUMN 30 PIC X(7)  VALUE "Pagina ".
       03 COLUMN 37 PIC Z9   SOURCE PAGE-COUNTER.
Verbi Report Writer
PROCEDURE DIVISION.
OPEN OUTPUT ReportFile.
INITIATE VenditeReport.       *> inizializza contatori e report

PERFORM UNTIL EOF
    READ InputFile AT END SET EOF TO TRUE END-READ
    GENERATE RigaDettaglio    *> produce una riga, gestisce automaticamente
                                *> page break, heading, footing, subtotali
END-PERFORM.

TERMINATE VenditeReport.      *> stampa gli ultimi footing e totali
CLOSE ReportFile.
Tipi di gruppo RD
TipoQuando viene stampato
REPORT HEADINGUna volta, all'inizio del report (dopo INITIATE)
PAGE HEADINGIn cima a ogni pagina
CONTROL HEADINGQuando il valore di un campo di controllo cambia
DETAILPer ogni GENERATE
CONTROL FOOTINGAlla fine di un gruppo di controllo (subtotali)
PAGE FOOTINGIn fondo a ogni pagina
REPORT FOOTINGUna volta, alla fine del report (dopo TERMINATE)
Stampa manuale (senza Report Writer)
*> Pattern alternativo con WRITE / ADVANCING
01 PrintLine  PIC X(80).
01 LineCount  PIC 99  VALUE ZERO.
       88 NuovaPagina VALUE 60 THRU 99.

WRITE PrintLine FROM Intestazione
    AFTER ADVANCING PAGE.
WRITE PrintLine FROM LineaDettaglio
    AFTER ADVANCING 1 LINE.
WRITE PrintLine FROM Separatore
    BEFORE ADVANCING 2 LINES.
Clausole avanzate del Report Writer
ClausolaDoveEffetto
GROUP INDICATECampo in DETAILIl campo viene stampato solo alla prima riga del gruppo (poi viene soppresso). Utile per evitare ripetizioni del nome regione su ogni riga.
RESET ONCampo con SUMSpecifica quando azzerare un accumulatore. Default: si azzera al cambio del controllo associato al footing. RESET ON FINAL mantiene il totale per l'intero report.
USE BEFORE REPORTINGDECLARATIVESProcedura invocata prima della stampa di un gruppo RD. Permette logica personalizzata (calcoli, soppressione condizionale via SUPPRESS PRINTING).
SUPPRESS PRINTINGDentro USE BEFORE REPORTINGImpedisce la stampa del gruppo corrente (soppressione condizionale di righe).
*> GROUP INDICATE: stampa la regione solo sulla prima riga
01 RigaDettaglio TYPE DETAIL.
   02 LINE PLUS 1.
       03 COLUMN 1  PIC X(15) SOURCE WS-Regione
           GROUP INDICATE.           *> solo alla prima riga del gruppo
       03 COLUMN 20 PIC X(15) SOURCE WS-Prodotto.
       03 COLUMN 40 PIC $$$,$$9.99 SOURCE WS-Importo.

*> RESET ON: accumulatore che NON si azzera a ogni gruppo
01 TYPE CONTROL FOOTING WS-Regione.
   02 LINE PLUS 1.
       03 COLUMN 20 PIC X(12)     VALUE "Subtot:".
       03 COLUMN 40 PIC $$$,$$9.99 SUM WS-Importo.
       03 COLUMN 55 PIC $$$,$$9.99 SUM WS-Importo
           RESET ON FINAL.            *> totale progressivo, mai azzerato
*> USE BEFORE REPORTING: logica custom prima della stampa
DECLARATIVES.
Controllo-Dettaglio SECTION.
    USE BEFORE REPORTING RigaDettaglio.
Controllo-Dettaglio-Para.
    IF WS-Importo = 0
        SUPPRESS PRINTING          *> non stampare righe con importo zero
    END-IF.
END DECLARATIVES.
Il Report Writer automatizza ciò che altrimenti richiede gestione manuale di contatori pagina, intestazioni e subtotali. Non tutti i compilatori lo supportano pienamente: GnuCOBOL ha supporto parziale. GROUP INDICATE e RESET ON sono supportati nella maggior parte delle implementazioni; USE BEFORE REPORTING richiede DECLARATIVES.
CALL — SUBROUTINE E SOTTOPROGRAMMI
Programma chiamato (GETSUM.cob)
*> Compila: cobc -m GETSUM.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. GETSUM.
DATA DIVISION.
LINKAGE SECTION.
   01 LNum1  PIC 9.
   01 LNum2  PIC 9.
   01 LSum   PIC 99.
PROCEDURE DIVISION USING LNum1 LNum2 LSum.
   COMPUTE LSum = LNum1 + LNum2.
EXIT PROGRAM.
Programma chiamante
*> Compila: cobc -x main.cob
CALL 'GETSUM'
    USING Num1, Num2, Sum1.

*> BY REFERENCE (default): modifiche visibili
CALL 'PROC' USING BY REFERENCE Var1.

*> BY CONTENT: copia; modifiche non visibili
CALL 'PROC' USING BY CONTENT Var1.

*> BY VALUE: passa valore diretto (per C)
CALL 'PROC' USING BY VALUE 42.

*> RETURNING: valore di ritorno
CALL 'FUNZ' USING Param
    RETURNING Risultato.

*> ON EXCEPTION: gestione errore
CALL 'MODULO' USING Dati
    ON EXCEPTION DISPLAY "Modulo mancante"
END-CALL.
CALL STATIC vs CALL DINAMICA
CALL Dinamica (default)

Il modulo viene caricato a runtime (dynamic linking). Il nome è risolto al momento dell'esecuzione. Richiede .so / .dll visibile.

CALL "nome-modulo" USING Arg1 Arg2.
*> Oppure con variabile
01 NomeModulo PIC X(20) VALUE "CALCOLA".
CALL NomeModulo USING Dati.   *> Risolto a runtime
CALL STATIC

Il modulo viene incorporato al momento della link (static linking). Richiede che tutti i moduli siano compilati insieme o linkati con -lnome.

*> Modo 1: flag compilatore (preferito)
cobc -x -fstatic-call main.cob MODULO.cob

*> Modo 2: direttiva nel sorgente (GnuCOBOL)
>>CALL-CONVENTION STATIC
CALL "CALCOLA" USING Dati.

*> Modo 3: con REPOSITORY (OO/moderni)
REPOSITORY.
    FUNCTION MiaFunzione
        AS "mia-funzione" IS STATIC.
CaratteristicaDinamicaStatica
Nome callLetterale o variabileSolo letterale noto a compile time
LinkingRuntime (dlopen)Compile time (ld)
VelocitàPiù lenta (risoluzione runtime)Più veloce (no overhead)
FlessibilitàAlta (plug-in, moduli dinamici)Bassa (binario monolitico)
Flag cobcdefault-fstatic-call
CANCEL — Scarica modulo dinamico
CANCEL "nome-modulo".
*> Forza rilascio dalla memoria e reinizializza
*> le variabili globali del modulo alla prossima CALL
CALL — FUNZIONI C, LIBRERIE E SYSTEM CALLS
Chiamata di funzioni C standard
*> printf / puts
01 MsgBuf PIC X(80) VALUE "Ciao mondo!\n\x00".
CALL "puts"   USING BY REFERENCE MsgBuf.
CALL "printf" USING BY REFERENCE MsgBuf.

*> malloc / free
01 BufPtr  USAGE POINTER.
01 BufSize USAGE BINARY-LONG.
MOVE 1024 TO BufSize.
CALL "malloc" USING BY VALUE BufSize
    RETURNING BufPtr.
CALL "free"   USING BY VALUE BufPtr.

*> strlen
01 StrLen USAGE BINARY-LONG.
CALL "strlen" USING BY REFERENCE MsgBuf
    RETURNING StrLen.

*> memcpy
01 SrcBuf PIC X(100).
01 DstBuf PIC X(100).
01 BufLen USAGE BINARY-LONG VALUE 100.
CALL "memcpy"
    USING BY REFERENCE DstBuf
          BY REFERENCE SrcBuf
          BY VALUE     BufLen.

*> getenv
01 EnvPtr    USAGE POINTER.
01 EnvName   PIC X(20) VALUE "HOME\x00".
CALL "getenv" USING BY REFERENCE EnvName
    RETURNING EnvPtr.

*> system (shell command)
01 Cmd PIC X(80) VALUE "ls -l\x00".
CALL "system" USING BY REFERENCE Cmd.
GnuCOBOL Built-in C interop
*> CBL_OC_GETENV / CBL_OC_SETENV (GnuCOBOL native)
CALL "CBL_OC_GETENV"
    USING BY REFERENCE  EnvName
          BY REFERENCE  EnvValue.

*> CBL_GC_FORK (solo Unix)
CALL "CBL_GC_FORK" RETURNING PID.

*> Accesso a memoria tramite puntatore
01 RawPtr  USAGE POINTER.
01 ValAdr  USAGE BINARY-LONG BASED.
SET ADDRESS OF ValAdr TO RawPtr.
DISPLAY ValAdr.  *> deref del puntatore
System Calls POSIX (via C wrapper)
*> open / read / write / close
01 FD-Sys   USAGE BINARY-LONG.
01 Flags    USAGE BINARY-LONG VALUE 0.    *> O_RDONLY=0
01 Mode     USAGE BINARY-LONG VALUE 0.
01 FilePath PIC X(40) VALUE "/etc/hostname\x00".
CALL "open"
    USING BY REFERENCE FilePath
          BY VALUE     Flags
          BY VALUE     Mode
    RETURNING FD-Sys.

01 Buffer   PIC X(256).
01 BufLen   USAGE BINARY-LONG VALUE 256.
01 BytesRd  USAGE BINARY-LONG.
CALL "read"
    USING BY VALUE     FD-Sys
          BY REFERENCE Buffer
          BY VALUE     BufLen
    RETURNING BytesRd.
CALL "close" USING BY VALUE FD-Sys.
Per chiamare funzioni C da COBOL: stringhe devono terminare con \x00 (null byte). Compilare con cobc -x prog.cob -lc (di solito implicito).
OBJECT ORIENTED COBOL
Definizione Classe (todolist.cob)
CLASS-ID. todolist.
DATA DIVISION.
CLASS-STORAGE SECTION.
   01 ListName PIC X(20).
PROCEDURE DIVISION.
FACTORY.
   METHOD-ID. new.
   DATA DIVISION.
   LINKAGE SECTION.
       01 LName PIC X(20).
   PROCEDURE DIVISION USING LName
       RETURNING SELF.
       MOVE LName TO ListName.
       INVOKE SUPER "new"
           RETURNING SELF.
   END METHOD new.
END FACTORY.
END CLASS todolist.
Uso della Classe
REPOSITORY.
    CLASS TodoCls AS "todolist".
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WkTodo USAGE OBJECT REFERENCE TodoCls.

PROCEDURE DIVISION.
*> Crea istanza
INVOKE TodoCls "new"
    USING BY CONTENT "La mia lista"
    RETURNING WkTodo.
*> Chiama metodo
INVOKE WkTodo "PrintToDos".
*> Distruggi oggetto
INVOKE WkTodo "finalize".
Metodi di istanza (OBJECT)
CLASS-ID. Contatore.
DATA DIVISION.
CLASS-STORAGE SECTION.
   01 Valore PIC 9(5) VALUE ZERO.

PROCEDURE DIVISION.
FACTORY.
   METHOD-ID. new.
   PROCEDURE DIVISION RETURNING SELF.
       INVOKE SUPER "new" RETURNING SELF.
   END METHOD new.
END FACTORY.

OBJECT.
   *> Metodi di istanza (non FACTORY)
   METHOD-ID. Incrementa.
   PROCEDURE DIVISION.
       ADD 1 TO Valore.
   END METHOD Incrementa.

   METHOD-ID. GetValore.
   DATA DIVISION.
   LINKAGE SECTION.
       01 LVal PIC 9(5).
   PROCEDURE DIVISION RETURNING LVal.
       MOVE Valore TO LVal.
   END METHOD GetValore.
END OBJECT.
END CLASS Contatore.
Ereditarietà (INHERITS)
*> Classe derivata che eredita da Contatore
CLASS-ID. ContatoreMax INHERITS Contatore.
DATA DIVISION.
CLASS-STORAGE SECTION.
   01 MaxVal PIC 9(5) VALUE 100.

PROCEDURE DIVISION.
OBJECT.
   *> Override del metodo Incrementa
   METHOD-ID. Incrementa OVERRIDE.
   PROCEDURE DIVISION.
       IF Valore < MaxVal
           INVOKE SUPER "Incrementa"
       END-IF.
   END METHOD Incrementa.
END OBJECT.
END CLASS ContatoreMax.
Interfacce (COBOL 2002+)
*> Definizione di un'interfaccia
INTERFACE-ID. Stampabile.
PROCEDURE DIVISION.
   METHOD-ID. Stampa.
   PROCEDURE DIVISION.
   END METHOD Stampa.
END INTERFACE Stampabile.

*> Classe che implementa l'interfaccia
CLASS-ID. Documento IMPLEMENTS Stampabile.
*> DEVE fornire implementazione di Stampa
Riepilogo OO COBOL
ConcettoCostrutto COBOLNote
ClasseCLASS-IDContiene FACTORY (metodi di classe) e OBJECT (metodi di istanza)
CostruttoreMETHOD-ID. new in FACTORYDeve chiamare INVOKE SUPER "new"
Metodo istanzaMETHOD-ID in OBJECTAccede a CLASS-STORAGE
EreditarietàINHERITSSingola ereditarietà; override con OVERRIDE
InterfacciaINTERFACE-IDContratto puro; IMPLEMENTS nella classe
PolimorfismoUSAGE OBJECT REFERENCERiferimento generico: USAGE OBJECT REFERENCE Stampabile
DistruttoreINVOKE obj "finalize"Rilascio manuale dell'oggetto
Il supporto OO varia molto tra compilatori. GnuCOBOL ha supporto limitato (CLASS-ID base, FACTORY). IBM Enterprise COBOL e Micro Focus hanno supporto più completo. Il codice OO COBOL è raro nel mainframe legacy.
CONVERSIONE TIPI C → COBOL
Tipo CCOBOL (USAGE)COBOL (PIC)Byte
int8_tUSAGE BINARY-CHARPIC S9(3)1
uint8_tUSAGE BINARY-CHAR UNSIGNEDPIC 9(3)1
int16_tUSAGE BINARY-SHORTPIC S9(5)2
uint16_tUSAGE BINARY-SHORT UNSIGNEDPIC 9(5)2
int32_tUSAGE BINARY-LONGPIC S9(9)4
uint32_tUSAGE BINARY-LONG UNSIGNEDPIC 9(9)4
int64_tUSAGE BINARY-DOUBLEPIC S9(18)8
uint64_tUSAGE BINARY-DOUBLE UNSIGNEDPIC 9(18)8
floatUSAGE FLOAT-SHORT o COMP-1N/A (no PIC)4
doubleUSAGE FLOAT-LONG o COMP-2N/A8
long doubleUSAGE FLOAT-EXTENDEDN/A16
char[n]PIC X(n)n
char* (null-term)USAGE POINTERPIC X(n) + \x00ptr size
void*USAGE POINTER4/8
size_tUSAGE BINARY-LONG UNSIGNED (32-bit)
USAGE BINARY-DOUBLE UNSIGNED (64-bit)
PIC 9(10) / PIC 9(18)4/8
bool (C99)PIC 9(1) o PIC 1 USAGE BITPIC 91
*> Esempio pratico
01 CIntVal    USAGE BINARY-LONG.         *> int32_t
01 CUIntVal   USAGE BINARY-LONG UNSIGNED. *> uint32_t
01 CFloat     USAGE FLOAT-SHORT.          *> float
01 CDouble    USAGE FLOAT-LONG.           *> double
01 CString    PIC X(64).                  *> char[64]
01 CPtr       USAGE POINTER.              *> void*
C STRUCT, ENUM, PUNTATORI → COBOL
struct C → Group Item COBOL
// C
typedef struct {
    int32_t  id;
    char     nome[32];
    float    saldo;
    uint8_t  flag;
} Cliente;
*> COBOL equivalente
01 Cliente.
   02 ID      USAGE BINARY-LONG.
   02 Nome    PIC X(32).
   02 Saldo   USAGE FLOAT-SHORT.
   02 Flag    USAGE BINARY-CHAR UNSIGNED.
union C → REDEFINES
// C
union Dato {
    int32_t  intero;
    float    reale;
    char     bytes[4];
};
*> COBOL
01 DatoRaw   PIC X(4).
01 DatoInt   REDEFINES DatoRaw
               USAGE BINARY-LONG.
01 DatoFloat REDEFINES DatoRaw
               USAGE FLOAT-SHORT.
enum C → Level 88
// C
typedef enum {
    APERTO = 0,
    CHIUSO = 1,
    ERRORE = 2
} Stato;
*> COBOL
01 StatoCod USAGE BINARY-LONG VALUE 0.
   88 APERTO   VALUE 0.
   88 CHIUSO   VALUE 1.
   88 ERRORE   VALUE 2.
*> Uso: SET APERTO TO TRUE.
*>      IF CHIUSO DISPLAY "Chiuso".
Puntatori
01 MioPtr    USAGE POINTER.
01 IntTarget USAGE BINARY-LONG BASED.  *> BASED = allocato via puntatore
01 FunzPtr   USAGE FUNCTION-POINTER.

*> Ottenere l'indirizzo di una variabile
SET MioPtr TO ADDRESS OF IntTarget.
*> Usare il puntatore (deref)
SET ADDRESS OF IntTarget TO MioPtr.
DISPLAY IntTarget.
*> NULL check
IF MioPtr = NULL
    DISPLAY "Puntatore nullo"
END-IF.
*> Puntatore a funzione (callback)
SET FunzPtr TO ENTRY "MiaFunzione".
CALL FunzPtr USING Parametro.
C ARRAY, MATRICI, STRINGHE → COBOL
Array C → Tabella COBOL
// C
int32_t valori[10];
valori[0] = 42;
valori[9] = 100;
*> COBOL (subscript parte da 1!)
01 TabellaValori.
   02 Valore USAGE BINARY-LONG
           OCCURS 10 TIMES.
MOVE  42  TO Valore(1).
MOVE 100  TO Valore(10).
Matrice C → Tabella multidimensionale
// C
int32_t matrice[3][4];
matrice[1][2] = 7;
*> COBOL
01 Matrice.
   02 Riga OCCURS 3 TIMES INDEXED BY I.
       03 Cella USAGE BINARY-LONG
               OCCURS 4 TIMES INDEXED BY J.
SET I TO 2. SET J TO 3.
MOVE 7 TO Cella(I, J).
Stringhe C (null-terminated) ↔ COBOL
*> Stringa COBOL → C null-terminated
01 CobolStr  PIC X(30) VALUE "Ciao mondo".
01 CStr      PIC X(31).   *> +1 per \0
MOVE SPACES TO CStr.
MOVE CobolStr TO CStr.
*> Scrivere manualmente il terminatore null
MOVE X"00" TO CStr(FUNCTION LENGTH(
    FUNCTION TRIM(CobolStr)) + 1 : 1).

*> In alternativa con INSPECT
INSPECT CStr REPLACING TRAILING SPACES BY LOW-VALUES.

*> Stringa C → COBOL (pulizia null e padding)
INSPECT CStr REPLACING ALL X"00" BY SPACE.

*> Reference modification (substring)
*> variabile(start : lunghezza)
DISPLAY CobolStr(1 : 4).    *> "Ciao"
MOVE CobolStr(6 : 5) TO Parte2.  *> "mondo"
Le stringhe COBOL sono padded con spazi a destra; quelle C con '\0'. Quando si chiama una funzione C da COBOL, ricordarsi di aggiungere X"00" alla fine della stringa.
SCREEN SECTION — TUI INTERATTIVO

La SCREEN SECTION permette di costruire interfacce testuali interattive (TUI) tipo terminal. Richiede libreria curses/PDCurses. Compilare con cobc -x -lncurses prog.cob.

Attributi Schermo (Screen Clauses)
ClausolaEffetto
BLANK SCREENCancella tutto lo schermo
BLANK LINECancella la riga corrente
LINE nPosizione riga (1-based)
COLUMN nPosizione colonna (1-based)
LINE PLUS nRiga relativa (+n dalla corrente)
COLUMN PLUS nColonna relativa
VALUE "testo"Testo fisso sullo schermo
FROM variabileOutput: legge da variabile working-storage
TO variabileInput: scrive in variabile working-storage
USING variabileInput+Output (FROM+TO insieme)
PIC X(n)Formato campo input
FOREGROUND-COLOR nColore testo (0-7: nero,rosso,verde,giallo,blu,magenta,ciano,bianco)
BACKGROUND-COLOR nColore sfondo
HIGHLIGHTTesto evidenziato/grassetto
LOWLIGHTTesto dimmerato
REVERSE-VIDEOInversione colori
UNDERLINESottolineato
BLINKLampeggiante
BELLSegnale acustico
SECUREInput nascosto (password)
REQUIREDCampo obbligatorio
FULLDeve riempire tutto il campo
AUTOAvanza automaticamente al campo successivo
NO ECHONon mostra l'input digitato
ERASE EOLCancella fino a fine riga
ERASE EOSCancella fino a fine schermo
SCROLL DOWNScorrimento verso il basso
SIZE nDimensione campo (alternativa a PIC)
UPPERConverte input in maiuscolo
LOWERConverte input in minuscolo
Costanti colori
NumColoreNumColore
0Nero (BLACK)4Rosso (RED)
1Blu (BLUE)5Magenta (MAGENTA)
2Verde (GREEN)6Giallo (YELLOW)
3Ciano (CYAN)7Bianco (WHITE)
Esempio completo SCREEN SECTION
DATA DIVISION.
WORKING-STORAGE SECTION.
   01 WS-Nome     PIC X(30).
   01 WS-Eta      PIC 99.
   01 WS-Password PIC X(20).
   01 WS-Scelta   PIC 9.

SCREEN SECTION.
01 SchermoPrincipale
   BACKGROUND-COLOR 1    *> sfondo blu
   FOREGROUND-COLOR 7.   *> testo bianco
   *> Sfondo e titolo
   02 BLANK SCREEN.
   *> Titolo centrato riga 1
   02 LINE 1 COLUMN 30
         VALUE "=== GESTIONE CLIENTI ==="
         FOREGROUND-COLOR 6     *> giallo
         HIGHLIGHT.
   *> Label
   02 LINE 4 COLUMN 5
         VALUE "Nome: "
         FOREGROUND-COLOR 7.
   *> Campo input
   02 LINE 4 COLUMN 12
         PIC X(30)
         USING WS-Nome
         FOREGROUND-COLOR 3     *> ciano
         BACKGROUND-COLOR 0     *> nero
         REQUIRED AUTO.
   *> Età
   02 LINE 5 COLUMN 5
         VALUE "Eta:  ".
   02 LINE 5 COLUMN 12
         PIC 99 USING WS-Eta
         FOREGROUND-COLOR 6
         AUTO.
   *> Password con oscuramento
   02 LINE 6 COLUMN 5
         VALUE "Pass: ".
   02 LINE 6 COLUMN 12
         PIC X(20) TO WS-Password
         SECURE
         FOREGROUND-COLOR 6.
   *> Riga separatore
   02 LINE 8 COLUMN 1
         PIC X(80)
         VALUE ALL "-"
         FOREGROUND-COLOR 5.
   *> Messaggio stato
   02 LINE 22 COLUMN 1
         VALUE "F1=Aiuto  F3=Esci  INVIO=Conferma"
         REVERSE-VIDEO.

*> Schermo di sola visualizzazione
01 SchermoOutput.
   02 BLANK SCREEN.
   02 LINE 5 COLUMN 10
         VALUE "Risultato: ".
   02 LINE 5 COLUMN 22
         PIC X(40) FROM WS-Nome
         HIGHLIGHT.

PROCEDURE DIVISION.
   *> Visualizza e gestisce input
   DISPLAY SchermoPrincipale.
   ACCEPT  SchermoPrincipale.
   *> Solo visualizzazione
   DISPLAY SchermoOutput.
   *> Posizionamento diretto (senza SCREEN SECTION)
   DISPLAY "Testo" AT LINE 10 COLUMN 5
       FOREGROUND-COLOR 2.
   *> ACCEPT con posizionamento
   ACCEPT WS-Scelta AT LINE 10 COLUMN 20.
SCREEN SECTION funziona con DISPLAY nomeschermo per visualizzare e ACCEPT nomeschermo per acquisire input. Le clausole FROM (solo output), TO (solo input), USING (input+output) determinano il flusso dati.
ACCEPT / DISPLAY AVANZATO
DISPLAY
DISPLAY "Testo".
DISPLAY Var1 " " Var2.
DISPLAY "Msg" WITH NO ADVANCING.
DISPLAY "Msg" UPON CONSOLE.
DISPLAY "Err" UPON STDERR.
*> Con posizionamento (curses)
DISPLAY "Testo"
    AT 0510    *> riga 05, col 10
    FOREGROUND-COLOR 2
    BACKGROUND-COLOR 0.
ACCEPT
ACCEPT Variabile.
ACCEPT Variabile FROM DATE.    *> YYMMDD
ACCEPT Variabile FROM DATE YYYYMMDD.
ACCEPT Variabile FROM TIME.    *> HHMMSScc
ACCEPT Variabile FROM DAY.     *> YYDDD
ACCEPT Variabile FROM DAY-OF-WEEK. *> 1=Lun
ACCEPT Variabile FROM COMMAND-LINE.
ACCEPT Variabile FROM ENVIRONMENT "HOME".
*> Con posizionamento
ACCEPT Variabile
    AT LINE 5 COLUMN 10.
COMPILARE CON cobc (GnuCOBOL)
Sintassi cobc
cobc [opzioni] file.cob [file2.cob ...] [-l libreria]
FlagEffetto
-xCompila in eseguibile autonomo
-mCompila in modulo (.so/.dll) dinamico
-o nomeSpecifica nome file output
-freeSource format free (senza vincoli di colonna)
-fixedSource format fixed (default)
-std=cobol2014Standard COBOL 2014
-std=ibmCompatibilità IBM mainframe
-std=mfCompatibilità Micro Focus
-fstatic-callForza tutte le CALL a essere statiche
-fdebugging-lineAbilita linee di debug (D in col.7)
-debugAbilita runtime checks complete
-gSimboli di debug (per gdb)
-O / -O2Ottimizzazione
-WallTutti i warning
-I dirDirectory per COPY (copybooks)
-L dirDirectory librerie
-l nomeLinka libreria
-vVerbose (mostra comandi eseguiti)
-save-tempsMantieni file intermedi (.c generato)
Programma singolo
# Compila ed esegui
cobc -x hello.cob
./hello

# Free format esplicito
cobc -x -free hello.cob

# Con output rinominato
cobc -x -o programma hello.cob

# Solo il C generato (debug compilazione)
cobc -C hello.cob
cat hello.c
PROGETTI MULTI-SORGENTE
Metodo 1: Compilazione insieme
# Tutto in un colpo (statico)
cobc -x main.cob GETSUM.cob UTILS.cob
Metodo 2: Moduli dinamici (.so)
# Compila i moduli come shared library
cobc -m GETSUM.cob         # → GETSUM.so
cobc -m UTILS.cob          # → UTILS.so
# Compila il main (le CALL verranno risolte a runtime)
cobc -x main.cob           # → main
./main                     # cerca GETSUM.so, UTILS.so in COB_LIBRARY_PATH
Metodo 3: Moduli statici (.o)
# Compila oggetti C
cobc -C GETSUM.cob         # genera GETSUM.c
gcc -c GETSUM.c -o GETSUM.o $(cob-config --cflags)
# Link finale
cobc -x -fstatic-call main.cob GETSUM.o
Variabili d'ambiente GnuCOBOL
VariabileScopo
COB_LIBRARY_PATHPercorsi per moduli .so a runtime
COB_COPY_DIRDirectory per COPY books
COB_CONFIG_DIRDirectory configurazione compilatore
COB_SCREEN_EXCEPTIONSAbilita gestione eccezioni schermo
COB_EXCEPTION_PROCEDUREProcedura gestore eccezioni
COPY books (include)
*> COPY include un file .cpy o .cob come testo
COPY STDDEF.          *> cerca STDDEF.cpy in COB_COPY_DIR
COPY "include/common.cpy" REPLACING
    ==PREFISSO== BY ==WS==.   *> sostituzione testo
COMPILAZIONE CON LIBRERIE ESTERNE
Librerie C statiche (.a)
# Compilare con libmath, libncurses, ecc.
cobc -x prog.cob -lm -lncurses
# Libreria custom statica
cobc -x prog.cob -L/usr/local/lib -lmialib
Librerie C dinamiche (.so / .dll)
# Linking con libreria dinamica
cobc -x prog.cob -ldl        # libdl per dlopen
export LD_LIBRARY_PATH=/path/to/libs:$LD_LIBRARY_PATH
./prog
Wrapper per librerie C esterne
*> Per usare funzioni da libm (math.h)
01 Angolo  USAGE FLOAT-LONG.
01 Coseno  USAGE FLOAT-LONG.
MOVE 1.5707963 TO Angolo.
CALL "cos"   USING BY VALUE Angolo   RETURNING Coseno.
CALL "sin"   USING BY VALUE Angolo   RETURNING Risultato.
CALL "sqrt"  USING BY VALUE Valore   RETURNING Radice.
CALL "pow"   USING BY VALUE Base Esp RETURNING Pot.
CALL "fabs"  USING BY VALUE Num      RETURNING Abs.
CALL "floor" USING BY VALUE Num      RETURNING Floor.
CALL "ceil"  USING BY VALUE Num      RETURNING Ceil.

*> Compilare: cobc -x prog.cob -lm
Makefile di esempio
COBC    = cobc
COBFLAGS= -x -free -Wall -debug
LIBS    = -lncurses -lm

all: mioprog

mioprog: main.cob modulo1.cob modulo2.cob
    $(COBC) $(COBFLAGS) -o $@ $^ $(LIBS)

modulo1.so: modulo1.cob
    $(COBC) -m -free modulo1.cob

clean:
    rm -f mioprog *.so *.o *.c
GESTIONE ERRORI
FILE STATUS — Controllo errori I/O

Il metodo più comune: controllare il FILE STATUS dopo ogni operazione I/O.

FILE-CONTROL.
SELECT ClienteFile ASSIGN TO "clienti.dat"
    FILE STATUS IS WS-FS.

WORKING-STORAGE SECTION.
01 WS-FS  PIC XX.
   88 FS-OK     VALUE "00".
   88 FS-EOF    VALUE "10".
   88 FS-NOTFND VALUE "23".
   88 FS-DUPKEY VALUE "22".

OPEN INPUT ClienteFile.
IF NOT FS-OK
    DISPLAY "Errore apertura: " WS-FS
    STOP RUN
END-IF.
Tabella completa FILE STATUS
CodiceCategoriaSignificato
00SuccessoOperazione completata con successo
02SuccessoREAD riuscita, chiave duplicata presente (alternate key)
04SuccessoLunghezza record diversa da quella attesa
05SuccessoOPEN su file opzionale inesistente (creato)
10EOFFine file raggiunta (AT END)
14EOFREAD sequenziale: numero relativo troppo grande
21Errore chiaveChiave fuori sequenza (sequential write su indexed)
22Errore chiaveChiave duplicata su WRITE
23Errore chiaveRecord non trovato (READ/START/DELETE)
24Errore chiaveBoundary violation (disco pieno, record troppo grande)
30Errore permanenteErrore I/O generico permanente
34Errore permanenteBoundary violation (file sequenziale)
35Errore permanenteOPEN su file non esistente (non opzionale)
37Errore permanenteOPEN modo non supportato dal dispositivo
38Errore permanenteOPEN su file chiuso con LOCK
39Errore permanenteAttributi file conflittuali
41Errore logicoOPEN su file già aperto
42Errore logicoCLOSE su file non aperto
43Errore logicoREAD/REWRITE senza READ precedente (random/dynamic)
44Errore logicoREWRITE: dimensione record cambiata (sequenziale)
46Errore logicoREAD sequenziale fallita: nessun record valido corrente
47Errore logicoREAD su file non aperto in INPUT o I-O
48Errore logicoWRITE su file non aperto in OUTPUT, I-O o EXTEND
49Errore logicoDELETE/REWRITE su file non aperto in I-O
9xImpl. definedErrori specifici del compilatore/sistema operativo
DECLARATIVES — Gestione errori centralizzata

Le DECLARATIVES sono sezioni speciali nella PROCEDURE DIVISION che vengono invocate automaticamente dal runtime quando si verifica un errore I/O, una condizione di debug, o una label di report. Devono essere dichiarate prima di qualsiasi altro codice nella PROCEDURE DIVISION, racchiuse tra DECLARATIVES. e END DECLARATIVES.

Forme della clausola USE
Forma USETriggerScopo
USE AFTER STANDARD ERROR PROCEDURE ON file-nameErrore I/O su un file specificoGestione errori per singolo file
USE AFTER STANDARD ERROR PROCEDURE ON INPUTErrore I/O su qualsiasi file aperto in INPUTGestore generico per categoria di apertura
USE AFTER STANDARD ERROR PROCEDURE ON OUTPUTErrore I/O su qualsiasi file aperto in OUTPUTIdem per OUTPUT
USE AFTER STANDARD ERROR PROCEDURE ON I-OErrore I/O su qualsiasi file aperto in I-OIdem per I-O
USE AFTER STANDARD ERROR PROCEDURE ON EXTENDErrore I/O su qualsiasi file aperto in EXTENDIdem per EXTEND
USE FOR DEBUGGING ON procedure-nameIngresso nel paragrafo/sezione monitorataDebug (richiede WITH DEBUGGING MODE)
USE BEFORE REPORTING identifierPrima di stampare un gruppo nel Report WriterLogica personalizzata nella stampa report
Struttura ed esempio completo
PROCEDURE DIVISION.
DECLARATIVES.

*> Handler per errori su un file specifico
Errore-Clienti SECTION.
    USE AFTER STANDARD ERROR PROCEDURE ON ClienteFile.
Errore-Clienti-Para.
    DISPLAY "Errore I/O su ClienteFile: " WS-FS.
    EVALUATE WS-FS
        WHEN "35" DISPLAY "File non trovato"
        WHEN "30" DISPLAY "Errore I/O permanente"
        WHEN "41" DISPLAY "File gia' aperto"
        WHEN OTHER DISPLAY "Errore non previsto"
    END-EVALUATE.
    STOP RUN.

*> Handler generico per TUTTI i file in INPUT
Errore-Input SECTION.
    USE AFTER STANDARD ERROR PROCEDURE ON INPUT.
Errore-Input-Para.
    DISPLAY "Errore lettura generico: " WS-FS.

*> Handler per debug su un paragrafo (richiede DEBUGGING MODE)
Debug-Calcolo SECTION.
    USE FOR DEBUGGING ON CalcolaIVA.
Debug-Calcolo-Para.
    DISPLAY "[DEBUG] Entrato in CalcolaIVA"
    DISPLAY "  Riga:  " DEBUG-LINE
    DISPLAY "  Nome:  " DEBUG-NAME.

END DECLARATIVES.

*> ─── Dopo END DECLARATIVES: logica normale ───
Main-Logic SECTION.
Main-Para.
    OPEN INPUT ClienteFile.
    *> Se OPEN fallisce, il runtime chiama
    *> automaticamente Errore-Clienti SECTION
    PERFORM UNTIL EOF-Reached
        READ ClienteFile
            AT END SET EOF-Reached TO TRUE
        END-READ
    END-PERFORM.
    CLOSE ClienteFile.
    STOP RUN.
Regole e precedenze DECLARATIVES
RegolaDettaglio
Posizione obbligatoriaSubito dopo PROCEDURE DIVISION, prima di qualsiasi paragrafo o sezione non-declarativa
Ogni USE in una SECTIONOgni clausola USE deve essere in una SECTION dedicata con almeno un paragrafo
Precedenza: specifico > genericoSe esiste sia un handler per ON ClienteFile che per ON INPUT, viene invocato quello specifico per il file
Flusso dopo l'handlerSe l'handler non esegue STOP RUN o GOBACK, il controllo ritorna all'istruzione successiva a quella che ha causato l'errore
No PERFORM verso declarativeNon si puo' chiamare una sezione DECLARATIVE con PERFORM dal codice normale
Coesistenza con INVALID KEYSe il verbo ha INVALID KEY, la DECLARATIVE non viene invocata per quell'operazione (INVALID KEY ha precedenza)
Relazione con FILE STATUS: Le DECLARATIVES vengono invocate dopo che il FILE STATUS e' stato aggiornato. All'interno dell'handler, il FILE STATUS contiene gia' il codice dell'errore e puo' essere ispezionato. Se sia FILE STATUS che DECLARATIVES sono attivi, vengono eseguiti entrambi; se anche INVALID KEY e' presente, INVALID KEY ha priorita' e la DECLARATIVE non scatta.
INVALID KEY / AT END — Gestione inline
READ ClienteFile
    AT END
        SET EOF-Flag TO TRUE
    NOT AT END
        PERFORM ProcessaRecord
END-READ.

WRITE ClienteData
    INVALID KEY
        DISPLAY "Chiave duplicata o errore"
    NOT INVALID KEY
        ADD 1 TO RecordCount
END-WRITE.
ON SIZE ERROR — Overflow aritmetico
ADD A TO B
    ON SIZE ERROR
        DISPLAY "Overflow aritmetico!"
        MOVE ZEROS TO B
    NOT ON SIZE ERROR
        CONTINUE
END-ADD.

COMPUTE Result = X / Y
    ON SIZE ERROR
        DISPLAY "Divisione per zero o overflow"
END-COMPUTE.
ON EXCEPTION — Errore su CALL
CALL "MODULO-ESTERNO" USING Dati
    ON EXCEPTION
        DISPLAY "Modulo non trovato o errore nel caricamento"
    NOT ON EXCEPTION
        DISPLAY "Chiamata riuscita"
END-CALL.
RAISE / RESUME (COBOL 2014+)
*> Exception handling moderno (supporto limitato nei compilatori)

*> RAISE: solleva un'eccezione
RAISE EXCEPTION EC-DATA-INCOMPATIBLE.

*> >>TURN: attiva il monitoraggio di eccezioni specifiche
>>TURN EC-SIZE CHECKING ON
>>TURN EC-BOUND CHECKING ON
>>TURN EC-DATA CHECKING ON

*> RESUME: dentro un handler, riprende l'esecuzione
*> RESUME AT NEXT STATEMENT — riprende dal punto successivo
*>                           all'istruzione che ha causato l'eccezione

*> Esempio: handler con RESUME
DECLARATIVES.
Err-Bound SECTION.
    USE AFTER EXCEPTION CONDITION EC-BOUND.
Err-Bound-Para.
    DISPLAY "Indice fuori range".
    RESUME AT NEXT STATEMENT.  *> continua dopo l'errore
END DECLARATIVES.
Categorie eccezioni standard (EC-*)
CategoriaTrigger
EC-ALLTutte le eccezioni (catch-all)
EC-ARGUMENTArgomento non valido a funzione intrinseca
EC-BOUNDSubscript o indice fuori range
EC-DATADato incompatibile o corrotto
EC-FLOWFlusso irregolare (fall-through di paragrafo, ecc.)
EC-I-OErrore I/O generico
EC-OVERFLOWOverflow stringa (STRING/UNSTRING)
EC-PROGRAMErrore nel caricamento programma (CALL)
EC-RANGEValore fuori range
EC-SIZEOverflow aritmetico o divisione per zero
EC-SORT-MERGEErrore durante SORT o MERGE
EC-STORAGEMemoria insufficiente (ALLOCATE)
La gestione errori in COBOL è frammentata: FILE STATUS + INVALID KEY per I/O, ON SIZE ERROR per aritmetica, ON EXCEPTION per CALL. Non esiste un meccanismo try/catch unificato come in linguaggi moderni (RAISE/RESUME è poco supportato).
PROGRAMMI ANNIDATI (NESTED PROGRAMS)

Da COBOL-85 è possibile annidare programmi all'interno di un programma contenitore. Ogni programma annidato ha il proprio scope di dati. Alternativa a CALL con moduli separati.

IDENTIFICATION DIVISION.
PROGRAM-ID. ProgrammaEsterno.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 Risultato   PIC 9(6) VALUE ZEROS.
01 Dato1       PIC 9(3) VALUE 100.
01 Dato2       PIC 9(3) VALUE 200.

PROCEDURE DIVISION.
    CALL "Calcolatore" USING Dato1 Dato2 Risultato.
    DISPLAY "Risultato: " Risultato.
    STOP RUN.

    *> ─── Programma annidato ───
    IDENTIFICATION DIVISION.
    PROGRAM-ID. Calcolatore.
    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 Temporaneo PIC 9(6).
    LINKAGE SECTION.
    01 L-A        PIC 9(3).
    01 L-B        PIC 9(3).
    01 L-Result   PIC 9(6).

    PROCEDURE DIVISION USING L-A L-B L-Result.
        COMPUTE L-Result = L-A + L-B.
    END PROGRAM Calcolatore.

END PROGRAM ProgrammaEsterno.
COMMON e INITIAL
*> COMMON: il programma annidato è visibile anche dai fratelli
PROGRAM-ID. Utilita IS COMMON.

*> INITIAL: il programma viene reinizializzato ad ogni CALL
PROGRAM-ID. Contatore IS INITIAL.
*> Tutte le variabili tornano al VALUE originale ad ogni invocazione

*> GLOBAL: variabili visibili nei programmi annidati
01 SharedData PIC X(50) IS GLOBAL.
*> I programmi figli possono accedere a SharedData senza LINKAGE
I programmi annidati evitano i problemi del linking dinamico (CALL con .so) e sono compilati insieme in un unico binario. Utili per subroutine interne senza esporre moduli separati.
FUNZIONI INTRINSECHE (FUNCTION)
Matematiche
FunzioneDescrizione
ABS(n)Valore assoluto
SQRT(n)Radice quadrata
INTEGER(n)Troncamento a intero
INTEGER-PART(n)Parte intera
FRACTION-PART(n)Parte decimale
MOD(n,d)Modulo
REM(n,d)Resto
MAX(a,b,...)Massimo
MIN(a,b,...)Minimo
MEAN(a,b,...)Media
MEDIAN(a,b,...)Mediana
SUM(a,b,...)Somma
VARIANCE(a,...)Varianza
STANDARD-DEVIATIONDev. standard
EXP(n)e^n
LOG(n)log naturale
LOG10(n)log base 10
SIN(n)Seno (radianti)
COS(n)Coseno
TAN(n)Tangente
ASIN(n)Arcoseno
ACOS(n)Arcocoseno
ATAN(n)Arcotangente
PIValore π
RANDOM([seed])Numero casuale 0-1
Data e Ora
FunzioneDescrizione
CURRENT-DATEData+ora corrente (21 char)
WHEN-COMPILEDData compilazione (21 char)
DATE-OF-INTEGER(n)Numero giorno → YYYYMMDD
INTEGER-OF-DATE(d)YYYYMMDD → numero giorno
DAY-OF-INTEGER(n)Numero giorno → YYYYDDD
INTEGER-OF-DAY(d)YYYYDDD → numero giorno
Stringhe
FunzioneDescrizione
LENGTH(s)Lunghezza stringa
UPPER-CASE(s)Maiuscolo
LOWER-CASE(s)Minuscolo
REVERSE(s)Inversa
TRIM(s)Rimuove spazi
NUMVAL(s)Stringa → numero
CHAR(n)Numero → char
ORD(c)Char → numero
ORD-MAXMax ordinale del set
ORD-MINMin ordinale del set
*> Uso FUNCTION
COMPUTE R = FUNCTION SQRT(9).
MOVE FUNCTION CURRENT-DATE TO DataOra.
DISPLAY FUNCTION UPPER-CASE(Nome).
COMPUTE X = FUNCTION PI.
*> FUNCTION come statement di USE
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
REPOSITORY.
    FUNCTION ALL INTRINSIC.
*> → poi si può usare senza "FUNCTION":
COMPUTE X = SQRT(2).
SPECIAL REGISTERS

I registri speciali sono variabili predefinite dal compilatore, disponibili senza dichiarazione in WORKING-STORAGE.

RegistroTipoDescrizione
RETURN-CODEPIC S9(4) COMPCodice di ritorno del programma o dell'ultimo CALL. Visibile al sistema operativo dopo STOP RUN.
SORT-STATUSPIC 9(4)Stato dell'ultima operazione SORT/MERGE. 0 = successo.
SORT-RETURNPIC S9(4) COMPAlias di SORT-STATUS in alcuni dialetti (IBM).
LINAGE-COUNTERPIC 9(n)Numero riga corrente in un file con clausola LINAGE. Gestito automaticamente da WRITE ADVANCING.
PAGE-COUNTERPIC 9(n)Contatore pagine nel Report Writer. Incrementato automaticamente.
LINE-COUNTERPIC 9(n)Contatore righe nel Report Writer.
NUMBER-OF-CALL-PARAMETERSPIC 9(2) COMPNumero di parametri passati all'ultima CALL (GnuCOBOL).
COB-CRT-STATUSPIC 9(4)Stato dell'ultimo ACCEPT da schermo. Tasti funzione: 1001=F1, 1002=F2, ecc. (GnuCOBOL).
WHEN-COMPILEDPIC X(21)Data/ora di compilazione.
*> RETURN-CODE: comunicazione tra programmi
CALL "VALIDATORE" USING Dati.
IF RETURN-CODE NOT = 0
    DISPLAY "Validazione fallita, codice: " RETURN-CODE
END-IF.

*> Impostare il return code per il chiamante
MOVE 0 TO RETURN-CODE.
STOP RUN.       *> il sistema vede exit code 0

*> GOBACK al posto di STOP RUN (nei sottoprogrammi)
MOVE 4 TO RETURN-CODE.
GOBACK.          *> ritorna al chiamante, RC=4

*> SORT-STATUS: controllo dopo SORT
SORT WorkFile ON ASCENDING KEY WKey
    USING InFile GIVING OutFile.
IF SORT-STATUS NOT = 0
    DISPLAY "Errore SORT: " SORT-STATUS
END-IF.

*> NUMBER-OF-CALL-PARAMETERS (GnuCOBOL)
*> Utile per parametri opzionali in sottoprogrammi
IF NUMBER-OF-CALL-PARAMETERS < 3
    MOVE SPACES TO LParam3   *> default se non passato
END-IF.

*> COB-CRT-STATUS: rilevare tasti funzione (GnuCOBOL)
*> Richiede: SET ENVIRONMENT "COB_SCREEN_EXCEPTIONS" TO "Y"
ACCEPT WS-Campo AT LINE 5 COLUMN 10.
EVALUATE COB-CRT-STATUS
    WHEN 0    CONTINUE          *> Enter
    WHEN 1001 PERFORM Aiuto     *> F1
    WHEN 1003 STOP RUN         *> F3 = Esci
    WHEN 2005 CONTINUE         *> PgDn
END-EVALUATE.
REFERENCE MODIFICATION — SUBSTRING

Permette di accedere a una porzione di un campo alfanumerico senza definire sottocampi. Sintassi: campo(posizione : lunghezza). Posizione parte da 1.

01 Frase PIC X(20) VALUE "HELLO WORLD".

*> Estrazione substring
DISPLAY Frase(1 : 5).        *> "HELLO"
DISPLAY Frase(7 : 5).        *> "WORLD"

*> Lunghezza opzionale: dal punto fino alla fine
DISPLAY Frase(7 :).           *> "WORLD         " (fino alla fine)

*> Modifica in-place
MOVE "CIAO" TO Frase(1 : 4). *> "CIAOO WORLD"

*> Posizione e lunghezza possono essere variabili
01 Pos  PIC 99 VALUE 3.
01 Len  PIC 99 VALUE 4.
DISPLAY Frase(Pos : Len).     *> 4 caratteri dalla posizione 3

*> Su campi di gruppo (trattati come alfanumerici)
01 DataGrezza PIC X(8) VALUE "20241225".
DISPLAY DataGrezza(1 : 4).   *> "2024" (anno)
DISPLAY DataGrezza(5 : 2).   *> "12"   (mese)
DISPLAY DataGrezza(7 : 2).   *> "25"   (giorno)

*> Con FUNCTION LENGTH per calcoli dinamici
MOVE "!" TO Frase(FUNCTION LENGTH(Frase) : 1).
*> Mette "!" nell'ultima posizione
Se posizione + lunghezza - 1 supera la dimensione del campo, il risultato è undefined behavior. Con -debug in GnuCOBOL si ottiene un errore runtime. Verificare sempre i limiti quando posizione/lunghezza sono variabili.
OCCURS DYNAMIC / ALLOCATE / FREE (COBOL 2014+)

COBOL 2014 introduce la gestione dinamica della memoria, finora assente nel linguaggio. Queste feature hanno supporto limitato nei compilatori.

OCCURS DYNAMIC — Array a dimensione variabile runtime
*> Tabella con dimensione allocata a runtime
01 TabDinamica.
   02 NumElementi PIC 9(5).
   02 Elemento PIC X(20)
       OCCURS DYNAMIC
       CAPACITY IN NumElementi.

*> Ridimensiona a runtime
ALLOCATE 100 CHARACTERS RETURNING Elemento.
*> oppure
ALLOCATE Elemento.
ALLOCATE / FREE — Gestione memoria esplicita
*> ALLOCATE: alloca memoria dinamica
01 Ptr USAGE POINTER.
01 Buffer PIC X(1024) BASED.

*> Alloca e associa a una variabile BASED
ALLOCATE Buffer RETURNING Ptr.

*> Alloca N caratteri generici
ALLOCATE 4096 CHARACTERS RETURNING Ptr
    ON EXCEPTION
        DISPLAY "Memoria insufficiente".

*> FREE: rilascia memoria allocata
FREE Ptr.
*> Dopo FREE, Ptr è NULL e Buffer non è più accessibile
Confronto allocazione statica vs dinamica
FeatureOCCURS n TIMESOCCURS ... TO ... DEPENDING ONOCCURS DYNAMIC
DimensioneFissa a compile timeVariabile, con range fissoVariabile, senza limite fisso
MemoriaAllocata staticamenteAllocata per il maxAllocata a runtime
StandardCOBOL-68+COBOL-85+COBOL 2014+
Supporto GnuCOBOLPienoPienoParziale (3.x+)
ALLOCATE/FREE e OCCURS DYNAMIC sono feature recenti con supporto ancora incompleto. GnuCOBOL 3.x ha supporto sperimentale. IBM Enterprise COBOL V6.3+ supporta OCCURS DYNAMIC. Testare sempre la compatibilità del compilatore.
COMPILAZIONE CONDIZIONALE

Da COBOL 2002/2014: direttive del preprocessore per includere/escludere codice a compile time. Sintassi: >> in colonna 7+ (free) o colonna 7 (fixed).

*> Definizione costante di compilazione
>>DEFINE VERSIONE AS 2
>>DEFINE DEBUG-MODE AS 1
>>DEFINE PIATTAFORMA AS "LINUX"

*> Condizionale semplice
>>IF DEBUG-MODE = 1
    DISPLAY "[DEBUG] Valore: " Variabile.
>>END-IF

*> IF / ELSE
>>IF PIATTAFORMA = "LINUX"
    CALL "system" USING BY REFERENCE CmdLinux.
>>ELSE
    CALL "system" USING BY REFERENCE CmdWindows.
>>END-IF

*> Verifica se definito
>>IF VERSIONE IS DEFINED
    DISPLAY "Versione attiva".
>>END-IF

>>IF MODULO-EXTRA IS NOT DEFINED
    DISPLAY "Modulo extra non disponibile".
>>END-IF

*> Definizione da riga di comando (GnuCOBOL)
cobc -x -D DEBUG-MODE=1 -D PIATTAFORMA="LINUX" prog.cob

*> Attivazione/disattivazione in cascata
>>DEFINE LIVELLO AS 3
>>IF LIVELLO >= 2
    PERFORM LogDettagliato.
>>END-IF
>>IF LIVELLO >= 3
    PERFORM LogVerbose.
>>END-IF
DirettivaEffetto
>>DEFINE nome AS valoreDefinisce una costante di compilazione
>>IF condizioneInizio blocco condizionale
>>ELSERamo alternativo
>>END-IFFine blocco condizionale
>>SET nome AS valoreRidefinisce una costante (se già definita)
>>TURN EC-BOUND CHECKING ONAttiva/disattiva controlli runtime specifici
>>SOURCE FORMAT FREE/FIXEDCambia formato sorgente
In GnuCOBOL, le direttive >>DEFINE possono anche essere passate da riga di comando con -D NOME=VALORE. Utile per build differenziati (debug/produzione, piattaforme diverse).
COPY & REPLACING — PATTERN AVANZATI

La clausola COPY include testo da un copybook (.cpy) esterno. REPLACING permette sostituzioni testuali al momento dell'inclusione, fondamentale per il riuso delle strutture dati.

Sintassi completa
*> COPY base
COPY nome-copybook.
COPY "path/to/copybook.cpy".

*> COPY con REPLACING (pseudo-text delimiters ==...==)
COPY RECDEF REPLACING
    ==:PREFIX:== BY ==WS-CLI==
    ==:SIZE:==   BY ==100==.

*> REPLACING multipli sullo stesso COPY
COPY SQLTAB REPLACING
    ==:TABLE:==  BY ==CLIENTI==
    ==:KEY:==    BY ==ID-CLIENTE==
    ==:REC:==    BY ==REC-CLI==.
Esempio: copybook parametrizzato
*> ─── File: RECDEF.cpy ───
01 :PREFIX:-Record.
   02 :PREFIX:-ID    PIC 9(5).
   02 :PREFIX:-Nome  PIC X(30).
   02 :PREFIX:-Stato PIC X.

*> ─── Nel programma: istanzia due volte ───
COPY RECDEF REPLACING ==:PREFIX:== BY ==WS-CLI==.
*> Genera: 01 WS-CLI-Record. 02 WS-CLI-ID PIC 9(5). ...

COPY RECDEF REPLACING ==:PREFIX:== BY ==WS-FOR==.
*> Genera: 01 WS-FOR-Record. 02 WS-FOR-ID PIC 9(5). ...
REPLACE — Sostituzione globale nel sorgente
*> REPLACE opera su TUTTO il sorgente (non solo COPY)
REPLACE ==VECCHIO-NOME== BY ==NUOVO-NOME==.
*> Da qui in poi, ogni occorrenza viene sostituita

*> Disattivare REPLACE
REPLACE OFF.
ClausolaScopeUso tipico
COPY ... REPLACINGSolo il testo incluso dal COPYParametrizzare copybook (prefissi, nomi tabella)
REPLACETutto il sorgente fino a REPLACE OFFRefactoring, rename globale temporaneo
Best practice: Usare convenzione con prefisso (es. :PREFIX:) nei copybook per rendere chiaro dove avvengono le sostituzioni. I copybook sono cercati in: directory corrente, COB_COPY_DIR, directory specificate con -I in cobc.
FILE LOCKING — ACCESSO CONCORRENTE

Il file locking controlla l'accesso concorrente quando più programmi o thread accedono allo stesso file. Definito nella clausola SELECT e nei verbi I/O.

LOCK MODE nella SELECT
SELECT ClienteFile ASSIGN TO "clienti.dat"
    ORGANIZATION IS INDEXED
    ACCESS MODE IS DYNAMIC
    LOCK MODE IS MANUAL         *> lock esplicito per record
    WITH LOCK ON MULTIPLE RECORDS
    FILE STATUS IS WS-FS.
Modalità di lock
LOCK MODEComportamentoUso tipico
AUTOMATICLock acquisito automaticamente su READ, rilasciato su READ successiva o UNLOCKProgrammi semplici con accesso sequenziale
MANUALLock acquisito solo con READ WITH LOCK, rilasciato con UNLOCK o CLOSETransazioni che richiedono controllo preciso
EXCLUSIVEL'intero file è bloccato all'OPEN; nessun altro può accederviBatch esclusivi, riorganizzazione file
Verbi con lock
*> READ con lock esplicito (LOCK MODE MANUAL)
READ ClienteFile
    WITH LOCK                   *> blocca il record
    KEY IS IDCliente
    INVALID KEY DISPLAY "Non trovato"
END-READ.

*> READ senza lock (solo lettura)
READ ClienteFile
    WITH NO LOCK                *> non blocca
    KEY IS IDCliente
END-READ.

*> UNLOCK: rilascia i lock sul file
UNLOCK ClienteFile RECORDS.   *> rilascia tutti i record lockati
UNLOCK ClienteFile RECORD.    *> rilascia solo il record corrente

*> OPEN con sharing (chi altro può aprire il file)
OPEN I-O ClienteFile WITH LOCK. *> lock esclusivo
OPEN INPUT ClienteFile
    SHARING WITH ALL OTHER.      *> condiviso in lettura
OPEN I-O ClienteFile
    SHARING WITH NO OTHER.       *> esclusivo
OPEN I-O ClienteFile
    SHARING WITH READ ONLY.      *> altri possono solo leggere
FILE STATUS e lock: Un tentativo di READ WITH LOCK su un record già bloccato da un altro processo restituisce FILE STATUS "68" (record locked). Gestire sempre questo caso per evitare deadlock. In GnuCOBOL il locking è basato su fcntl() (POSIX).
JSON GENERATE / PARSE (COBOL 2014+)

Da COBOL 2014, con supporto in GnuCOBOL 3.x+, IBM Enterprise COBOL V6.2+ e Micro Focus.

JSON GENERATE — da record COBOL a stringa JSON
WORKING-STORAGE SECTION.
01 Prodotto.
   02 ProdID     PIC 9(5) VALUE 12345.
   02 ProdNome   PIC X(20) VALUE "Widget".
   02 ProdPrezzo PIC 9(5)V99 VALUE 49.99.
   02 ProdAttivo PIC 9 VALUE 1.
01 JsonOutput PIC X(500).
01 JsonLen    PIC 9(5).

*> Generazione base
JSON GENERATE JsonOutput FROM Prodotto
    COUNT IN JsonLen
    ON EXCEPTION
        DISPLAY "Errore JSON GENERATE"
    NOT ON EXCEPTION
        DISPLAY JsonOutput(1 : JsonLen)
END-JSON.
*> Output: {"ProdID":12345,"ProdNome":"Widget","ProdPrezzo":49.99,"ProdAttivo":1}

*> Con NAME (rinomina chiavi JSON)
JSON GENERATE JsonOutput FROM Prodotto
    COUNT IN JsonLen
    NAME OF ProdID IS "id"
             ProdNome IS "name"
             ProdPrezzo IS "price"
             ProdAttivo IS "active"
END-JSON.
*> Output: {"id":12345,"name":"Widget","price":49.99,"active":1}

*> Con SUPPRESS (escludi campi)
JSON GENERATE JsonOutput FROM Prodotto
    COUNT IN JsonLen
    SUPPRESS ProdAttivo
END-JSON.
JSON PARSE — da stringa JSON a record COBOL
01 JsonInput  PIC X(500)
    VALUE '{"id":99,"name":"Gadget","price":19.99}'.
01 ParsedProd.
   02 ProdID     PIC 9(5).
   02 ProdNome   PIC X(20).
   02 ProdPrezzo PIC 9(5)V99.

JSON PARSE JsonInput INTO ParsedProd
    NAME OF ProdID IS "id"
             ProdNome IS "name"
             ProdPrezzo IS "price"
    ON EXCEPTION
        DISPLAY "Errore parsing JSON"
    NOT ON EXCEPTION
        DISPLAY "ID: " ProdID
        DISPLAY "Nome: " ProdNome
        DISPLAY "Prezzo: " ProdPrezzo
END-JSON.
XML GENERATE / PARSE
*> Sintassi analoga a JSON
01 XmlOutput PIC X(1000).
01 XmlLen    PIC 9(5).

XML GENERATE XmlOutput FROM Prodotto
    COUNT IN XmlLen
    WITH ATTRIBUTES       *> oppure WITH ENCODING (UTF-8, ecc.)
    ON EXCEPTION
        DISPLAY "Errore XML"
END-XML.

XML PARSE XmlInput
    PROCESSING PROCEDURE IS HandleXml
END-XML.
*> HandleXml riceve eventi SAX: XML-EVENT, XML-TEXT, XML-NTEXT
Il supporto JSON/XML varia molto tra compilatori. GnuCOBOL 3.2+ supporta JSON GENERATE. JSON PARSE e XML sono meglio supportati in IBM Enterprise COBOL V6.2+ e Micro Focus.
EMBEDDED SQL (DB2 / ESQL)

COBOL su mainframe IBM usa Embedded SQL per interagire con DB2. Le istruzioni SQL sono racchiuse tra EXEC SQL e END-EXEC. Il precompilatore DB2 le converte in chiamate al database prima della compilazione COBOL.

Struttura base
WORKING-STORAGE SECTION.

*> SQLCA: area di comunicazione SQL (obbligatoria)
EXEC SQL INCLUDE SQLCA END-EXEC.

*> Host variables: variabili COBOL usate nelle query
01 WS-ID      PIC 9(5).
01 WS-Nome    PIC X(30).
01 WS-Saldo   PIC S9(9)V99 COMP-3.
01 WS-Ind     PIC S9(4) COMP.  *> indicator variable (null check)
Operazioni CRUD
*> SELECT singola riga (INTO host variables)
EXEC SQL
    SELECT NOME, SALDO
    INTO :WS-Nome, :WS-Saldo:WS-Ind
    FROM CLIENTI
    WHERE ID = :WS-ID
END-EXEC.
*> :WS-Ind = -1 se SALDO è NULL

*> INSERT
EXEC SQL
    INSERT INTO CLIENTI (ID, NOME, SALDO)
    VALUES (:WS-ID, :WS-Nome, :WS-Saldo)
END-EXEC.

*> UPDATE
EXEC SQL
    UPDATE CLIENTI SET SALDO = :WS-Saldo
    WHERE ID = :WS-ID
END-EXEC.

*> DELETE
EXEC SQL
    DELETE FROM CLIENTI
    WHERE ID = :WS-ID
END-EXEC.
Cursori (result set multi-riga)
*> Dichiarazione cursore
EXEC SQL
    DECLARE CUR-CLIENTI CURSOR FOR
    SELECT ID, NOME, SALDO FROM CLIENTI
    WHERE SALDO > :WS-MinSaldo
    ORDER BY NOME
END-EXEC.

*> Apertura, lettura, chiusura
EXEC SQL OPEN CUR-CLIENTI END-EXEC.

PERFORM UNTIL SQLCODE NOT = 0
    EXEC SQL
        FETCH CUR-CLIENTI
        INTO :WS-ID, :WS-Nome, :WS-Saldo
    END-EXEC
    IF SQLCODE = 0
        DISPLAY WS-ID " " WS-Nome " " WS-Saldo
    END-IF
END-PERFORM.

EXEC SQL CLOSE CUR-CLIENTI END-EXEC.
SQLCODE — Codici di ritorno
SQLCODESignificato
0Successo
+100Nessuna riga trovata (SELECT) o fine cursore (FETCH)
-803Violazione chiave duplicata (INSERT)
-805Package/plan non trovato
-811SELECT INTO restituisce più di una riga
-911Deadlock o timeout
-904Risorsa non disponibile
< 0Errore generico (consultare SQLERRMC per dettagli)
*> Gestione errori tipica
EVALUATE SQLCODE
    WHEN 0    CONTINUE
    WHEN 100  DISPLAY "Nessun dato trovato"
    WHEN -803 DISPLAY "Chiave duplicata"
    WHEN OTHER
        DISPLAY "Errore SQL: " SQLCODE
        DISPLAY "Messaggio: " SQLERRMC
END-EVALUATE.
Compilazione: Il sorgente con Embedded SQL va prima processato dal precompilatore DB2 (DSNHPC su z/OS) che genera COBOL puro con CALL al runtime DB2. In ambiente GnuCOBOL si può usare ESQL/OC (Open COBOL ESQL) o OCESQL per interfacciarsi con PostgreSQL/MySQL.
CICS — PROGRAMMAZIONE TRANSAZIONALE

CICS (Customer Information Control System) è il transaction monitor IBM per applicazioni online su mainframe. I programmi COBOL/CICS gestiscono transazioni interattive (schermate 3270, servizi web) tramite comandi EXEC CICS.

Struttura di un programma CICS
*> Differenze rispetto a COBOL batch:
*> - NON usare ACCEPT, DISPLAY, OPEN, READ, WRITE, CLOSE
*> - NON usare STOP RUN (usare EXEC CICS RETURN)
*> - I/O solo tramite EXEC CICS (SEND MAP, RECEIVE MAP, READ FILE, ecc.)

IDENTIFICATION DIVISION.
PROGRAM-ID. CICSPGM.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-Resp    PIC S9(8) COMP.
01 WS-Resp2   PIC S9(8) COMP.
01 WS-Data    PIC X(100).

PROCEDURE DIVISION.
    EXEC CICS HANDLE CONDITION
        ERROR(Errore-Para)
    END-EXEC.
    PERFORM Logica-Main.
    EXEC CICS RETURN END-EXEC.

Errore-Para.
    EXEC CICS SEND TEXT FROM("Errore!")
        LENGTH(7) ERASE END-EXEC.
    EXEC CICS RETURN END-EXEC.
Comandi CICS principali
CategoriaComandoDescrizione
TerminaleSEND MAP / RECEIVE MAPInvia/ricevi schermata BMS (3270)
TerminaleSEND TEXTInvia testo libero al terminale
FileREAD FILE / WRITE FILELeggi/scrivi record VSAM
FileREWRITE FILE / DELETE FILEAggiorna/cancella record
FileSTARTBR / READNEXT / ENDBRBrowse sequenziale su file VSAM
QueueWRITEQ TS / READQ TSTemporary Storage queue (dati di sessione)
QueueWRITEQ TD / READQ TDTransient Data queue (log, trigger)
ProgrammaLINK / XCTLChiama sottoprogramma / trasferimento controllo
ProgrammaRETURNRitorna al CICS o al chiamante
SyncSYNCPOINTCommit delle modifiche
SyncSYNCPOINT ROLLBACKRollback delle modifiche
Esempio: lettura file VSAM
EXEC CICS READ FILE('CUSTFILE')
    INTO(WS-Data)
    RIDFLD(WS-Key)
    LENGTH(WS-Len)
    RESP(WS-Resp)
    RESP2(WS-Resp2)
END-EXEC.

EVALUATE WS-Resp
    WHEN DFHRESP(NORMAL)   PERFORM Processa
    WHEN DFHRESP(NOTFND)   DISPLAY "Non trovato"
    WHEN DFHRESP(DISABLED) DISPLAY "File disabilitato"
    WHEN OTHER
        DISPLAY "Errore CICS RESP=" WS-Resp
END-EVALUATE.
CICS è esclusivo dell'ambiente mainframe IBM (z/OS). Non esiste in GnuCOBOL. Per sviluppo/test locale si usano emulatori CICS come Micro Focus Enterprise Server o IBM CICS TX. Il precompilatore CICS (DFHECP1$) traduce i comandi EXEC CICS in CALL al runtime.
JCL — INTEGRAZIONE CON JOB CONTROL LANGUAGE

Su mainframe IBM (z/OS), i programmi COBOL batch vengono eseguiti tramite JCL (Job Control Language). Il JCL definisce l'ambiente di esecuzione: file fisici, librerie, parametri e risorse.

JCL base per un programma COBOL
//MYJOB   JOB (ACCT),'NOME',CLASS=A,MSGCLASS=X
//*
//STEP1   EXEC PGM=MIOPROG
//STEPLIB  DD  DSN=MY.LOAD.LIB,DISP=SHR
//*
// Associazione file logici COBOL → dataset fisici z/OS
//CLIENTI  DD  DSN=PROD.CLIENTI.VSAM,DISP=SHR
//REPORT   DD  DSN=PROD.REPORT.OUTPUT,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(5,2)),
//             DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSOUT   DD  SYSOUT=*
//SYSPRINT DD  SYSOUT=*
Relazione SELECT ↔ DD
COBOL (SELECT)JCL (DD)Collegamento
SELECT ClienteFile ASSIGN TO CLIENTI//CLIENTI DD DSN=...Il nome dopo ASSIGN TO corrisponde al DD name nel JCL
SELECT ReportFile ASSIGN TO REPORT//REPORT DD DSN=...Idem
DISPLAY ... UPON SYSOUT//SYSOUT DD SYSOUT=*Output standard (console/spool)
JCL per compilazione + esecuzione
//COMPILE EXEC PGM=IGYCRCTL,PARM='RENT,OPT(2)'
//SYSIN    DD  DSN=MY.SOURCE.LIB(MIOPROG),DISP=SHR
//SYSLIB   DD  DSN=MY.COPYBOOK.LIB,DISP=SHR
//SYSLIN   DD  DSN=&&OBJ,DISP=(NEW,PASS),SPACE=(CYL,1)
//SYSPRINT DD  SYSOUT=*
//*
//LKED    EXEC PGM=IEWL,PARM='RENT,LIST,MAP'
//SYSLIN   DD  DSN=&&OBJ,DISP=(OLD,DELETE)
//SYSLMOD  DD  DSN=MY.LOAD.LIB(MIOPROG),DISP=SHR
//SYSPRINT DD  SYSOUT=*
//*
//RUN     EXEC PGM=MIOPROG
//STEPLIB  DD  DSN=MY.LOAD.LIB,DISP=SHR
RETURN-CODE e condizioni JCL
*> Nel programma COBOL: imposta il codice di ritorno
MOVE 0 TO RETURN-CODE.   *> successo
MOVE 4 TO RETURN-CODE.   *> warning
MOVE 8 TO RETURN-CODE.   *> errore
MOVE 16 TO RETURN-CODE.  *> errore grave
// Nel JCL: condiziona i passi successivi
//STEP2   EXEC PGM=PROG2,COND=(4,LT,STEP1)
//* Esegue STEP2 solo se RETURN-CODE di STEP1 >= 4
//*
// Con IF/THEN/ELSE (JCL moderno):
//  IF (STEP1.RC = 0) THEN
//STEP2   EXEC PGM=PROG2
//  ELSE
//STEPERR EXEC PGM=ERRPGM
//  ENDIF
JCL è specifico di z/OS. In ambiente GnuCOBOL su Linux/macOS, i file sono associati tramite il path nell'ASSIGN TO o variabili d'ambiente. Non esiste JCL, ma si usano script shell per orchestrare i batch. La convenzione RETURN-CODE rimane valida: in GnuCOBOL il valore diventa l'exit code del processo.
DEBUGGING
Debugging Lines (Fixed Format)
*> 'D' in colonna 7 = riga di debug (compilata solo con -fdebugging-line)
      *  Codice normale:
       MOVE 42 TO Valore.
      D DISPLAY "DEBUG: Valore = " Valore.

*> Attivazione:
cobc -x -fdebugging-line prog.cob
*> Senza il flag, le righe D sono ignorate dal compilatore.
Runtime checks con GnuCOBOL
FlagControllo
-debugAbilita tutti i controlli runtime (bounds, subscript, overflow)
-gGenera simboli di debug per gdb/lldb
-ftraceTraccia l'esecuzione di ogni statement (molto verboso)
-ftraceallTraccia tutto incluse le sezioni DECLARATIVES
-fsource-locationMostra file e riga nei messaggi di errore runtime
-fstack-checkControlla overflow dello stack
# Compilazione per debugging completo
cobc -x -debug -g -fsource-location -Wall prog.cob

# Esecuzione con tracing a runtime
export COB_SET_TRACE=Y
./prog
# Stampa ogni statement eseguito: Source: 'prog.cob', Line: 42, ...

# Redirect trace su file
export COB_TRACE_FILE=debug.log
./prog

# Debug con gdb
cobc -x -g prog.cob
gdb ./prog
# In gdb: break cob_stop_run per fermarsi prima dell'uscita
# In gdb: print b_42 per vedere variabile dichiarata alla riga 42
USE FOR DEBUGGING (COBOL-85)
*> Richiede SOURCE-COMPUTER con WITH DEBUGGING MODE
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SOURCE-COMPUTER. X86 WITH DEBUGGING MODE.

PROCEDURE DIVISION.
DECLARATIVES.
Debug-Handler SECTION.
    USE FOR DEBUGGING ON CalcolaIVA.
Debug-Para.
    DISPLAY "Entrato in CalcolaIVA"
    DISPLAY "DEBUG-LINE: " DEBUG-LINE
    DISPLAY "DEBUG-NAME: " DEBUG-NAME.
END DECLARATIVES.

*> DEBUG-ITEM contiene:
*>   DEBUG-LINE    - numero riga sorgente
*>   DEBUG-NAME    - nome del paragrafo/variabile monitorata
*>   DEBUG-CONTENTS - contenuto (valore precedente, se variabile)
Tecniche di debug pratiche
*> Pattern: trace manuale con timestamp
01 WS-Debug-Ts PIC X(21).
MOVE FUNCTION CURRENT-DATE TO WS-Debug-Ts.
DISPLAY "[" WS-Debug-Ts "] CalcolaIVA: Imp="
    Imponibile " IVA=" TotaleIVA.

*> Pattern: dump di un record
DISPLAY "=== DUMP Cliente ===".
DISPLAY "  ID: ["   IDCliente   "]".
DISPLAY "  Nome: [" NomeCliente "]".
DISPLAY "  HEX: " FUNCTION ORD(IDCliente(1:1)).

*> Pattern: validazione invarianti
IF Totale < 0
    DISPLAY "ASSERT FAIL: Totale negativo = " Totale
    UPON STDERR
    STOP RUN
END-IF.
Debug interattivo con GDB — Guida dettagliata
# 1. Compilare con simboli di debug
cobc -x -g -debug -fsource-location prog.cob

# 2. Lanciare gdb
gdb ./prog

# 3. Comandi gdb utili per COBOL
Comando gdbEffetto
break cob_stop_runBreakpoint prima dell'uscita dal programma
break prog.c:42Breakpoint alla riga 42 del C generato (corrisponde a una riga COBOL)
print b_WS_ContaStampa la variabile COBOL WS-Conta (prefisso b_, trattini → underscore)
print b_1Stampa la variabile COBOL definita a livello 01 (se non ha nome: usa il numero di riga)
display b_WS_FSMostra automaticamente WS-FS dopo ogni step
info localsElenca tutte le variabili locali (include le variabili COBOL convertite)
nextEsegue la prossima riga C (può corrispondere a più statement COBOL)
stepEntra nelle funzioni chiamate (es. CALL)
continueContinua fino al prossimo breakpoint
backtraceMostra lo stack di chiamate (utile dopo un crash)
x/20cb b_RecordADump esadecimale di 20 byte del record (utile per ispezionare campi packed)
# Sessione di esempio
$ gdb ./prog
(gdb) break cob_stop_run
(gdb) run
(gdb) print b_WS_Totale
$1 = "00012345"
(gdb) print b_WS_FS
$2 = "00"
(gdb) x/10cb b_WS_Record
0x...:  0x4d 0x61 0x72 0x69 0x6f 0x20 0x20 0x20 ...
(gdb) backtrace
#0  cob_stop_run (status=0) at libcob/common.c:...
#1  prog_ () at prog.c:142
Naming convention GnuCOBOL → C: I nomi delle variabili COBOL sono convertiti in nomi C con prefisso b_ e trattini sostituiti da underscore. Es: WS-Contab_WS_Conta, IDClienteb_IDCliente. Per trovare il nome esatto: cobc -x -g prog.cob poi grep "WS.Conta" prog.c.