Programmare su IBM i: sorgenti, ILE, RPG e SQL Capitolo 4 di 9

CL: il linguaggio che tiene insieme il resto

Rivista il Verificata su IBM i 7.5

Accedi per salvare

Il CLControl 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.

Torna all'indice della guida

← Torna al blog

Commenti

Nessun commento ancora. Sii il primo a commentare!

Devi avere un account per commentare. Accedi · Registrati