Instruction RPG full free · IBM i (AS/400) · Procédures, sous-programmes et erreurs
MONITOR
Capter les erreurs d'un bloc
Surveille un groupe d'instructions et, si une erreur d'exécution se produit, saute au ON-ERROR dont le code correspond, puis reprend après ENDMON.
Syntaxe
MONITOR;
instructions
ON-ERROR code1 {: code2 ...};
traitement de l'erreur
ON-ERROR;
traitement des autres erreurs
ENDMON;
code- Un ou plusieurs codes d'état (par exemple
00102pour la division par zéro,00202pour un appel terminé en erreur), séparés par:. Le bloc ne s'exécute que pour ces codes. *PROGRAM- Mot-clé qui regroupe les erreurs de programme, dont celle de code 00102.
ON-ERROR sans code- Capte toutes les erreurs non traitées par un
ON-ERRORprécédent. - Effet
- À l'entrée dans un
ON-ERROR,%STATUScontient le code de l'erreur (102, 105, 202 dans les exemples). Les instructions duMONITORsituées après l'erreur ne sont pas exécutées ; l'exécution reprend aprèsENDMON.
À quoi ça sert
Avant MONITOR, on captait les erreurs instruction par instruction avec l'extension (E) ou les indicateurs d'erreur. MONITOR regroupe plusieurs instructions sous une seule gestion d'erreur : conversions, divisions, appels de procédures. Le traitement d'erreur est écrit une fois, à côté du code qu'il protège.
Le premier exemple intercepte une division par zéro (statut 102) et une conversion d'un texte non numérique (statut 105) ; le programme continue ensuite normalement. Le ON-ERROR sans code, placé en dernier, sert de filet de sécurité.
Exemple 1 : Division par zéro et conversion impossible
**free
// MONITOR : intercepter une erreur d'execution et continuer.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s montant packed(9:2) inz(1250.50);
dcl-s nbclient packed(3:0);
dcl-s moyenne packed(9:2);
dcl-s texte char(10) inz('12A4');
dcl-s valeur packed(7:0);
// Division par zero (code 00102)
monitor;
moyenne = montant / nbclient;
snd-msg 'Moyenne : ' + %char(moyenne);
on-error 00102;
snd-msg 'Division par zero, statut ' + %char(%status);
moyenne = 0;
endmon;
// Conversion impossible (code 00105)
monitor;
valeur = %dec(texte : 7 : 0);
snd-msg 'Valeur : ' + %char(valeur);
on-error 00105;
snd-msg 'Texte non numerique, statut ' + %char(%status);
on-error;
snd-msg 'Autre erreur, statut ' + %char(%status);
endmon;
snd-msg 'Le programme continue.';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Division par zero, statut 102
Texte non numerique, statut 105
Le programme continue.
Chaque erreur va vers le ON-ERROR de son code, et %STATUS permet de l'afficher. Après ENDMON, le programme continue.
Exemple 2 : Le code change quand l'erreur vient d'une procédure
**free
// MONITOR : une erreur remonte d'une procedure, mais seuls les codes listes sont captes.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s nb packed(3:0);
dcl-s resultat packed(9:2);
dcl-pr ratio packed(9:2);
total packed(9:2) const;
diviseur packed(3:0) const;
end-pr;
// Cas 1 : sans erreur, aucun ON-ERROR n'est execute.
nb = 4;
monitor;
resultat = ratio(1250.50 : nb);
snd-msg 'Cas 1 : ratio = ' + %char(resultat);
on-error;
snd-msg 'Cas 1 : erreur';
endmon;
// Cas 2 : division par zero directe, dans le groupe : statut 102.
nb = 0;
monitor;
resultat = 1250.50 / nb;
on-error 00102;
snd-msg 'Cas 2 : division directe, statut ' + %char(%status);
endmon;
// Cas 3 : la meme division dans une procedure remonte en statut 202.
monitor;
resultat = ratio(1250.50 : nb);
on-error 00202;
snd-msg 'Cas 3 : division dans la procedure, statut ' + %char(%status);
endmon;
// Cas 4 : on attend 00102, mais l'erreur arrive en 00202 : rien ne la capte.
monitor;
resultat = ratio(1250.50 : nb);
on-error 00102;
snd-msg 'Cas 4 : cette ligne n est jamais atteinte';
endmon;
snd-msg 'Fin du programme (jamais atteinte).';
*inlr = *on;
dcl-proc ratio;
dcl-pi *n packed(9:2);
total packed(9:2) const;
diviseur packed(3:0) const;
end-pi;
return total / diviseur;
end-proc;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Cas 1 : ratio = 312.62
Cas 2 : division directe, statut 102
Cas 3 : division dans la procedure, statut 202
Erreur : RNQ0202 - (C G D F) Appel à RATIO terminé en erreur.
Cas 2 : la division est faite dans le groupe, le statut est 102. Cas 3 : la même division est faite par la procédure ratio ; l'erreur remonte avec le statut 202 (appel terminé en erreur) et seul ON-ERROR 00202 la capte. Cas 4 : le groupe n'attend que 00102, l'erreur arrive en 00202, personne ne la capte et le programme s'arrête avec l'erreur RNQ0202.
Le piège
Le code de l'erreur dépend de l'endroit où elle se produit. Une division par zéro dans le groupe donne 102, mais la même division dans une procédure appelée arrive chez l'appelant sous le code 202, et un ON-ERROR 00102 ne la voit pas : le programme s'arrête (cas 4, RNQ0202). Si vous protégez un appel de procédure, ajoutez 00202 ou un ON-ERROR sans code.
Le compilateur empêche aussi le recouvrement : placer ON-ERROR 00102 après un ON-ERROR sans code (ou après *PROGRAM) est refusé avec RNF7583. Mettez toujours le cas général en dernier.