Aller au contenu

Instruction RPG full free · IBM i (AS/400) · Déclarations

DCL-PI

Déclarer l'interface d'une procédure

Décrit, à l'intérieur d'une procédure, ses paramètres et le type de la valeur qu'elle retourne ; elle doit correspondre au prototype.

Syntaxe

dcl-pi nom | *n [type de retour];
  paramètre type(longueur) [const | value] [options(*nopass : *omit)];
end-pi;
dcl-pi *n packed(9:2); montant packed(9:2) const; end-pi;
nom | *n
Le nom de la procédure, ou *n pour reprendre celui de dcl-proc (la forme habituelle).
type de retour
Le type de la valeur renvoyée par return. Absent si la procédure ne renvoie rien.
paramètres
Les paramètres reçus, avec les mêmes mots-clés que dans le prototype : const, value, options(*nopass : *omit).
Effet
Aucun indicateur ni %FOUND. La déclaration crée les paramètres comme des variables de la procédure. %parms donne le nombre de paramètres réellement passés par l'appelant.

À quoi ça sert

dcl-pi est le pendant, dans la procédure, du dcl-pr de l'appelant. Le prototype dit comment on appelle ; l'interface dit ce qu'on reçoit. Les deux décrivent les mêmes paramètres, avec les mêmes types et les mêmes mots-clés.

Pour un paramètre facultatif, options(*nopass) permet à l'appelant de ne pas le passer, ce qui évite d'écrire plusieurs procédures presque identiques. %parms permet alors de savoir ce qui a été fourni. En RPG IV en colonnes, c'était la spécification D avec le code PI.

Exemple 1 : Paramètres facultatifs et %PARMS

**free
// DCL-PI : l'interface de la procedure; OPTIONS(*NOPASS) rend un parametre facultatif.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr libelle varchar(60);
  nom   char(20) const;
  ville char(15) const options(*nopass);
  solde packed(9:2) const options(*nopass);
end-pr;

snd-msg libelle('Dupont SA');
snd-msg libelle('Dupont SA' : 'Montpellier');
snd-msg libelle('Dupont SA' : 'Montpellier' : 1250.50);

*inlr = *on;

dcl-proc libelle;
  dcl-pi *n varchar(60);
    nom   char(20) const;
    ville char(15) const options(*nopass);
    solde packed(9:2) const options(*nopass);
  end-pi;
  dcl-s texte varchar(60);

  texte = %trim(nom);
  if %parms >= 2;
    texte += ' a ' + %trim(ville);
  endif;
  if %parms >= 3;
    texte += ', solde ' + %char(solde);
  endif;
  texte += ' (' + %char(%parms) + ' parametre(s))';
  return texte;
end-proc;

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

Dupont SA (1 parametre(s))
Dupont SA a Montpellier (2 parametre(s))
Dupont SA a Montpellier, solde 1250.50 (3 parametre(s))

Avec un, deux ou trois arguments, le même texte s'allonge selon ce qui est fourni. %parms dit combien de paramètres ont été passés : on ne lit ville que s'il y en a au moins deux, et solde qu'à partir de trois.

Exemple 2 : Lire un paramètre non passé

**free
// DCL-PI : un parametre facultatif non transmis ne doit pas etre lu sans verification.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr remise packed(9:2);
  montant packed(9:2) const;
  taux    packed(5:2) const options(*nopass);
end-pr;

snd-msg 'Avec taux : ' + %char(remise(1000 : 10));
snd-msg 'Sans taux : ' + %char(remise(1000));

*inlr = *on;

dcl-proc remise;
  dcl-pi *n packed(9:2);
    montant packed(9:2) const;
    taux    packed(5:2) const options(*nopass);
  end-pi;
  return montant * taux / 100;
end-proc;

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

Avec taux : 100.00
Sans taux : 100.00

La procédure remise lit taux sans vérifier s'il a été passé. L'appel avec le taux donne bien 100,00 ; l'appel sans taux ne donne pas d'erreur non plus, mais une valeur au hasard : ici 100,00, comme si le taux valait 10. Le résultat est faux.

Exemple 3 : Tester %PARMS et utiliser *OMIT

**free
// DCL-PI : la meme procedure, protegee par %PARMS, et OPTIONS(*OMIT) pour sauter un parametre.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-pr remise packed(9:2);
  montant packed(9:2) const;
  taux    packed(5:2) const options(*nopass : *omit);
end-pr;

snd-msg 'Avec taux : ' + %char(remise(1000 : 10));
snd-msg 'Sans taux : ' + %char(remise(1000));
snd-msg 'Omis      : ' + %char(remise(1000 : *omit));

*inlr = *on;

dcl-proc remise;
  dcl-pi *n packed(9:2);
    montant packed(9:2) const;
    taux    packed(5:2) const options(*nopass : *omit);
  end-pi;
  dcl-s tauxEff packed(5:2) inz(5);

  if %parms >= 2 and %addr(taux) <> *null;
    tauxEff = taux;
  endif;
  return montant * tauxEff / 100;
end-proc;

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

Avec taux : 100.00
Sans taux : 50.00
Omis      : 50.00

La même procédure, protégée : si le taux manque (ou est omis avec *omit), on utilise 5 %. %addr(taux) <> *null détecte un paramètre omis. Les trois appels donnent 100, 50 et 50.

Le piège

Un paramètre *nopass non passé n'est pas une erreur, c'est une valeur au hasard. Dans l'exemple 2, remise(1000) lit un taux qui n'existe pas et renvoie 100,00 : la valeur est celle qui traîne en mémoire, aucun message d'erreur. Testez toujours %parms (exemple 3) avant de lire un paramètre facultatif. Pour un paramètre sauté avec *omit, testez %addr(paramètre) <> *null.