Aller au contenu

Instruction RPG full free · IBM i (AS/400) · Procédures, sous-programmes et erreurs

CALLP

Appeler une procédure ou un programme

Appelle une procédure ou un programme décrit par un prototype, en ignorant la valeur éventuellement renvoyée, et permet de capter l'erreur d'appel avec l'extension E.

Syntaxe

CALLP{(E)} nom-procedure({parametre1 : parametre2 ...});
nom-procedure({parametre1 : parametre2 ...});
nom-procedure
Le nom du prototype (dcl-pr) ou de la procédure à appeler. Un prototype avec extpgm appelle un programme, par exemple QCMDEXC.
parametres
Les valeurs passées, séparées par :. Un paramètre déclaré const accepte une expression ou une constante. Sans const, il est passé par référence : la procédure modifie la zone de l'appelant.
(E)
Extension d'erreur. Si l'appel échoue, le programme ne s'arrête pas : %ERROR passe à *ON et %STATUS reçoit le code de l'erreur.
Effet
L'appel lui-même ne positionne rien. Avec l'extension (E), %ERROR vaut *ON si l'appel a échoué et %STATUS contient le code (211 pour un programme introuvable, 202 pour un appel terminé en erreur, dans les exemples). Si la procédure renvoie une valeur, CALLP la jette.

À quoi ça sert

En full free, le mot CALLP est facultatif : ajouter(encours : 50.25); fait exactement la même chose que callp ajouter(encours : 50.25);. On l'écrit surtout pour deux raisons : rendre l'intention explicite quand la valeur renvoyée est volontairement ignorée, et pouvoir ajouter l'extension (E).

En RPG IV en colonnes, c'était le code opération CALLP. Dès qu'on veut utiliser la valeur renvoyée par la procédure, on l'appelle dans une expression, sans CALLP.

Exemple 1 : Programme, procédure et paramètre par référence

**free
// CALLP : appeler une procedure ou un programme, avec ou sans le mot CALLP.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr qcmdexc extpgm('QCMDEXC');
  cmd char(200) const;
  lng packed(15:5) const;
end-pr;

dcl-pr majuscule char(30);
  texte char(30) const;
end-pr;

dcl-pr ajouter ind;
  total packed(9:2);
  montant packed(9:2) const;
end-pr;

dcl-s encours packed(9:2) inz(1250.50);
dcl-s nom char(30) inz('Dupont SA');
dcl-s ok ind;

// Appel d'un programme : CALLP ou appel direct, c'est equivalent.
callp qcmdexc('CHKOBJ OBJ(JOBIRPG/CLIENT) OBJTYPE(*FILE)' : 200);
snd-msg 'Fichier CLIENT trouve';

// Appel d'une procedure qui renvoie une valeur : on peut l'ignorer avec CALLP.
callp majuscule(nom);
snd-msg 'Nom apres CALLP : [' + %trim(nom) + ']';

// Dans une expression, la valeur renvoyee est utilisee.
snd-msg 'Nom en majuscules : [' + %trim(majuscule(nom)) + ']';

// Le parametre sans CONST est passe par reference : l'appelant voit la modification.
ok = ajouter(encours : 100.00);
snd-msg 'Encours apres ajout : ' + %char(encours) + ', retour ' + %char(ok);
ajouter(encours : 50.25);
snd-msg 'Encours apres ajout sans CALLP : ' + %char(encours);

*inlr = *on;

dcl-proc majuscule;
  dcl-pi *n char(30);
    texte char(30) const;
  end-pi;
  return %upper(texte);
end-proc;

dcl-proc ajouter;
  dcl-pi *n ind;
    total packed(9:2);
    montant packed(9:2) const;
  end-pi;
  total += montant;
  return *on;
end-proc;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Fichier CLIENT trouve
Nom apres CALLP : [Dupont SA]
Nom en majuscules : [DUPONT SA]
Encours apres ajout : 1350.50, retour 1
Encours apres ajout sans CALLP : 1400.75

Le premier appel de QCMDEXC vérifie que le fichier existe. majuscule renvoie une valeur : avec callp elle est ignorée et nom reste inchangé ; dans l'expression suivante, elle est utilisée. Enfin total est passé par référence : encours passe de 1250.50 à 1350.50 puis à 1400.75, avec ou sans callp.

Exemple 2 : Capter l'échec d'un appel avec (E)

**free
// CALLP(E) : l'extension E capte l'erreur d'appel, sans elle le programme s'arrete.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr appeler extpgm('B4INEXIST');
  numcli packed(5:0) const;
end-pr;

dcl-pr qcmdexc extpgm('QCMDEXC');
  cmd char(200) const;
  lng packed(15:5) const;
end-pr;

// Programme absent, avec (E) : %ERROR est positionne, le programme continue.
callp(e) appeler(100);
if %error;
  snd-msg 'Appel de B4INEXIST en erreur, statut ' + %char(%status);
endif;

// Commande valide, avec (E) : pas d'erreur.
callp(e) qcmdexc('CHKOBJ OBJ(JOBIRPG/CLIENT) OBJTYPE(*FILE)' : 200);
snd-msg 'CHKOBJ CLIENT : erreur = ' + %char(%error);

// Commande qui echoue, avec (E) : on lit le statut sans planter.
callp(e) qcmdexc('CHKOBJ OBJ(JOBIRPG/PASCLIENT) OBJTYPE(*FILE)' : 200);
snd-msg 'CHKOBJ PASCLIENT : erreur = ' + %char(%error) + ', statut ' + %char(%status);

// Sans (E), la meme erreur arrete le programme.
callp qcmdexc('CHKOBJ OBJ(JOBIRPG/PASCLIENT) OBJTYPE(*FILE)' : 200);
snd-msg 'Cette ligne n est jamais atteinte';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Appel de B4INEXIST en erreur, statut 211
CHKOBJ CLIENT : erreur = 0
CHKOBJ PASCLIENT : erreur = 1, statut 202
Erreur : RNQ0202 - (C G D F) Appel à *LIBL/QCMDEXC terminé en erreur.

L'appel d'un programme qui n'existe pas donne le statut 211, une commande qui échoue le statut 202. La dernière ligne appelle la même commande sans (E) : l'erreur n'est plus captée et le programme s'arrête avec l'erreur d'exécution RNQ0202 ; le message qui suit n'est jamais affiché.

Le piège

Sans (E), une erreur d'appel arrête le programme. Le deuxième exemple se termine par RNQ0202 - Appel à *LIBL/QCMDEXC terminé en erreur : %ERROR n'a de sens qu'avec l'extension. Avec CALLP(E), testez %ERROR tout de suite après l'appel, avant qu'une autre opération ne le réinitialise.

Un paramètre sans const est modifiable par la procédure appelée : c'est pratique pour renvoyer un résultat, dangereux si on ne s'y attend pas.