Travailler avec IFS, intégration RPG4 et APIs du C

BoTTom |    Changer de couleur
 
 ILE permet d'utiliser en RPG 4 des fonctions écrites ou destinées au C/400.
 
  le protypage RPG 4 va permettre de réaliser cela.
 
 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
 
 Manipulation de fichiers IFS
 
  fonction open
 ..................................................................
 :  D open            PR            10I 0 extproc('open')         :
 :  D  chemin                         *    Value Options(*string) :
 :  D  oflag                        10I 0  value                  :
 :  D  mode                         10U 0  value Options(*nopass) :
 :  D  codepage                     10U 0  value Options(*nopass) :
 :  D  c_ccsid [V5R20]              10U 0  value Options(*nopass) :
 :................................................................:
 
 La valeur retournée est un descripteur de fichier ou -1 en cas d'erreur
  (les API perror(), __errno() et strerror() retournent le code erreur)
 
 Chemin correspond au nom complet du fichier manipulé
 
 oflag  indique les options d'ouverture (voir ci dessous)
 mode   indique les droits à assigner (en cas de création)
 codepage indique le code page à assigner (particulièrement en création)
 c_ccsid  indique le ccsid à utiliser lors des I/O


|    Changer de couleur
Options d'ouverture (certaines peuvent être cumulées)
 
  * Traduit de QSYSINC/H.FCNTL
  */*******************************************************************/
  */* File Access Modes (type d'ouverture, paramètre oflag)           */
  */*******************************************************************/
  *#define O_RDONLY 00001 /* lecture uniquement */
 D O_RDONLY        S             10I 0  INZ(x'01')
  *#define O_WRONLY 00002 /* écriture uniquement */
 D O_WRONLY        S             10I 0  INZ(x'02')
  *#define O_RDWR 00004 /* Ouveture pour lecture/écriture */
 D O_RDWR          S             10I 0  INZ(x'04')
  *#define O_CREAT 00010 /* Création si le fichier n'existe pas */
 D O_CREATE        S             10I 0  INZ(x'08')
  *#define O_EXCL 00020 /* Erreur si O_CREAT et fichier existe déja */
 D O_EXCL          S             10I 0  INZ(x'10')
  *#define O_TRUNC 00100 /* Mise à blanc lors de l'open             */
 D O_TRUNC         S             10I 0  INZ(x'40')
  */*******************************************************************/
  */* File Status Flags values */
  */*******************************************************************/
  *#define O_CODEPAGE 040000000 /* le 4ème paramètre est un code page */


|    Changer de couleur
 D O_CODEPAGE      S             10I 0  INZ(x'800000')
  *#define O_CCSID  E 000000020 /* le 4ème paramètre est un CCSID (1) */
 D O_CCSID         S             10I 0  INZ(x'000020')
  *#define O_TEXTDATA 0100000000 /* le fichier est un fichier texte (2) */
 D O_TEXTDATA      S             10I 0  INZ(x'01000000')
  *#define O_APPEND 00400 /* position à fin de fichier lors de l'open */
 D O_APPEND        S             10I 0  INZ(x'0100')
  *#define O_LARGEFILE 004000000000 /* ouverture d'un fichier large >2Go */
 D O_LARGEFILE     S             10I 0  INZ(x'20000000')
  *#define O_INHERITMODE 001000000000 /* droits hérité du répertoire */
 D O_INHERITMODE   S             10I 0  INZ(x'08000000')
  */*******************************************************************/
  */* File Share Mode Values */
  */*******************************************************************/
  *#define O_SHARE_RDONLY 000000200000 /* partage en lecture */
 D O_SHARE_RDONLY  S             10I 0  INZ(x'010000')
  *#define O_SHARE_WRONLY 000000400000 /* partage en écriture */
 D O_SHARE_WRONLY  S             10I 0  INZ(x'020000')
  *#define O_SHARE_RDWR 000001000000 /* partage en lecture/écriture */
 D O_SHARE_RDWR    S             10I 0  INZ(x'040000')
  *#define O_SHARE_RDWR 000002000000 /* aucun partage */
 D O_SHARE_NONE    S             10I 0  INZ(x'080000')


|    Changer de couleur
 
 (1)  CCSID et Codes Pages sur les fichiers IFS.
 
  depuis la V5R10, les fichiers IFS sont marqués par un CCSID et non plus
   une page de code.
 
  Cette version apporte un nouveau CCSID 5348, qui correspond au 1252
  (ANSI LATIN-1), mais avec le support de l'EURO [¤].
 
  ATTENTION, la conversion 297 <-> 5348 ne peut pas avoir lieu
           (1147 <-> 5348 oui, 1147 étant l'EBCDIC francais avec EURO)
 
 Vous ne pourrez pas copier un fichier (CPY) de 297 vers 5348
                     éditer(EDTF) un fichier en 5348 si votre job est en 297
                     utiliser l'API open() si votre job est en 297
 
 
  - O_CODEPAGE, qui est compatible avec la V4R50 créé un fichier en CCSID
     5348 quand 1252 est demandé (1252 étant considéré comme une codepage)
 
  - O_CCSID, disponible depuis la V5R10 uniquement respecte scrupuleusement
     la demande de CCSID (à privilégier donc)


|    Changer de couleur
 
 (2) option O_TEXTDATA
 
  Si cette option est utilisée et uniquement sur un fichier existant
   le système assure une conversion entre le CCSID du JOB et le CCSID
   du fichier lors des lectures et des écritures
 
  Les fin de ligne (LF) sont enlevées lors d'une lecture, elles sont
   automatiquement ajoutées lors d'une écriture
 
 ceci nous oblige à ouvrir le fichier une première fois avec les options
  O_CREATE et O_CCSID, le fichier est alors créé avec le CCSID demandé.
 
 Vous devez impérativement renseigner le 4ème paramètre
 
    rappel :  819 est l'ascii internationnal (celui d'Unix)
              850 est l'ascii PC (celui de DOS)
             1252 est l'Ansi (l'ascii de WIndows si vous préférez)
             5348 est le CCSID pour l'ANSI avec le caractère EURO.
 
 Puis nous le fermerons, pour le réouvrir avec l'option O_TEXTDATA.
 


|    Changer de couleur
 
 Si vous êtes en V5R20, vous pouvez ajouter la déclaration suivante
 
 D/if defined(*V5R2M0)
  *    Autorise la conversion vers le bon CCSID dès la création
  *     il faut alors renseigner le 5ème paramètre de l'API open()
  * Note: O_TEXT_CREAT implique l'utilisation des options suivantes :
  *           O_CREAT+O_TEXTDATA+(O_CODEPAGE ou O_CCSID)
  *
  *#define O_TEXT_CREAT 020000000 /* conversion sur nouveau fichier */
 D O_TEXT_CREAT    S             10I 0  INZ(x'0200000')
 D/endif
 
 Qui permet de préciser le CCSID à utiliser lors des write() en 5ème
  paramètre en plus du CCSID à assigner au fichier en 4ème paramètre.
 
 Ceci évite la double ouverture du fichier assez fastidieuse
 
 ####################################################################### 
 # Vous remarquerez if defined(*V5R2M0) conditionnant la déclaration   # 
 ####################################################################### 
 


|    Changer de couleur
 
 * Traduit de QSYSINC/SYS.STAT
 */*********************************************************************/
 */* droits et type de fichier                                            */
 */*********************************************************************/
 * Droits du propriétaire
 * -----------------------
 * #define S_IRUSR 0000400 /* Read for owner */
 D S_IRUSR         S             10I 0  INZ(x'0100')
  * #define S_IWUSR 0000200 /* Write for owner */
 D S_IWUSR         S             10I 0   INZ(x'80')
  * #define S_IXUSR 0000100 /* Execute and Search for owner */
 D S_IXUSR         S             10I 0   INZ(x'40')
  * #define S_IRWXU 0000100 /* les trois précédents */
 D S_IRWXU         S             10I 0   INZ(x'01C0')
 
  * Droits du groupe
  *-----------------
  * #define S_IRGRP 0000040 /* Read for group */
 D S_IRGRP         S             10I 0   INZ(x'20')
  * #define S_IWGRP 0000020 /* Write for group */
 D S_IWGRP         S             10I 0   INZ(x'10')


|    Changer de couleur
 
  * #define S_IXGRP 0000010 /* Execute and Search for group */
 D S_IXGRP         S             10I 0   INZ(x'08')
 
  * Droits pour *public
  *-----------------------
  * #define S_IROTH 0000004 /* Read for other */
 D S_IROTH         S             10I 0   INZ(x'04')
  * #define S_IWOTH 0000002 /* Write for other */
 D S_IWOTH         S             10I 0   INZ(x'02')
  * #define S_IXOTH 0000001 /* Execute and Search for other */
 D S_IXOTH         S             10I 0   INZ(x'01')
  * #define S_IRWXO (S_IROTH|S_IWOTH|S_IXOTH) /* RWX for other */
 D S_IRWXO         S             10I 0   INZ(x'07')
 
  fonction close
 ..................................................................
 :  D close           PR            10I 0 extproc('close')        :
 :  D  fileHandle                   10I 0  Value                  :
 ..................................................................
 la valeur retour contient 0 (fermeture normale) ou -1 (erreur)
 


|    Changer de couleur
 
Autres fonctions (retournent toutes le nbr d'octets manipulés ou -1)
 
 
 fonction write
..................................................................
:  D write           PR          10I 0 extproc('write')          :
:  D  fileHandle                 10I 0  Value                    :
:  D  bufferO                      *    Value                    :
:  D  bufferlen                  10U 0  Value                    :
..................................................................
 
 
 fonction read
..................................................................
:  D read            PR          10I 0 extproc('read')           :
:  D  fileHandle                 10I 0  Value                    :
:  D  bufferI                      *    Value                    :
:  D  bufferlen                  10U 0  Value                    :
..................................................................
 
 


|    Changer de couleur
 
 Fonction lseek(), positionnement dans le fichier
 
 fonction lseek
..................................................................
:  D lseek           PR          10I 0 extproc('lseek')          :
:  D  fileHandle                 10I 0  Value                    :
:  D  offset                     10I 0  Value                    :
:  D  reference                  10U 0  Value                    :
..................................................................
 
  * reference doit contenir l'une des valeurs suivantes :
  *---------------------------------------------------
 
  * #define SEEK_SET        /* Offset absolu (position dans le fichier) */
 D SEEK_SET        C                    0
  * #define SEEK_CUR        /* Offset relatif à la position actuelle    */
 D SEEK_CUR        C                    1
  * #define SEEK_END        /* Offset relatif à la fin de fichier       */
 D SEEK_END        C                    2
 
 





©AF400