RPG-IV: procédures et fonctions

BoTTom |    Changer de couleur
  Les versions 3.60 et 3.20 apportent à RPG-IV un nouvel ordre, CALLP.
 
  il permet de faire des appels de programmes en format libre
 
     il faut pour cela déclarer le programme et ses paramètres avant,
      en spécif D, cela s'appelle un PROTOTYPE :
 
  DEXEC             PR                  EXTPGM('QCMDEXC')
  D                              250
  D                               15P 5 CONST
   **** fin du prototype, déclaration des variables de travail
  Dcommande         S            250    INZ('WRKSPLF')
 
    PR indique qu'il s'agit d'un prototype (même positions que DS)
    EXTPGM le nom du pgm externe
 
    CONST sur un paramètre indique que les expressions sont admises
 
  C                   callp     exec(commande:%size(commande))
   * ou bien ...
   /free
         exec(commande:%size(commande))


|    Changer de couleur
 
  Le même ordre peut être utilisé pour l'appel à des procédures liées
     (liage par copie[module] ou par référence[programme de service].)
 
     il faut alors déclarer la procédure et ses paramètres, avant, en
      spécif D avec le mot-clé EXTPROC
 
  Dinviteclient     PR                  EXTPROC('F4client')
  D                                6  0
  D                                1    VALUE
 
    EXTPROC le nom de la procédure
 
    VALUE indique qu'il s'agit d'un paramètre non modifiable, dont on envoi
          une copie de la valeur,ce qui autorise les expressions, comme
          avec CONST. (value n'est pas valide avec EXTPGM)
 
ce qui permet
 
     C                   callp     inviteclient(nocli:'W'))
 
 


|    Changer de couleur
 
 Rappel sur la réception de paramètres :
 
 
    -> la réception des paramètres peut elle même etre réalisée
 
 
       a/ comme avant (*ENTRY PLIST)
 
 
       b/ en spécif D, avec une interface de procédure ( PI )
 
 
        DProgrammeB       PI
        D nocli                          6  0
 
          en entete du programme appelé, pour un programme externe
 
          en entete de procédure, dans le cas d'une procédure,
             comme vu ci-dessous :
 
 


|    Changer de couleur
 
 La procèdure peut être dans le même source car RPG-IV admet maintenant
  plusieurs procédures (au sens ILE) par source.
 
  Une procédure ressemble à :
 
    - un sous-programme :
 
            elle est codée dans le même source
            elle a des temps de réponse proches
            elle "voit" les fichiers ouverts par le pgm principal.
 
   - à un programme indépendant :
 
            elle occupe un niveau d'invocation
                        (influence sur la gestion des erreurs)
            elle ne connait que ces propres variables.
 
   - ni à l'un, ni à l'autre, car :
 
            vous choisissez si elle utilisable par un autre pgm.
            elle peut se présenter sous la forme d'une fonction


|    Changer de couleur
 
 Déclaration d'une procédure ou d'une fonction   [OBLIGATOIRE]
 
 la délaration se fait par le biais d'un prototype comme vu plus haut.
 
 Définition d'une procédure ou d'une fonction 
 
 Une nouvelle spécif "P" pour définir le début et la fin de la fonction
                                              (proche de BEGSR / ENDSR)
 EXPORT autorise l'utilisation de cette procédure par des modules externes
        (sinon cette procédure est privée c'est à dire utilisable
          uniquement dans le même source)
 
 Des Spécifs D  pour définir les paramètres recus (PI à la place de PR)
 
     Et le système VERIFIE que l'interface (PI) est identique au prototype
 
 Des Spécifs F, en V6R10, pour définir des fichiers locaux
 
 Des Spécifs D  pour définir les variables locales
 
 Les spécifs C de traitement.


|    Changer de couleur
                  structure générale d'un pgm RPG-IV :  
 
H  Spécif H générale       |contient NOMAIN s'il n'y a pas de pgm principal
F  Déclaration de fichiers |(ouvertures globales)
D  variables globales      |
D proc1           PR       | prototype procédure 1
D proc2           PR       | prototype procédure 2
I  variables des fichiers  | (globales)
C  traitement              | programme principal
O  sorties                 | sorties du programme principal
 
P proc1           B       -|
D                 PI       | définition de l'interface
D                          | variables locales
C                          | traitement
P                 E       -|
 
P proc2           B       -|
D                 PI       |  2ème procédure (idem)
D                          |
C                          |
P                 E       -|


|    Changer de couleur
 La déclaration du prototype ET de l'interface peut paraitre redondante.
 
    il faut analyser cette double déclaration dans les cas (probablement
      les plus nombreux) ou le programme qui utilise la procédure et la
      procédure ne sont pas dans le même source
 
 les prototypes ammènent alors :
 
    + le contrôle du nombre de paramètres et de leur longueur à la COMPIL
    + la possibilité de passer des paramètres par valeur.
 
      le passage de paramètres en RPG se fait naturellement par adresse.
         - le pgm appelant envoi l'adresse du paramètre
         - le pgm appelé recoit un pointeur, travail directement sur la
             mémoire du programme appelant.
         - au retour le pgm appelant voit sa variable modifiée.
 
      ° avec CONST on copie l'information en mémoire temporaire et on envoi
          l'adresse de cette copie.l'appel peut être un CALLP avec EXTPGM.
 
      ° avec VALUE on envoi directement une valeur (une copie), mais le pgm
          appellé doit une procédure, donc CALLP avec EXTPROC.


|    Changer de couleur
 
 Et tout cela nous ammène vers les fonctions,
 
    une fonction est une forme particulière de procédure qui :
 
    ° retourne une valeur (la définition est donnée sur les lignes PR ET PI)
 
    ° peut donc directement être utilisée en lieu et place de la valeur
       qu'elle retourne (comme une fonction intégrée %xxx)
 
    ° DOIT être déclarée par un prototype (CALL|CALLB sont invalides)
 
 Le prototype devant être déclaré aussi bien dans le source écrivant la
  fonction, que dans tous les sources qui l'utilisent, il est conseillé
  de placer le prototype  dans un source à part et de copier ce source
  par
 
      /COPY fichier,membre
 
 On rejoint ansi une philosophie "langage C" ou toutes les fonctions
  sont externes au langage et ou il faut copier les fichiers de déclaration
  par les fameux "include stdio.h", etc...


|    Changer de couleur
 Exemple:                             /-- cette fonction retourne du 2 dt 0.
                                     /
DFindemois        PR             2P 0 
D                                 D   DATFMT(*DMY)
 
 
P Findemois       B                   [ EXPORT ]
 * Définition de l'Interface de procédure  (PI)
 *  doit être conforme avec le prototype (vérifié à la compilation)
D                 PI             2P 0 
D Datein                          D   DATFMT(*DMY)
 * variables locales
D                 DS
D  Wdate                          D   DATFMT(*DMY)
D    wjour                       2S 0  OVERLAY(wdate)
 * traitement
C                   eval      wdate = datein
C                   eval      wjour = 1
C                   ADDDUR    1:*M          WDATE
C                   SUBDUR    1:*D          WDATE
C                   RETURN    Wjour
P Findemois       E


|    Changer de couleur
 
                           Récapitulatif.  
 
 PROTOTYPE :
 
  DFINDEMOIS        PR             2P 0
  D                                 D   DATFMT(*DMY/) CONST
 
Sont définis :
 
  + le nom du programme/de la procédure (nom externe pouvant être différent)
 
  + la définition de la valeur de retour pour une fonction
 
  + le type d'appel à réaliser EXTPROC(nom) = Appel d'une procédure->CALLB
                               EXTPGM(nom)  = Appel d'un programme ->CALL
 
  + le nombre et la nature des paramètres
 
              - le nom est facultatif et relève du commentaire
              - type et longueur
              - obligatoire (dft) ou optionnel.


|    Changer de couleur
 Syntaxe générale : 
 
D nom                  PR          lg!type    mots-clés
 
 Mots-clés admis :     DATFMT, DIM, LIKE, PROCPTR, TIMFMT
                       OPDESC demande à ce que le descripteur soit transmis
                               (équivalent à CALLB(D).)
 
  la longueur, le type et les mots-clés définissent la valeur retournée.
 
 
 INTERFACE :
 
Pnom-procédure    B
D                      PI          lg!type    mots-clés
 
Sont définis :
 
  + la définition de la valeur de retour pour une fonction
  + le nom, le nombre et la nature des paramètres recus.
 
 Mots-clés admis :     DATFMT, DIM, LIKE, PROCPTR, TIMFMT, OPDESC


|    Changer de couleur
 
 Définition des paramètres : 
 
Spécif D de définition de variable
 
 Mots-clés admis :     ASCEND, DATFMT, DIM, LIKE, PROCPTR, TIMFMT, (VARYING)
                                                                     v4r20
 
 Nouveaux mots-clés :
 
 CONST           La valeur est copiée dans une variable temporaire.
 (conseillé) 
                  ==>  utilisation possible d'expressions lors de l'appel.
 
 VALUE           passage d'un paramètre par valeur (et non par adresse)
 
                 Cette information doit être indiquée aussi bien dans le
                  prototype que dans la procédure utilisée.
                 Il s'agit d'un contrôle réalisé par le compilateur
 
 NOOPT           pas d'optimisation pour cette variable (OPTIMIZE(*FULL).)
 


|    Changer de couleur
 STATIC          cette variable est stockée en mémoire statique:
 
                 elle est initialisée lors du PREMIER appel,
                  toutes les autres fois elle retrouve sa valeur précédente.
                 les variables globales sont forcément statiques.
 
 OPTIONS(*OMIT | *NOPASS | *VARSIZE | *STR)
 
         *OMIT     la valeur *OMIT (pointeur null) est admise.
         -> La fonction %ADDR( ) retourne *NULL si le paramètre est omis.
 
         *NOPASS   le paramètre est facultatif,
                     (les paramètres suivants doivent l'être aussi)
         -> La fonction %PARMS retourne le nombre de paramètres reçus
 
         *VARSIZE  paramètre à longueur variable, la longueur indiquée est
                    une longueur maxi, une lg plus petite peu être utilisée
 
           Utilisable avec l'API CEEDOD qui décrit les paramètres reçus
            pour la procédure appelée, mais aussi avec QCMDEXC par exemple.
 
         *STR      paramètre géré en chaîne compatible C (terminaison x'00')


|    Changer de couleur
 
 ILE va permettre d'utiliser des fonctions écrites ou destinées au C/400.
 
  le protypage et les différents mot-clés vont assurer la transposition.
 
 correspondance des paramètres
 ------------------------------
 
 quelques rappels
 
 EN C, le passage de paramètres se fait par défaut par valeur
 
 EN RPG  le passage de paramètres se fait par défaut par référence
         (on passe un pointeur, comme en C par int*), pour un passage
         de paramère par valeur, indiquer VALUE 
 
 EN C, les chaines de caractères sont terminées par x'00', en RPG elles
        sont à taille fixe, sans terminaison, l'option OPTIONS(*STRING) 
        assure la correspondance, et si la paramètre envoyé est une chaine
        , GAP stocke l'information en mémoire temporaire, ajoute un zéro
        héxadécimal et transmet l'adresse (le pointeur).
 


|    Changer de couleur
 
 +-------------+------------+--------------------------------------------+
 +     C       +  RPG 4     + Mots-clés                                  +
 +-------------+------------+--------------------------------------------+
 + int, long   +  10I 0     + VALUE                                      +
 +-------------+------------+--------------------------------------------+
 + unsigned int+  10U 0     + VALUE                                      +
 +-------------+------------+--------------------------------------------+
 + double      +   8F 0     + VALUE                                      +
 +-------------+------------+--------------------------------------------+
 + char        +   1A       + VALUE (il s'agit d'UN octet seul)          +
 +OU ----------+------------+--------------------------------------------+
 + char        +  10U 0     + VALUE                                      +
 +-------------+------------+--------------------------------------------+
 + short       +  10i 0     + VALUE                                      +
 +-------------+------------+--------------------------------------------+
 + int*        +  10i 0     +                                            +
 +-------------+------------+--------------------------------------------+
 + unsigned*   +  10U 0     +                                            +
 +-------------+------------+--------------------------------------------+
 + double*     +   8F 0     +                                            +
 +-------------+------------+--------------------------------------------+


|    Changer de couleur
 
 +-------------+------------+--------------------------------------------+
 +     C       +  RPG 4     + Mots-clés                                  +
 +-------------+------------+--------------------------------------------+
 + char*       + xxxA       + OPTIONS(*STRING)                           +
 +OU ----------+------------+--------------------------------------------+
 + char*       +    *       + VALUE (il faudra utiliser %ADDR().)        +
 +-------------+------------+--------------------------------------------+
 + void*       +    *       + VALUE                                      +
 +(pointeur)   +            +                                            +
 +-------------+------------+--------------------------------------------+
 + (*)         +    *       + VALUE  PROCPTR                             +
 +(fonction)   +            +                                            +
 +-------------+------------+--------------------------------------------+
 
 L'utilisation du mot-clé CONST sera souvent un plus pour les données
  élémentaires, par exemple si une fonction C admet un integer, le prototype
  ..................................................................
  :  D mafonctionC     PR                  extproc('maFonctionC')  :
  :  D                               10i 0 CONST                   :
  :................................................................:
 permet d'utiliser du décimal paquet, le compilateur assurant la conversion.


|    Changer de couleur
 par exemple, la définition suivante
 
  double cos(double)
 
 se traduit en RPG , par :
 
  ..................................................................
  :  D cosinus         PR             8F 0 extproc('cos')          :
  :  D                                8F 0  VALUE                  :
  :................................................................:
 
 et celle ci (utilisant des chaînes)
 
  char* strcpy (char* str1, str2)
 
 se traduit en RPG , par :
 
  ..................................................................
  :  D stringcopy      PR              *   extproc('strcpy')       :
  :  D  str1                         25A    OPTIONS(*STRING)       :
  :  D  str2                         25A    OPTIONS(*STRING)       :
  :................................................................:


|    Changer de couleur
 Exemple d'un pgm complet utilisant atoi (alpha -> int) et atof (->flot)
 -----------------------------------------------------------------------
 
H bnddir('QC2LE') DFTACTGRP(*NO) ACTGRP(*CALLER)
D atoi            pr            10i 0 extproc('atoi')
D  num                            *   options(*string) value
D atof            pr             8f   extproc('atof')
D  num                            *   options(*string) value
D i               s             10i 0
D p               s             13p 7
C                  movel     '-100  '      num               6
C                  eval      i = atoi(%trim(num))
 *
 *  I = -100
C                   eval(h)   p = atof(%trim(num))
 *
 *  P = -000100.0000000
C                   movel     '-5.67 '      num               6
C                   eval(h)   p = atof(%trim(num))
 *
 *  P = -000005.6700000
                   return


|    Changer de couleur
 
Pour une valeur retour de type chaine, nous avons deux possibilités :
 
 1/ baser une variable sur le pointeur recu :
  ..................................................................
  :  D ptr             S               *                           :
  :  D chaine          S             50A   BASED(ptr)              :
  :                                                                :
  :   /free                                                        :
  :     ptr = stringcopy(chaine1 : chaine2) ;                      :
  :     if chaine = *blanks;                                       :
  :................................................................:
 
 2/ Utiliser la fonction RPG %str()
  ..................................................................
  :  D ptr             S               *                           :
  :  D chaine          S             50A                           :
  :                                                                :
  :   /free                                                        :
  :     ptr = stringcopy(chaine1 : chaine2) ;                      :
  :     eval chaine = %str(ptr)                                    :
  :................................................................:


|    Changer de couleur
 
 Certaines fonctions utilisent des variables globales, par exemple system()
 
H bnddir('QC2LE') DFTACTGRP(*NO) ACTGRP(*CALLER)
 
D Exec            pr            10i 0 Extproc('system')
D  cmd                            *   options(*string) value
 
D ErrMsgID        S              7    IMPORT('_EXCP_MSGID')
D retour          S             10I O
 
 /free
 
   retour = Exec('DLTSPLF *SELECT');
 
   if retour > 0;
 
      if ErrMsgID = 'CPF....' ;
 
         .../...
 
 /end-free


|    Changer de couleur
 
 
 La version 7 apporte quelques nouveautés sur le plan des prototypes
 
 
  - les valeurs retour des fonctions peuvent être maintenant
      transmises en tant que paramètre (caché)
 
    en effet les valeurs retour des fonctions étaient transmises en tant
     que valeur sur la pile d'appel.
 
    lorsque ces dernières étaient de grande taille , cela avait un impact
     sur les performances, particulièrement lors d'appels successifs.
 
    en utilisant RTNPARM la valeur retour est en fait un paramètre
     supplémentaire transmis par adresse, donc plus rapide d'accès.
 
 
    ce paramètre doit être indiqué dans le prototype ET l'interface de
     procédure.
 
 


|    Changer de couleur
 
 Si vous appellez un langage autre que RPG, vous devez alors fournir un
  paramètre supplémentaire en première position pour la valeur retour.
 
 Exemple :
 
 D getLibText      pr            50a   RTNPARM
 D   bib                         10a   CONST
  /free
       if getLibText('BDVIN1') = *blanks;
 
   .../...
 
 PGM PARM(&TEXT &BIB)
 DCL &TEXT TYPE(*CHAR) LEN(50)
 DCL &BIB  TYPE(*CHAR) LEN(10)
 
 RTVOBJD OBJ(&BIB) OBJTYPE(*LIB) TEXT(&TEXT)
 
  .../...
 
 Ce paramètre RTNPARM n'est admis qu'avec des procédures.


|    Changer de couleur
 
  - les prototype n'ont plus à être indiqués impérativement dans le source
      qui implémente une fonction, mais uniquement dans ceux qui l'utilisent
 
   par exemple dans un programme de service, ce code suffit :
 
  P getDate         B                   EXPORT
  D                 pi              D
   /free
     return %date ;
   /end-free
  P getDate         E
 
 bien sur dans les programmes utilisant la fonction il faudra écrire
 
  D getDate         PR              D
 
 le compilateur devant absolument savoir que getDate est une fonction :
 
      a/ sans paramètre
      b/ qui retourne une date
 


|    Changer de couleur
 
 tableau des mots-clés et du contexte où ils sont admis :
 
+---------------------+----------------+----------------+----------------|
| Mot-clé             |   Prototype    |   Procédure    |    paramètre   |
|                     |      (PR)      | Interface (PI) |    (PR ou PI)  |
+---------------------+----------------+----------------+----------------|
| ASCEND              |                |                |        A       |
+---------------------+----------------+----------------+----------------|
| CONST               |                |                |        A       |
+---------------------+----------------+----------------+----------------|
| DATFMT              |        A       |        A       |        A       |
+---------------------+----------------+----------------+----------------|
| DESCEND             |                |                |        A       |
+---------------------+----------------+----------------+----------------|
| DIM                 |        A       |        A       |        A       |
+---------------------+----------------+----------------+----------------|
| EXTPGM              |        A       |                |                |
+---------------------+----------------+----------------+----------------|
| EXTPROC             |        A       |                |                |
+---------------------+----------------+----------------+----------------|
 


|    Changer de couleur
 
+---------------------+----------------+----------------+----------------|
| Mot-clé             |   Prototype    |   Procédure    |    paramètre   |
|                     |      (PR)      | Interface (PI) |    (PR ou PI)  |
+---------------------+----------------+----------------+----------------|
| LIKE                |        A       |        A       |        A       |
+---------------------+----------------+----------------+----------------|
| NOOPT               |                |                |        A       |
+---------------------+----------------+----------------+----------------|
| OPDESC              |        A       |        A       |                |
| (pour les API ILE)  |                |                |                |
+---------------------+----------------+----------------+----------------|
| OPTIONS             |                |                |        A       |
+---------------------+----------------+----------------+----------------|
| PROCPTR             |        A       |        A       |        A       |
+---------------------+----------------+----------------+----------------|
| TIMFMT              |        A       |        A       |        A       |
+---------------------+----------------+----------------+----------------|
| VALUE               |                |                |        A       |
+------------------------------------------------------------------------+
| RTNPARM (V7)        |        A       |        A       |                |
+---------------------+----------------+----------------+----------------+





©AF400