Il CL — Control Language — è il linguaggio in cui sono scritti i comandi del sistema, ed è anche un linguaggio di programmazione vero, con variabili, condizioni, cicli e gestione degli errori.
Nella pratica è quello che tiene insieme tutto il resto: prepara l'ambiente, chiama i programmi, gestisce le eccezioni, sottomette il lavoro. Se in un applicativo qualcosa gira di notte, quasi certamente c'è un CL che lo lancia.
Viene insegnato poco e scritto molto, ed è per questo che se ne trova tanto scritto male.
Un CL minimo
PGM PARM(&AZIENDA)
DCL VAR(&AZIENDA) TYPE(*CHAR) LEN(3)
DCL VAR(&DATA) TYPE(*CHAR) LEN(8)
DCL VAR(&MSG) TYPE(*CHAR) LEN(132)
RTVSYSVAL SYSVAL(QDATE) RTNVAR(&DATA)
OVRDBF FILE(ORDINI) TOFILE(DATILIB/ORDINI&AZIENDA)
CALL PGM(PRODLIB/CHIUSURA) PARM(&AZIENDA)
MONMSG MSGID(CPF0000) EXEC(DO)
CHGVAR VAR(&MSG) VALUE('Chiusura fallita per azienda' *BCAT &AZIENDA)
SNDPGMMSG MSG(&MSG) TOMSGQ(QSYSOPR) MSGTYPE(*INFO)
DLTOVR FILE(ORDINI)
RETURN
ENDDO
DLTOVR FILE(ORDINI)
ENDPGM
Ci sono dentro quasi tutte le cose che un CL fa davvero: ricevere parametri, leggere lo stato del sistema, ridirigere un file, chiamare un programma, accorgersi che è andato male e dirlo a qualcuno.
MONMSG, che è il cuore di tutto
Un comando che fallisce manda un messaggio di eccezione. MONMSG è l'unico modo per
accorgersene: senza, il CL si ferma con un errore che, in batch, nessuno vede fino al
giorno dopo.
Si usa in due modi, e la differenza conta:
CALL PGM(PRODLIB/CHIUSURA)
MONMSG MSGID(CPF0000) EXEC(GOTO CMDLBL(ERRORE))
Messo subito dopo un comando, vale per quel comando soltanto.
PGM
MONMSG MSGID(CPF0000 MCH0000) EXEC(GOTO CMDLBL(ERRORE))
...
Messo all'inizio del programma, prima di qualunque altro comando, vale per tutti: è la rete di sicurezza generale.
Avvertenza
MONMSG MSGID(CPF0000) cattura qualunque messaggio della famiglia CPF, e
il modo in cui viene usato più spesso — MONMSG MSGID(CPF0000) da solo, senza EXEC —
significa "ignora ogni errore e vai avanti". A volte è ciò che si vuole, per esempio dopo
un DLTF su un file che potrebbe non esistere. Molto più spesso è un modo per nascondere
i guasti: il programma continua su dati che non ci sono, e l'errore compare tre passi più
avanti, dove non ha più senso.
Un MONMSG senza EXEC andrebbe scritto solo sul singolo comando di cui si è deciso che
l'errore è accettabile, mai su tutto il programma.
Le variabili
Cominciano con &, hanno un tipo dichiarato e non c'è conversione implicita fra tipi.
DCL VAR(&CONTATORE) TYPE(*DEC) LEN(5 0) VALUE(0)
DCL VAR(&NOME) TYPE(*CHAR) LEN(10)
DCL VAR(&TROVATO) TYPE(*LGL) VALUE('0')
CHGVAR VAR(&CONTATORE) VALUE(&CONTATORE + 1)
CHGVAR VAR(&NOME) VALUE('CLIENTE' *BCAT &CODICE)
*CAT concatena, *BCAT concatena inserendo uno spazio, *TCAT toglie prima gli spazi in
coda. Sono tre operatori diversi e sbagliarli produce nomi con spazi in mezzo, che è una
classe intera di errori "l'oggetto non esiste" su oggetti che esistono.
Leggere lo stato del sistema
I comandi che cominciano con RTV restituiscono un'informazione in una variabile invece di
mostrarla a schermo. Sono quelli che rendono un CL capace di adattarsi:
RTVJOBA JOB(&NOMEJOB) USER(&UTENTE) NBR(&NUMERO) CURLIB(&LIBCORR)
RTVSYSVAL SYSVAL(QDATE) RTNVAR(&DATA)
RTVOBJD OBJ(PRODLIB/ORDINI) OBJTYPE(*FILE) RTNLIB(&LIBTROVATA)
Consiglio
RTVOBJD è anche il modo pulito per sapere se un oggetto esiste: si
esegue, e si monitora CPF9801. È più leggibile della scorciatoia che si vede spesso —
un CHKOBJ seguito da un MONMSG muto — e soprattutto dice quale errore è successo,
invece di trattare allo stesso modo "non esiste" e "non hai i diritti".
Leggere un file
Il CL può leggere un file, ma un record alla volta e in sola lettura:
DCLF FILE(PRODLIB/PARAMETRI)
LEGGI:
RCVF
MONMSG MSGID(CPF0864) EXEC(GOTO CMDLBL(FINE))
...
GOTO CMDLBL(LEGGI)
FINE:
CPF0864 è la fine del file, e va monitorata sempre: è il modo in cui il ciclo si chiude.
Non è un linguaggio per elaborare dati, e usarlo per farlo è una scelta che si paga in prestazioni e in leggibilità. Per leggere un parametro di configurazione va benissimo; per scorrere un archivio, no.
OVRDBF, l'ignoto potente
Le sovrascritture di file sono uno degli strumenti più usati e meno spiegati:
OVRDBF FILE(ORDINI) TOFILE(COLLAUDO/ORDINI)
OVRDBF FILE(ORDINI) MBR(GENNAIO)
OVRDBF FILE(REPORT) SHARE(*YES)
Un programma compilato per leggere ORDINI legge quello che la sovrascrittura gli mette
davanti: un file in un'altra libreria, un altro membro, con altri parametri di apertura.
È il modo in cui lo stesso programma serve dodici mesi di archivio, o gira su collaudo
senza essere ricompilato.
Avvertenza
una sovrascrittura ha un ambito, che per impostazione predefinita è
il livello di chiamata in cui è stata fatta. Un OVRDBF in un CL che poi chiama un
programma funziona; lo stesso OVRDBF dimenticato senza DLTOVR, in un job interattivo
che continua a lavorare, resta attivo e fa leggere il file sbagliato a tutto quello che
viene dopo. Le sovrascritture si cancellano sempre, anche sulla strada dell'errore — ed è
il motivo per cui nell'esempio in cima al capitolo DLTOVR compare due volte.
Come si compila
CRTBNDCL PGM(PRODLIB/CHIUSURA) SRCFILE(PRODLIB/QCLSRC) SRCMBR(CHIUSURA)
CRTBNDCL produce un programma ILE, ed è la forma da usare oggi. CRTCLPGM produce un
programma del vecchio modello: si incontra sul codice storico e non c'è motivo di usarlo
per il codice nuovo.
Commenti
Nessun commento ancora. Sii il primo a commentare!
Devi avere un account per commentare. Accedi · Registrati