Aller au contenu
DCL-PR · DCL-PI · RPG IV colonné et full free

PR et PI en RPG, le prototype et l'interface de procédure

Le PR décrit un appel, le PI reçoit les paramètres. Trois exemples, chacun en RPG IV colonné et en full free : un programme qui remplace son *ENTRY PLIST par un PI, le programme qui l'appelle par son prototype, et des procédures internes. Tout a été compilé, exécuté et débogué sur un IBM i 7.5.

2formats : RPG IV colonné et full free
6programmes compilés et exécutés
6erreurs reproduites, avec leur message
0*ENTRY PLIST

En une phrase

Le prototype (PR) dit à l'appelant comment appeler un programme ou une procédure ; l'interface de procédure (PI) déclare, dans l'appelé, les paramètres qu'il reçoit ; et quand les deux sont dans le même source, le compilateur vérifie qu'ils correspondent.

PR et PI, c'est quoi

En RPG III, on appelle un programme par CALL suivi de PARM, et le programme appelé reçoit ses paramètres par *ENTRY PLIST. Rien ne vérifie que les deux listes concordent. Le RPG IV permet les appels prototypés : on déclare l'appel une fois, et le compilateur contrôle chaque appel.

PR : le prototypePI : l'interface de procédure
RôleDécrit un appel : qui appeler, avec quels paramètresDéclare les paramètres reçus (et la valeur rendue)
OùChez l'appelant (et, par /COPY, chez l'appelé)Dans l'appelé : programme ou procédure
RPG IV colonnéSpécification D, PR en 24-25Spécification D, PI en 24-25
Full freeDCL-PR … END-PRDCL-PI … END-PI
NomObligatoire ; le nom externe par EXTPGM (programme) ou EXTPROC (procédure)Facultatif (*N en full free) ; s'il est donné, celui de la procédure, ou du prototype pour le programme principal
RemplaceCALL et PARM*ENTRY PLIST et ses PARM
Le même prototype, chez l'appelant et chez l'appelé Le membre TVAPRF contient le prototype de TVAF. Il est copié par /COPY dans APPELF, qui appelle TVAF par ce prototype, et dans TVAF, où le compilateur le compare au PI. TVAPRFle prototype (PR) /COPY /COPY APPELFappelle par le PR TVAFPR comparé au PI appel (EXTPGM)
Le prototype dans un membre à part, copié dans l'appelant et dans l'appelé.

Où ça s'écrit en RPG IV colonné

Le PR et le PI sont des spécifications D. La ligne qui porte PR ou PI ouvre la définition ; les lignes suivantes, sans type de définition, sont les paramètres. Les procédures, elles, sont encadrées par deux spécifications P : B (début) et E (fin) en colonne 24.

ColonnesZoneContenu
6Type de spécificationD
7-21NomLe nom du prototype, de l'interface ou du paramètre (indenté d'un blanc par usage)
24-25Type de définitionPR, PI ; à blanc pour un paramètre
33-39LongueurCalée à droite, en 39
40Type de donnéesP condensé, S étendu, A caractère…
41-42DécimalesPour une zone numérique
44-80Mots-clésEXTPGM, CONST, VALUE, OPTIONS, VARYING…
SEU, examen du membre TVAPR4 : ligne de format D (Name, ETDs, From, To/L, IDc, Keywords) au-dessus du prototype TVA4 PR EXTPGM et de ses trois paramètres
Dans SEU, la commande ligne FD affiche la ligne de format D : Ds en 24-25, To/L jusqu'en 39, Keywords à partir de 44.

En full free, plus de colonnes : DCL-PR et DCL-PI s'écrivent n'importe où sur la ligne, les paramètres se déclarent comme des variables (packed(11:2)), et la définition se termine par END-PR ou END-PI.

Exemple 1 Le programme appelé

Un PI à la place de *ENTRY PLIST

Le programme TVA reçoit un montant hors taxes et un taux, et rend le montant TTC dans le troisième paramètre. Son prototype est dans un membre à part, que l'appelé copie lui aussi.

RPG IV colonné Le prototype TVAPR4 et le programme TVA4

     D* TVAPR4 : prototype du programme TVA4, copie (/COPY) dans
     D* le programme appelant ET dans TVA4 lui-meme.
     DTVA4             PR                  EXTPGM('TVA4')
     D MONTANTHT                     11P 2 CONST
     D TAUX                           5P 2 CONST
     D MONTANTTTC                    11P 2
     H DFTACTGRP(*NO) DECEDIT('0,')
     H* TVA4 : calcule un montant TTC. Le PI remplace *ENTRY PLIST.
      /COPY QRPGLESRC,TVAPR4
     DTVA4             PI
     D MONTANTHT                     11P 2 CONST
     D TAUX                           5P 2 CONST
     D MONTANTTTC                    11P 2
     C                   EVAL(H)   MONTANTTTC = MONTANTHT * (1 + TAUX / 100)
     C                   EVAL      *INLR = *ON
     C                   RETURN

Full free Le prototype TVAPRF et le programme TVAF

**FREE
// TVAPRF : prototype du programme TVAF, copie (/COPY) dans
// le programme appelant ET dans TVAF lui-meme.
dcl-pr tvaf extpgm('TVAF');
  montantHt packed(11:2) const;
  taux packed(5:2) const;
  montantTtc packed(11:2);
end-pr;
**FREE
// TVAF : calcule un montant TTC. Le PI remplace *ENTRY PLIST.
ctl-opt dftactgrp(*no) decedit('0,');
/copy QRPGLESRC,TVAPRF

dcl-pi tvaf;
  montantHt packed(11:2) const;
  taux packed(5:2) const;
  montantTtc packed(11:2);
end-pi;

eval(h) montantTtc = montantHt * (1 + taux / 100);
*inlr = *on;
return;
dcl-pr tvaf extpgm('TVAF');
EXTPGM fait du prototype celui d'un programme, appelé par un appel dynamique, comme un CALL. Sans EXTPGM ni EXTPROC, ce serait le prototype d'une procédure.
dcl-pi tvaf;
Le PI global est celui de la procédure principale, donc du programme. Quand un prototype existe, le PI doit porter le même nom, et le prototype doit le précéder dans le source : c'est le rôle du /copy placé avant.
montantHt packed(11:2) const;
Les paramètres d'un programme sont toujours transmis par référence ; CONST interdit au programme de les modifier. montantTtc, sans CONST, est le paramètre de retour.
*inlr = *on; return;
Le programme garde le cycle RPG : *INLR ferme le programme à la sortie.

Une compilation par programme, dans une bibliothèque qui est dans la liste des bibliothèques (le /COPY cherche QRPGLESRC par *LIBL) :

ADDLIBLE JOBIPRPI
CRTBNDRPG PGM(JOBIPRPI/TVA4) SRCFILE(JOBIPRPI/QRPGLESRC) DBGVIEW(*SOURCE)
CRTBNDRPG PGM(JOBIPRPI/TVAF) SRCFILE(JOBIPRPI/QRPGLESRC) DBGVIEW(*SOURCE)

Exemple 2 L'appelant

Appeler un programme par son prototype

Le programme APPEL copie le même prototype, puis appelle TVA trois fois : avec des littéraux, puis avec une expression.

RPG IV colonné APPEL4

     H DFTACTGRP(*NO) DECEDIT('0,')
     H* APPEL4 : appelle le programme TVA4 par son prototype.
      /COPY QRPGLESRC,TVAPR4
     DTTC              S             11P 2
     DPRIX             S              7P 2 INZ(12.50)
     DQTE              S              3P 0 INZ(3)
     DTEXTE            S             52A
     C                   CALLP     TVA4(100 : 20 : TTC)
     C                   EVAL      TEXTE = '100 HT a 20 % : ' + %CHAR(TTC)
     C     TEXTE         DSPLY
     C                   CALLP     TVA4(59.90 : 5.5 : TTC)
     C                   EVAL      TEXTE = '59,90 HT a 5,5 % : ' + %CHAR(TTC)
     C     TEXTE         DSPLY
     C* CONST : on peut passer une expression
     C                   CALLP     TVA4(PRIX * QTE : 20 : TTC)
     C                   EVAL      TEXTE = '3 x 12,50 a 20 % : ' + %CHAR(TTC)
     C     TEXTE         DSPLY
     C                   EVAL      *INLR = *ON

Full free APPELF

**FREE
// APPELF : appelle le programme TVAF par son prototype.
ctl-opt dftactgrp(*no) decedit('0,');
/copy QRPGLESRC,TVAPRF

dcl-s ttc packed(11:2);
dcl-s prix packed(7:2) inz(12.50);
dcl-s qte packed(3:0) inz(3);

tvaf(100 : 20 : ttc);
dsply ('100 HT a 20 % : ' + %char(ttc));
tvaf(59.90 : 5.5 : ttc);
dsply ('59,90 HT a 5,5 % : ' + %char(ttc));
// CONST : on peut passer une expression
tvaf(prix * qte : 20 : ttc);
dsply ('3 x 12,50 a 20 % : ' + %char(ttc));
*inlr = *on;
C CALLP TVA4(100 : 20 : TTC)
En colonné, l'appel prototypé passe par le code opération CALLP, les paramètres séparés par des deux-points. En full free, on écrit simplement tvaf(100 : 20 : ttc);.
tvaf(prix * qte : 20 : ttc);
Une expression en premier paramètre : c'est permis parce qu'il est CONST. Le compilateur convertit aussi 100, 59.90 ou 5.5 au format du paramètre.
decedit('0,')
La virgule décimale de %char. Les littéraux du source gardent le point : 59.90.
CALL QCMD
CALL APPEL4
CALL APPELF
Écran Entrée de commandes, messages détaillés : CALL APPEL4 puis CALL APPELF affichent chacun 100 HT a 20 % : 120,00, 59,90 HT a 5,5 % : 63,19 et 3 x 12,50 a 20 % : 45,00
Les deux versions donnent les mêmes résultats (F10 sur l'écran de QCMD pour voir les DSPLY).

Pourquoi le prototype dans un /COPY

Copié dans le programme appelé, le prototype est comparé au PI. Changeons le taux du PI de TVAF en packed(5:3), sans toucher au prototype :

*RNF3764 30 a      000800  Définition du paramètre (P(5,3)) différente de définition
                           de paramètre du prototype (P(5,2)).

La compilation échoue : l'erreur est trouvée avant toute exécution. Le compilateur vérifie aussi le nom : compilé sous un autre nom que celui d'EXTPGM, le même source donne l'avertissement RNF3776 (« Programme externe du prototype de la procédure principale différent du programme en cours de création »).

Faisons maintenant l'inverse : un appelant qui recopie le prototype à la main, au lieu du /COPY, et se trompe de type pour le taux :

// Prototype recopie a la main, et faux : taux en zone (zoned)
dcl-pr tvaf extpgm('TVAF');
  montantHt packed(11:2) const;
  taux zoned(5:2) const;
  montantTtc packed(11:2);
end-pr;

APPELXF compile sans un message : le compilateur ne connaît que ce prototype-là. L'erreur n'apparaît qu'à l'exécution, dans TVAF, qui lit en condensé un taux transmis en étendu :

Complément d'informations sur message : ID message RNQ0907, gravité 99, Erreur de données décimales, la procédure TVAF du programme JOBIPRPI/TVAF a trouvé une erreur de données décimales à l'instruction 20
F1 sur le message : RNQ0907, erreur de données décimales dans TVAF, à l'instruction 20 (le calcul).
Écran Entrée de commandes après CALL APPELXF : Erreur dans une donnée décimale, deux fois Erreur de données décimales et Appel à *LIBL/TVAF terminé en erreur, réponses C, puis MCH1202 unmonitored by TVAF at statement 0000000020
Après les réponses C : MCH1202, l'erreur de données décimales, non surveillée dans TVAF.

Un seul prototype, dans un membre copié des deux côtés : c'est ce que recommande IBM pour un programme ou une procédure appelé par d'autres programmes ou modules RPG.

Exemple 3 Les procédures

Des procédures internes, avec ou sans PR

Le programme PROC contient deux procédures : TTC, qui rend une valeur, et LIBELLE, qui a un paramètre facultatif. Elles sont dans le même source que leurs appels : le prototype est alors facultatif, le compilateur le déduit du PI.

RPG IV colonné PROC4

     H DFTACTGRP(*NO) DECEDIT('0,')
     H* PROC4 : deux procedures internes, sans PR (facultatif).
     DTEXTE            S             52A
     C                   EVAL      TEXTE = LIBELLE(TTC(100 : 20))
     C     TEXTE         DSPLY
     C                   EVAL      TEXTE = LIBELLE(TTC(59.90 : 5.5) : 'USD')
     C     TEXTE         DSPLY
     C                   EVAL      *INLR = *ON
     P* TTC : rend une valeur ; parametres passes par VALUE
     PTTC              B
     DTTC              PI            11P 2
     D HT                            11P 2 VALUE
     D TAUX                           5P 2 VALUE
     DRESULTAT         S             11P 2
     C                   EVAL(H)   RESULTAT = HT * (1 + TAUX / 100)
     C                   RETURN    RESULTAT
     PTTC              E
     P* LIBELLE : parametre facultatif, OPTIONS(*NOPASS) et %PARMS
     PLIBELLE          B
     DLIBELLE          PI            40A   VARYING
     D MONTANT                       11P 2 CONST
     D DEVISE                         3A   CONST OPTIONS(*NOPASS)
     DDEV              S              3A   INZ('EUR')
     C                   IF        %PARMS >= %PARMNUM(DEVISE)
     C                   EVAL      DEV = DEVISE
     C                   ENDIF
     C                   RETURN    %CHAR(MONTANT) + ' ' + DEV
     PLIBELLE          E
SEU, membre PROC4 à partir de la ligne 9 : spécification P TTC B, ligne de format D, PI TTC 11P 2 avec les paramètres HT et TAUX en VALUE, puis la procédure LIBELLE avec son PI 40A VARYING et le paramètre DEVISE en CONST OPTIONS(*NOPASS)
Les procédures dans SEU : P … B et P … E en colonne 24, la valeur rendue sur la ligne du PI.

Full free PROCF

**FREE
// PROCF : deux procedures internes, sans PR (facultatif).
ctl-opt dftactgrp(*no) decedit('0,');

dsply libelle(ttc(100 : 20));
dsply libelle(ttc(59.90 : 5.5) : 'USD');
*inlr = *on;

// TTC : rend une valeur ; parametres passes par VALUE
dcl-proc ttc;
  dcl-pi *n packed(11:2);
    ht packed(11:2) value;
    taux packed(5:2) value;
  end-pi;
  dcl-s resultat packed(11:2);

  eval(h) resultat = ht * (1 + taux / 100);
  return resultat;
end-proc;

// LIBELLE : parametre facultatif, OPTIONS(*NOPASS) et %PARMS
dcl-proc libelle;
  dcl-pi *n varchar(40);
    montant packed(11:2) const;
    devise char(3) const options(*nopass);
  end-pi;
  dcl-s dev char(3) inz('EUR');

  if %parms() >= %parmnum(devise);
    dev = devise;
  endif;
  return %char(montant) + ' ' + dev;
end-proc;
dcl-pi *n packed(11:2);
Le type écrit sur la ligne du PI est celui de la valeur rendue par return. En colonné, c'est la longueur et le type de la ligne PI : 11P 2. Le nom du PI est facultatif (*N) ; s'il est donné, c'est celui de la procédure, comme TTC en colonné.
ht packed(11:2) value;
VALUE : la procédure reçoit une copie. Possible pour une procédure, pas pour un programme.
devise char(3) const options(*nopass);
Le paramètre peut manquer. On le teste avant de le lire : %parms() >= %parmnum(devise) (IBM documente aussi %passed(devise)).
dsply libelle(ttc(100 : 20));
Une procédure qui rend une valeur s'appelle dans une expression. Appelée par CALLP, sa valeur serait perdue.
CALL PROC4
CALL PROCF
Écran Entrée de commandes : CALL PROC4 et CALL PROCF affichent chacun 120,00 EUR puis 63,19 USD
Sans devise, LIBELLE prend EUR ; avec la devise passée, USD.

Dans un programme créé par CRTBNDRPG, les procédures demandent DFTACTGRP(*NO). Compilé avec DFTACTGRP(*YES), le même source est refusé :

RNF1520 sev 20 : La procédure ne peut pas être définie avec DFTACTGRP(*YES).

Les modes de passage des paramètres

Mot-cléPassageÀ savoir
(aucun mot-clé)Par référenceL'appelé travaille sur la variable de l'appelant et peut la modifier : c'est le paramètre de retour MONTANTTTC. Il faut passer une variable de mêmes type et longueur : un packed(9:2) à la place du packed(11:2) donne RNF7535.
CONSTPar référence, en lecture seuleL'appelé ne peut pas modifier le paramètre. On peut passer un littéral ou une expression : le compilateur crée une zone temporaire au bon format.
VALUEPar valeur (copie)L'appelé reçoit une copie, qu'il peut modifier sans toucher à l'appelant. Pour les procédures seulement : interdit avec EXTPGM.
OPTIONS(*NOPASS)FacultatifLe paramètre peut ne pas être passé, ainsi que tous ceux qui suivent, qui doivent aussi être *NOPASS. Tester %PARMS (ou %PASSED) avant de s'en servir.

Sans CONST ni VALUE, un littéral est refusé. Avec le prototype de TVAF privé de CONST sur le premier paramètre, les trois appels de APPELF donnent :

*RNF7542 30     14 001400  Paramètre 1 non admis comme paramètre transmis par
                           référence.

Voir les paramètres reçus dans le débogueur

Un point d'arrêt sur le calcul de TVAF, puis l'appel par APPELF :

STRDBG PGM(JOBIPRPI/TVAF)
BREAK 12
CALL APPELF
STRDBG, source du module TVAF : le PI tvaf et ses paramètres montantHt, taux et montantTtc, arrêt à la ligne 12 sur le calcul
Arrêt à la ligne 12 : le programme a reçu ses paramètres par le PI.
Bas de l'écran STRDBG, arrêt ligne 12 : EVAL montantHt affiche MONTANTHT = 000000100.00
EVAL montantHt : 100,00, le littéral passé par l'appelant.
Bas de l'écran STRDBG après F10, ligne 13 : EVAL montantTtc affiche MONTANTTTC = 000000120.00
F10 (une instruction), puis EVAL montantTtc : 120,00, que l'appelant retrouve dans TTC.

Les paramètres d'un PI se lisent comme des variables. CLEAR PGM enlève le point d'arrêt, F12 laisse le programme finir, ENDDBG clôt la session.

Les erreurs, et ce qu'elles veulent dire

Toutes ont été obtenues sur un IBM i 7.5, avec les variantes fautives des exemples :

MessageQuandTexteCause
RNF3764à la compilation de TVAFDéfinition du paramètre (P(5,3)) différente de définition de paramètre du prototype (P(5,2)).Le PI ne correspond pas au prototype copié. C'est le contrôle que l'on gagne avec le /COPY.
RNF3776à la compilation, gravité 10Programme externe du prototype de la procédure principale différent du programme en cours de création.Le nom de EXTPGM n'est pas celui du programme compilé.
RNF7542à la compilation de l'appelantParamètre 1 non admis comme paramètre transmis par référence.Un littéral ou une expression passé à un paramètre sans CONST ni VALUE.
RNF7535à la compilation de l'appelantLe type et les attributs du paramètre 3 ne correspondent pas à ceux du prototype.Une variable d'un autre type ou d'une autre longueur passée par référence (packed(9:2) pour packed(11:2)).
RNF1520à la compilation de PROCFLa procédure ne peut pas être définie avec DFTACTGRP(*YES).Dans un programme créé par CRTBNDRPG, des procédures exigent DFTACTGRP(*NO), en CTL-OPT ou sur la commande.
MCH1202à l'exécutionErreur dans une donnée décimale (RNQ0907 : Erreur de données décimales).Un prototype recopié à la main, faux : la compilation ne voit rien.

Sources

Les exemples ont été compilés et exécutés sur un IBM i 7.5 (voir la méthode). Les règles viennent de ces sources, consultées le 23 octobre 2026 :

  1. ILE RPG Reference (SC09-2508-12), IBM, IBM i 7.5 (PDF). Prototype et interface de procédure : le PI répète le prototype et sert au contrôle ; le nom du PI doit être celui du prototype ; dans la procédure principale, le prototype précède le PI ; positions 24-25 PR et PI ; CONST (référence en lecture seule, accepte littéraux et expressions), VALUE, interdit avec EXTPGM ; OPTIONS(*NOPASS) et %PARMS, %PARMNUM, %PASSED ; prototype implicite pour une procédure du même module (CALLP).
  2. ILE RPG Programmer's Guide (SC09-2507-12), IBM, IBM i 7.5 (PDF). Prototype facultatif quand la procédure est dans le même module ; prototype d'une procédure appelée d'ailleurs à placer dans un membre copié dans l'appelant et dans l'appelé.

Questions fréquentes

Quelle différence entre un PR et un PI en RPG ?

Le prototype (PR, DCL-PR) décrit un appel : le nom du programme ou de la procédure et les paramètres attendus. Il sert à l'appelant. L'interface de procédure (PI, DCL-PI) déclare les paramètres que le programme ou la procédure reçoit. Elle se trouve dans l'appelé. Quand les deux sont dans le même source, le compilateur vérifie qu'ils correspondent.

Le PI remplace-t-il *ENTRY PLIST ?

Oui. Dans un programme RPG IV, un PI placé dans les définitions globales déclare les paramètres du programme, comme le faisait *ENTRY PLIST, avec en plus le contrôle par le compilateur et les mots-clés CONST et OPTIONS.

Le prototype est-il obligatoire ?

Il faut un prototype pour appeler un programme ou une procédure d'un autre module. Pour une procédure du même module, il est facultatif : le compilateur le déduit du PI. Un programme n'a pas besoin de son propre prototype ; mais les programmes RPG qui l'appellent en ont besoin, et il vaut mieux alors le mettre dans un membre /COPY, copié aussi dans le programme appelé.

Pourquoi mettre le prototype dans un membre /COPY ?

Pour que l'appelant et l'appelé compilent le même prototype. Copié dans l'appelé, il est comparé au PI : une différence donne l'erreur RNF3764 à la compilation. Recopié à la main dans l'appelant, il peut être faux sans que rien ne le signale avant l'exécution, par exemple une erreur de données décimales MCH1202.

Quelle différence entre CONST et VALUE ?

Les deux protègent la variable de l'appelant et acceptent un littéral ou une expression. CONST passe une référence en lecture seule ; VALUE passe une copie, que la procédure peut modifier. VALUE est interdit pour les paramètres d'un programme (prototype EXTPGM).

Comment rendre un paramètre facultatif ?

Avec OPTIONS(*NOPASS) sur le paramètre, et sur tous ceux qui le suivent. Dans la procédure, on teste qu'il a été passé avant de l'utiliser : %PARMS() >= %PARMNUM(nom), ou %PASSED(nom).