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). |
+-------------+------------+--------------------------------------------+ + 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 + + +-------------+------------+--------------------------------------------+ |
+-------------+------------+--------------------------------------------+ + 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. |
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) : :................................................................: |
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 |
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) : :................................................................: |
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 |
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 |
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 */ |
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') |
(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) |
(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. |
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 # ####################################################################### |
* 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') |
* #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) |
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 : .................................................................. |
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 |