Instruction RPG full free · IBM i (AS/400) · Déclarations
DCL-PR
Déclarer un prototype
Décrit comment appeler une procédure ou un programme : son nom, ses paramètres, leur mode de passage et la valeur qu'il retourne, pour que le compilateur vérifie chaque appel.
Syntaxe
dcl-pr nom [type de retour] [extpgm('PGM')];
paramètre type(longueur) [const | value] [options(*nopass : *omit)];
end-pr;
dcl-pr calculerTtc packed(9:2); montantHt packed(9:2) const; end-pr;
type de retour- Le type de la valeur renvoyée, après le nom. Absent pour une procédure qui ne renvoie rien.
extpgm('PGM')- Le prototype représente un programme externe (
*PGM), appelé par son nom système. const- Paramètre passé par référence en lecture seule : l'appelé ne peut pas le modifier, l'appelant peut passer une valeur calculée ou un littéral.
value- Paramètre passé par valeur : une copie, que l'appelé peut modifier sans effet sur l'appelant.
options(*nopass : *omit)- Paramètre facultatif, ou qu'on peut sauter en passant
*omit. - Effet
- Aucun indicateur ni %FOUND. Le prototype ne s'exécute pas : il ne fait que décrire l'appel. C'est l'appel lui-même qui renvoie la valeur déclarée. Pour un programme externe appelé avec
extpgm, une erreur d'exécution du programme appelé remonte comme exception, quemonitorpeut intercepter (%status).
À quoi ça sert
Appeler une procédure ou un programme sans prototype, c'est faire confiance au développeur : le compilateur ne peut pas vérifier le nombre de paramètres, leur type, leur longueur. Le prototype rend l'appel sûr, et se lit comme un contrat.
Pour appeler un programme CL ou RPG existant, on décrit son interface avec extpgm et on l'appelle comme une fonction. C'est la forme moderne de l'ancien call / parm. En RPG IV en colonnes, un prototype s'écrivait en spécifications D avec le code PR.
Exemple 1 : Un prototype et sa procédure
**free
// DCL-PR : decrire une procedure pour pouvoir l'appeler, avec ses parametres et son retour.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-pr calculerTtc packed(9:2);
montantHt packed(9:2) const;
tauxTva packed(5:2) const;
end-pr;
dcl-s ttc packed(9:2);
ttc = calculerTtc(1250.50 : 20);
snd-msg 'TTC de 1250,50 a 20 % : ' + %char(ttc);
snd-msg 'TTC de 98000 a 5,5 % : ' + %char(calculerTtc(98000 : 5.5));
*inlr = *on;
dcl-proc calculerTtc;
dcl-pi *n packed(9:2);
montantHt packed(9:2) const;
tauxTva packed(5:2) const;
end-pi;
return montantHt * (1 + tauxTva / 100);
end-proc;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
TTC de 1250,50 a 20 % : 1500.60
TTC de 98000 a 5,5 % : 103390.00
Le prototype décrit calculerTtc : deux paramètres const et un montant en retour. Les appels passent des littéraux (1250.50 : 20) et l'appel peut se placer à l'intérieur d'une expression. La procédure suit la fin du programme principal (après *inlr = *on).
Exemple 2 : Par référence, par valeur ou const
**free
// DCL-PR : sans CONST ni VALUE, le parametre est passe par reference : l'appele modifie l'appelant.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-pr majorer;
prix packed(9:2);
end-pr;
dcl-pr majorerConst;
prix packed(9:2) const;
end-pr;
dcl-pr majorerValeur;
prix packed(9:2) value;
end-pr;
dcl-s tarif packed(9:2) inz(100);
majorer(tarif);
snd-msg 'Par reference : ' + %char(tarif);
tarif = 100;
majorerValeur(tarif);
snd-msg 'Par valeur : ' + %char(tarif);
tarif = 100;
majorerConst(tarif);
snd-msg 'Par CONST : ' + %char(tarif);
*inlr = *on;
dcl-proc majorer;
dcl-pi *n;
prix packed(9:2);
end-pi;
prix = prix * 1.10;
end-proc;
dcl-proc majorerValeur;
dcl-pi *n;
prix packed(9:2) value;
end-pi;
prix = prix * 1.10;
end-proc;
dcl-proc majorerConst;
dcl-pi *n;
prix packed(9:2) const;
end-pi;
snd-msg 'Dans l''appele CONST : ' + %char(prix * 1.10);
end-proc;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Par reference : 110.00
Par valeur : 100.00
Dans l'appele CONST : 110.0000
Par CONST : 100.00
Sans mot-clé, le paramètre est passé par référence : majorer(tarif) change la variable de l'appelant, 100 devient 110. Avec value, la procédure travaille sur une copie : tarif reste à 100. Avec const, la procédure peut lire la valeur (elle affiche 110) mais pas la modifier.
Exemple 3 : Appeler un programme système
**free
// DCL-PR avec EXTPGM : appeler un programme ou une commande du systeme.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-pr qcmdexc extpgm('QCMDEXC');
commande char(200) const;
longueur packed(15:5) const;
end-pr;
monitor;
qcmdexc('CHKOBJ OBJ(JOBIRPG/CLIENT) OBJTYPE(*FILE)' : 200);
snd-msg 'CLIENT existe';
qcmdexc('CHKOBJ OBJ(JOBIRPG/INCONNU) OBJTYPE(*FILE)' : 200);
snd-msg 'INCONNU existe';
on-error;
snd-msg 'Echec de la commande, code ' + %char(%status);
endmon;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
CLIENT existe
Echec de la commande, code 202
extpgm('QCMDEXC') décrit le programme IBM qui exécute une commande. Le CHKOBJ du fichier CLIENT réussit ; celui d'un fichier inconnu échoue, et on-error récupère le code d'erreur (%status vaut 202, appel de programme en erreur).
Le piège
Sans const ni value, l'appelé modifie votre variable. L'exemple 2 montre tarif passé de 100 à 110 par l'appel majorer(tarif), alors que l'appelant n'a rien demandé. Pour une procédure qui ne doit que lire, mettez const : c'est plus sûr et c'est le seul mode qui accepte aussi un littéral ou un calcul.
Passer un littéral à un paramètre sans const est d'ailleurs refusé à la compilation : majorer(100) donne l'erreur RNF7542 (le paramètre ne peut pas être transmis par référence).