RPG-IV en V3R70 et pointeurs

BoTTom |    Changer de couleur
 
 Gestion des pointeurs , nouveaux codes opération en V3R70 :
 
 ...........................................................................
 :  Code     :   Facteur 1     :  Facteur 2      : zone result : > : < : = :
 ...........................................................................
 :  ALLOC    :                 :  longueur       : pointeur    :   :ER :   :
 :           :                 :                 :             :   :   :   :
 :  REALLOC  :                 :  longueur       : pointeur    :   :ER :   :
 :           :                 :                 :             :   :   :   :
 :  DEALLOC(N)                 :                 : pointeur    :   :ER :   :
 :...........:.................:.................:.............:...:...:...:
 
 (N) avec DEALLOC = assignation de la valeur nulle au pointeur.
 
 en V5R10, deux fonctions intégrées viennent remplacer ALLOC et REALLOC.
 
    %ALLOC(nb) renseigne un pointeur après réservation de "nb" octets
    %REALLOC(prt : nb) alloue un espace mémoire plus grand.
 
    DEALLOC est admis en format libre (/free, /end-free)
 


|    Changer de couleur
 Quelque précisions sur les pointeurs ,
 
  cela permet de redéfinir une zone mémoire.
 
la syntaxe est la suivante :
     Dpointeur                         *   inz(%addr(variable_connue))
     Dredefine         ds                  based(pointeur)
 
Exemple
 
     Dptindic                          *   inz(%addr(*in))
     Ddsindic          ds                  based(ptindic)
     D sortie                          N    overlay(dsindic:3)
     D annul                           N    overlay(dsindec:12)
 
 
  en traitement :
 
     C                   dow       sortie = *off
                              ...
     C                   if        annul
 


|    Changer de couleur
 les ordres ALLOC, REALLOC et DEALLOC permettent une gestion dynamique
  de la taille d'un tableau :
 
     Dpttbl                            *
     Ddstbl            ds                  based(pttbl)
     D tbl                            5    dim(32767)
 
     Dunpaquet         s              7  0 inz(50)
     Dindice_maxi      s              5  0 inz(10)
     DIndice           s              5  0
 
      * on demande 50 octets à l'OS
     C                   alloc     unpaquet      pttbl
      * en V5R10
      *          pttbl = %alloc(unpaquet) ;
 
     C                   DOU        ....
                         ...
     C                   eval      Indice = Indice + 1
     C                   if        indice > indice_maxi
     c                   exsr      plusgrand
     C                   endif


|    Changer de couleur
     C                    ...
     C                   enddo
 
     C                   dealloc(N)              pttbl
     C                   eval      *inlr = *on
 
     C     plusgrand     begsr
     C                   eval      indice_maxi = indice_maxi + 10
     C                   eval      unpaquet = %size(tbl) * indice_maxi
     C                   realloc   unpaquet      pttbl
      * en V5R10
      *          pttbl = %realloc(pttbl : indice_maxi * %size(tbl) );
      *
     c                   endsr
---------------------------------------------------------------------------
 La gestion des pointeurs est simplifiée en V3R70 par la possibilité
  de manipuler directement un pointeur par:
 
     C                   eval      pt = pt + lglue
 
  "lglue" représentant alors un nombre d'octets dont il faut se déplacer
    vers la droite (en incrémentation), très pratique avec un USER SPACE


|    Changer de couleur
 
 Exemple:         Structure d'un USER SPACE.
              De                          à  
                ..........................           --
      1       01: Espace utilisateur     :            ! Octets à blanc pour
                : (64 octets à blanc)    :            ! la communication
                ..........................64         -- entre programmes
      2       65: ENTETE GENERALE        :            !
                :   DU USER SPACE        :             > Découpage image
                :                        :            !   suivante
                ..........................140        --
      3      141: Rappel des paramètres  :  INPUT     !
                :  reçus par l'API       :            !
                ..........................            !
      4         : En-tête API            :  HEADER    !  voir structures
                :  (valeurs rencontrées) :             > dans QSYSINC
                ..........................            !  (option 13 de l'OS)
      5         : Liste générée par API  :  LIST      !
                :                        :            !
                :  (liste des membres    :           --
                :         des objets...) :
                :........................:???


|    Changer de couleur
 .......................................................................
 :  De   :   à   :Fmt: Signification ( DECOUPAGE DE "ENTETE" )         :
 ......................................................................:
 :  65   :  68   : B : Taille de l'en-tête générale (2)                :
 :  69   :  72   : C : Version                                         :
 :  73   :  80   : C : Nom du format utilisé par l'API (ex:OBJD0100)   :
 :  81   :  90   : C : Nom de l'API ayant généré la liste              :
 :  91   : 103   : C : Siècle-date-heure(SDDDDDDHHHHHH) de remplissage :
 : 104   : 104   : C : Etat (C=Complet,I=Incomplet,P=Partiel)          :
 : 105   : 108   : B : Nb d'octets utilisés dans le user space         :
 :       :       :                                                     :
 : 109   : 112   : B : Déplacement pour atteindre la zone INPUT        :
 : 113   : 116   : B : Taille de la zone INPUT                         :
 :       :       :                                                     :
 : 117   : 120   : B : Déplacement pour atteindre la zone HEADER       :
 : 121   : 124   : B : Taille de la zone HEADER                        :
 :       :       :                                                     :
 : 125   : 128   : B : Déplacement pour atteindre la liste (LIST)      :
 : 129   : 132   : B : Taille de la liste                              :
 : 133   : 136   : B : Nb d'entrées dans la liste                      :
 : 137   : 140   : B : Taille de chaque entrée.                        :
.:.......:.......:...:.................................................:


|    Changer de couleur
      * lecture d'un user space contenant la liste des membres d'un fichier
      * (le user space doit être déja rempli par l'API QUSLMBR)
      * ===================================================================
 
      * va contenir l'adresse de début du User Space
     D pointeur1       s               *
     D i               s             10i 0
 
      * l'entête (sera plaquée sur les positions 125 à 140)
      *
     Dptrinfos         s               *
     DRTVINF           ds                  based(ptrinfos)
     D  offset                       10i 0
     D  taille                       10i 0
     D  nbpostes                     10i 0
     D  lgposte                      10i 0
 
      * LIST : DS à plaquer sur un poste (ici représentant un membre)
      *
     dptrliste         s               *
     DLIST             ds                  based(ptrliste)
     d  ... (informations membre: nom, date de création etc...)


|    Changer de couleur
 
      * prototype pour API qui retrouve pointeur de début du USER SPACE
     dQUSPTRUS         PR                  EXTPGM('QUSPTRUS')
     d  space                        20    const
     d  ptr                            *
 
      /free
       // extraction du pointeur de début
          QUSPTRUS('EXEMPLE   QTEMP' : pointeur1);
 
       // positionnement sur la partie entête (125éme octet)
          ptrinfos = pointeur1 + 124;
 
 
       //  maintenant RTVINF  (DS) a un contenu valide
       //  (rappel)
       // RTVINF   e       ds                  based(ptrinfos)
       //   offset                       10i 0
       //   taille                       10i 0
       //   nbpostes                     10i 0
       //   lgposte                      10i 0
 


|    Changer de couleur
 
       // positionnement sur le premier poste
       //  (la structure "LIST" vient se positionner "par dessus")
 
          ptrliste = pointeur1 + offset;
 
 
       //  boucle (nbpostes fois)
          for       i = 1 to nbpostes;
               // traitement d'un élément
                         ...
                         ...
                         ...
                         ...
                         ...
               if        i < nbpostes;
                         ptrliste = ptrliste + lgposte;
               endif;
 
          endfor;
 
et enfin, Trigger :


|    Changer de couleur
 Trigger : Pgm associé à une action base de données (ajout, màj, supression)
 
 cette association se fait par   ADDPFTRG :
 
                    Ajouter déclencheur fich phys (ADDPFTRG)   
 
 Indiquez vos choix, puis appuyez sur ENTREE. 
 
 Fichier physique . . . . . . . . >  CLIENTP       Nom
   Bibliothèque . . . . . . . . .     *LIBL       Nom, *LIBL, *CURLIB
 Moment de déclenchement  . . . . >  *BEFORE       *BEFORE, *AFTER
 Evénement de déclenchement . . . >  *UPDATE  <--+ *INSERT, *DELETE, *UPDATE
 Programme  . . . . . . . . . . . >  TRIGGER1    | Nom
   Bibliothèque . . . . . . . . .     *LIBL     | Nom, *LIBL, *CURLIB
 Remplacer déclencheur  . . . . .   *NO         | *NO, *YES
 Condition déclenchement en màj     *ALWAYS  <--+ *ALWAYS, *CHANGE
                                                |
                                                |
                           .....................|........................
                           : le mot-clé TRGUPDCND ne s'affiche que si   :
                           : TRGEVENT est saisi avec la valeur *UPDATE  :
                           :............................................:


|    Changer de couleur
 
 Le pgm trigger peut signaler une erreur logique :
 
 
 
 
    + il doit envoyer un message à l'appelant
 
 
    + l'action base de données est interrompue inachevée.
 
 
    + le message CPF502B est émis, le message envoyé par votre trigger
        n'est pas retransmis (donc le texte est inutilisable)
 
 
 
  Mais, la gestion des triggers change en V3R70
 
 
 la commande ADDPFTRG accepte un nouveau paramètre ALWREPCHG.
 


|    Changer de couleur
 
 lorsque ce paramètre est renseigné à oui, le trigger peut modifier
  l'enregistrement base de donnée qui a provoqué son appel :
 
 c'est à dire faire de la substitution de données.
 
 
 RAPPEL, un trigger recoit un buffer contenant :
 
 - des informations système
 
 - la version AVANT de l'enregistrement
 
 - la version APRES.
 
 
 le trigger peut donc maintenant faire de la substitution de données
   et/ou renseigner automatiquement les champs vides.
 
 ce sont les données du trigger qui seront placées dans la base et non
   celles initialement indiquées par le programme.
 


|    Changer de couleur
 
 Exemple :
 
 soit un fichier article avec le buffer suivant
 
      | codearticle |  libellé                   |  datecrt   |
      |             |                            |            | 
 
 le trigger recoit un paramètre
 
   infos système              | code |libellé |date | code |libellé |date |
 |              | Dep1 | Dep2 |                     |                     | 
                   !     !    ^                     ^
                   !-----!----!                     !
                         !                          !
                         !--------------------------!
 
 
 dep1 indique le déplacement pour aller à la version avant du buffer
 dep2  "       "    "          "   "           "     après du buffer
 
 


|    Changer de couleur
 
 le paramètre ALWREPCHG fait que si le trigger modifie la version après
   c'est cette version de l'enregistrement qui est stockée dans la base.
 
 Imaginons maintenant de rajouter dans le fichier article une zone SIECLE
  complétant la zone date de création (6,0)
 
   (répenser à la nouveauté CHGPF qui permet de modifier un fichier ONLINE)
 
   Puis recompilons tous les programmes utilisant le fichier article.
 
 
 si nous n'avons pas modifié le source de ces programmes la zone SIECLE
   n'est JAMAIS renseignée.
 
 Ajoutons maintenant un trigger BEFORE/UPDATE, BEFORE/INSERT qui calcule
  automiquement le SIECLE en fonction de l'année.
 
 
 Vous avez le SIECLE  dans vos fichiers,
  reste à modifier les programmes devant afficher cette information.
 


|    Changer de couleur
 
techniquement cela ce fait de la manière suivante :
 
définition des paramètres recus :
 
     Dparam            ds
     D  filler                       64
     D   dep2                        10I 0
 
puis déclaration d'une DS externe(avec le fichier article) basée sur un
  pointeur.
 
il s'agit en fait d'un découpage théorique qui n'a pas d'existence tant que
le pointeur n'a pas de valeur.
 
     Dptr              S               *
     Darticle        e ds                  based(ptr) EXTNAME(articlp1)
 
 attribuer à ptr l'adresse de param revient à "plaquer" article sur param,
  "+ dep2" revient à le décaler de "dep2" octets.
 
     c                   eval      ptr = %addr(param) + dep2


|    Changer de couleur
code complet :
==============
     Dparam            DS
     D  filler                       64
     D   dep2                        10I 0
     Dlgparam          S             10I 0
     Dptr              S               *
     Darticle        E DS                  based(ptr) EXTNAME(articlp1)
 
     C     *entry        plist
     C                   parm                    param
     C                   parm                    lgparam
 
     c                   eval      ptr = %addr(param) + dep2
     c                   if        datcrt < 500101
     c                   eval      siecle = 20
     c                   else
     c                   eval      siecle = 19
     c                   endif
 
      * n'oublions pas le
     C                   return





©AF400