Nouveautés V6R10 du compilateur RPG-IV -Support complet du multithreading avec THREAD(*CONCURRENT) en specif H Chaque thread possède une copie des variables déclarées STATIC certaines variables peuvent être partagées par STATIC(*ALLTHREAD) le mot-clé SERIALIZE sur une procédure demande à ce que cette dernière ne puisse être lancée que par un thread à la fois. -support plus souple d'UNICODE une conversion implicite est réalisée lors des affectations(EVAL/EVALR) et des tests (IF, DOW/DOU, ...) entre une variable EBCDIC et une variable UNICODE, sans utilisation des fonctions %CHAR() et %UCS2() cette conversion implicite était déja réalisée par MOVE/MOVEL |
-la taille maxi des constantes passe à 16380 (la moitié pour UNICODE) -la taille maxi des variables caractères passe de 65535 à 16 Mo !! le nombre d'occurrences d'une DS ou d'un tableau n'est plus limité qu'à la taille globale maxi de 16.773.104 octets ( 16 Mo ) le mot-clé LEN peut être utilisé à la place des colonnes 33/39 (lg) sur la définition d'une zone ou d'une DS (spécif D) le mot-clé VARYING admet un paramètre (2 ou 4) indiquant le nombre d'octets utilisés pour stocker la lg. Sans paramètre, le compilateur calcul. la fonction %ADDR() admet un deuxième argument *DATA quand elle s'applique sur une zone VARYING, demandant à ce que l'adresse pointe sur la partie significative de la variable (et non les octets binaires de début) Tout cela permettant une meilleure gestion des flux XML avec xml-into |
XML-INTO : la ptf SI34938 apporte deux nouvelles options à xml-into 1/ datasubf permet de régler le problème suivant: Ddata S 1024 inz('+ D <cours nom="XML" module="PGM"> D manipuler du XML en RPG D </cours> D ') La balise cours contient deux attributs nom et module, mais aussi une donnée directement encadrée par la balise (ici le texte descriptif) l'option datasubf=text ("text" est un exemple), permet de recevoir les données dans une DS de ce type : DCOURS DS D NOM 10 D MODULE 10 D TEXT 50 |
2/ countprefix permet de recevoir le nombre d'éléments extrait dans un compteur. Ddata S 1024 inz('+ C <les cours> D <cours nom="XML" module="PGM"> D </cours> D <cours nom="XML" module="RPG"> D </cours> D <cours nom="XMl" module ="GAP"> D </cours></lescours>') countprefix=nbr, permet d'avoir une DS de ce type associé à xml-into Dlescours Dnbrcours 10I 0 Dcours likeds(cours_modele) DIM(50) la variable nbrcours contenant ensuite la valeur 3. (voir http://www-949.ibm.com/software/rational/cafe/docs/DOC-2975 ) |
V6R10 , la ptf SI42426 apporte trois autres options à xml-into 3/ ns , gestion des namespace (espaces de nommage) parfois la structure XMl utilise les namespace, pour "qualifer" les noms : Ddata S 1024 inz('+ D <les cours xmlns:vNS= D "http://www.volubis.fr/NS"> D <vNS:cours nom=="XML" module="PGM"> D </cours> D <vNS:cours nom="XML" module="RPG"> D </cours> D <vNS:cours nom="XMl" module ="GAP"> D </cours></lescours>') ns=remove enlève les espaces de nommage pour rechercher les sous-zones (la data structure s'appelle cours) ns=merge ajoute l'espace de nommage en remplacant ":" par "_" (la data structure s'appelle vNS_cours) |
4/ ns_prefix, récupération du namespace nsprefix=namespc_ si on trouve une zone namespc_xxx, oùu xxx est le nom de la zone cette dernière recevera le namespace, soit "vNS" dans nos exemples. exemple DCOURS DS D NOM 10 D namespc_NOM 32 D MODULE 10 D namespc_MODULE 32 5/ case=convert gère les balise XML portant des noms, non valides en RPG (code-postal) les noms sont convertit en majuscules (comme case=any),les caractères invalides remplacés par '_', sauf le première caractère qui est ignoré s'il est invalide. (code-postal devient CODE_POSTAL) |
-La taille du module ou du programme objet peut être réduite par OPTION(*NOUNREF) en spécif H ou sur la commande de compilation. les variables non utilisées ne sont plus répercutées dans l'objet. la valeur par défaut est *UNREF (même résultat qu'aujourd'hui) -les informations concernant le pgm et ces paramètres pouvaient déja être notées dans un fichier stream au format PCML par PGMINFO(*PCML) ce fichier PCML était utile pour des apppels depuis JAVA, mais aussi pour la création de services WEB. la création de services web étant facilité en V6R10 (nouveau serveur d'application intégré) ces informations peuvent maintenant être stockées dans l'objet PGMINFO(*PCML:*MODULE) dans un fichier IFS PGMINFO(*PCML : *STMF) ou dans les deux PGMINFO(*PCML : *ALL) |
- la spécif F possède de nouveaux paramètres sur les versions précédentes, il était possible d'indiquer un nom réel de fichier à utiliser à l'exécution, par EXTFILE, évitant des OVRDBF EXTDESC() permettant d'indiquer le nom du fichier à la compilation -> cela permet de compiler avec un fichier qui n'est pas dans *LIBL EXTDESC('BDVIN1/VINS') -> cela permet de manipuler un fichier ayant le même nom de format puisque que c'est le nom en spécif F qui est utilisé le paramètre EXTFILE(), admet maintenant EXTFILE(*EXTDESC) demandant à ce que le nom réel à l'exécution soit celui de EXTDESC - les définitions de fichier (F) et de DS (D) admettent un nouveau mot-clé TEMPLATE indiquant que cette déclaration n'est qu'un modèle. - EXTNAME , mot-clé lié à une DS externe (spécif D), admet maintenant un litéral, éventuellement qualifié |
Les ordres d'entrée/sortie READ,CHAIN,UPDATE,etc, admettaient un nom de DS résultat dans le cadre d'un fichier décrit en interne. la DS résultat est maintenant admise aussi pour un fichier externe et EXFMT possède aussi cette possibilité. -un nom de format peut être qualifié par QUALIFIED en spécif F le nom de format doit être manipulé sous la forme "fichier.format" (dans notre exemple il s'agit d'une TABLE SQL, d'où le même nom) il n'a plus à être unique : il n'y a plus de spécif I et O pour ce fichier ==> les I/O doivent utiliser une DS : Fvins IF E DISK QUALIFIED Din DS LIKEREC(vins.vins) /free read vins IN; dsply IN.VIN_NOM; return; /end-free |
le mot-clé MAIN en spécif H permet d'indiquer une sous procédure en tant que procédure principale.Cette dernière ne peut être lancée que par CALL. le source ne contient donc plus que des procédures, la procédure déclarée MAIN doit contenir EXTPGM('le-nom-du-pgm') sur le proptotype il n'y a plus de cycle GAP , il faut donc fermer explicitement par CLOSE les fichiers (le compilateur signale une erreur RNF7534 de gravité 10) source TESTMAIN h MAIN(ENTREE) D ENTREE PR EXTPGM('TESTMAIN') D 5A P ENTREE B D PI D parm1 5A /free dsply parm1; /end-free P ENTREE E |
les spécif F sont admises maintenant locales (à l'intérieur des procédures) entre la spécif P et les D. les entrées/sorties doivent être réalisées à l'aide de DS. les fichiers sont fermés automatiquement à la fin de la procédure, sauf à utiliser STATIC, qui garde les fichier ouverts et les variables chargées. Exemple, utilisation d'une fonction "lecture" qui retourne une donnée Caractère/50 (le nom) à partir d'un code numérique en entrée. H DFTACTGRP(*NO) ACTGRP(*CALLER) ALWNULL(*USRCTL) D lecture PR 50 D 10I 0 CONST /free dsply lecture(1) ; *inlr = *on; /end-free la procédure lecture, contenant sa propre spécif F : |
P lecture B Fvins IF E DISK QUALIFIED D PI 50 D code 10I 0 CONST Din DS LIKEREC(vins.vins) /free chain code vins IN; return IN.VIN_NOM; /end-free P lecture E Cela permet de mieux gérer les fonctions dans des programmes de service retournant des valeurs basées sur des données venant de fichier lus. il y avait un certain nombre de restrictions qui nous poussaient à déclarer le fichier en USROPN et à l'ouvrir et le fermer à chaque utilisation ou bien à placer le programme de service dans un groupe d'activation à part. |
LIKEFILE , définition d'un fichier comme un autre 1/ en spécif F, on récupère tous les attributs de la déclaration de fichier d'origine, type d'ouverture, utilisation de la clé, etc... Attention cela implique QUALIFIED (implicite), donc DS résultat. Fvins IF E DISK Fproducteur LIKEFILE(vins) le GAP cherche à ouvrir les deux fichiers de la même manière, mais doivent quand même être précisé sur le deuxième fichier : - COMMIT qui n'est pas répercuté - USROPN qui n'est pas répercuté - SFILE() pour le nom de la zone rang qui doit être différent - OFLIND qui doit avoir un indicateur différent - EXTIND qui doit utiliser un DS différente enfin EXTFILE, EXTMBR peut être indiqué sur l'une ou l'autre ou les deux déclarations avec les règles suivantes : |
+--------------------------------------------------+----------------------+ ! déclaration de deux fichiers en spécif F ! fichiers ouverts ! +--------------------------------------------------+----------------------+ !Ffic1 IF E DISK ! fic1 ! !Ffic2 LIKEFILE(fic1) ! fic2 ! +--------------------------------------------------+----------------------+ !Ffic1 IF E DISK EXTFILE('bib/fic3') ! fic3 ! !Ffic2 LIKEFILE(fic1) ! fic3 ! +--------------------------------------------------+----------------------+ !Ffic1 IF E DISK ! fic1 ! !Ffic2 LIKEFILE(fic1) ! fic4 ! ! EXTFILE('bib/fic4') ! ! +--------------------------------------------------+----------------------+ !Ffic1 IF E DISK EXTFILE('bib/fic3') ! fic3 ! !Ffic2 LIKEFILE(fic1) ! fic4 ! ! EXTFILE('bib/fic4') ! ! +--------------------------------------------------+----------------------+ !Ffic1 IF E DISK EXTMBR('membreA') ! fic1, membreA ! !Ffic2 LIKEFILE(fic1) ! fic4, membreA ! ! EXTFILE('bib/fic4') ! ! +--------------------------------------------------+----------------------+ |
2/ le mot-clé LIKEFILE peut être indiqué en spécif D, sur un paramètre de procédure, afin de passer un fichier en tant que paramètre le paramètre transmis doit lui même être un fichier déclaré par EXTFILE par un pgm appellant RPG ! (pas de COBOL, ni de C) le fichier référencé peut être déclaré avec TEMPLATE, afin de n'être qu'un modèle.il doit préciser le facteur de groupage par BLOCK() en effet, le facteur de groupage est déterminé par le GAP en fonction des ordres d'entrée/sortie réalisés par le programme. ici le fichier n'étant q'un modèle, le GAP ne peux pas décider du type de groupage, il faut préciser : BLOCK(*YES) le groupage a lieu sauf pour READE/READP/READPE BLOCK(*NO) les enregistrements sont lus un par un. l'ouverture de fichier est passée par référence, elle est commune aux 2. par exemple l'appelant peut lire et l'appelé mettre à jour. |
Exemples : * test de la syntaxe, il n'y a pas d'intérêt particulier pour l'instant H DFTACTGRP(*NO) ACTGRP(*CALLER) ALWNULL(*USRCTL) Fvins UF E K DISK TEMPLATE F QUALIFIED FVIN2 LIKEFILE(VINS) DIN DS likerec(vin2.vins) /free read vin2 in; dow not %eof; ... read vin2 in; enddo; *inlr = *on; /end-free |
* une procédure de mise à jour, qui UPDATE la ligne lue par la procédure * principale, le fichier et la DS, sont passés en paramètre. H DFTACTGRP(*NO) ACTGRP(*CALLER) ALWNULL(*USRCTL) FVINS UF E K DISK TEMPLATE QUALIFIED BLOCK(*NO) FVIN2 LIKEFILE(VINS) F EXTFILE('BDVIN1/VINS') Dds_modele DS likerec(vins.vins) TEMPLATE Dmiseajour PR D parm1 LIKEFILE(VINS) D parm2 LIKEDS(ds_modele) DIN DS LIKEDS(ds_modele) /free read vin2 in; dow not %eof; if in.vin_nom = ' '; miseajour(vin2:in) ; endif; read vin2 in; enddo; *inlr = *on; /end-free |
Pmiseajour B D PI D vin_in LIKEFILE(VINS) D OUT LIKEDS(DS_MODELE) /free eval out.vin_nom = '(non précisé)' ; update vin_in.vins out; /end-free Pmiseajour E la procédure recoit la totalité de l'enregistrement dans OUT la mise à jour doit aussi avoir lieu par le biais de cette DS (il n'y a plus de spécif I et O) Dernier exemple, nous allons placer la procédure "miseajour" dans un programme de service externe. |
Source TESTFIL3F H ALWNULL(*USRCTL) FVINS UF E K DISK TEMPLATE QUALIFIED Source TESTFIL3D Dds_modele DS likerec(vins.vins) TEMPLATE Dmiseajour PR D parm1 LIKEFILE(vins) D parm2 likeds(ds_modele) Source du Programme de service , complié par les commandes : CRTRPGMOD CRTSRVPGM EXPORT(*ALL) H NOMAIN /copy af4test/manip610,testfil3F /copy af4test/manip610,testfil3D pmiseajour B EXPORT D PI D vin_in LIKEFILE(vins) D OUT LIKEDS(DS_MODELE) |
/free eval out.vin_nom = '(non précisé)' ; update vin_in.vins out; /end-free Pmiseajour E Puis le programme compilé par CRTRPGMOD puis CRTPGM / BDNSRVPGM() /copy af4test/manip610,testfil3F FVIN2 LIKEFILE(VINS) EXTFILE('BDVIN1/VINS') /copy af4test/manip610,testfil3D DIN DS LIKEDS(DS_MODELE) /free read vin2 in; dow not %eof; if in.vin_nom = ' '; miseajour(vin2:in) ; endif; read vin2 in; enddo; *inlr = *on; /end-free |