RPG-IV en V5R10 : ° support des classes JAVA ° Nombreuses fonctions intégrées supplémentaires (%LOOKUP, %XLATE ...) ° possibilité de Monitorer les erreurs avec MONITOR / ON-ERROR / ENDMON ° Data structures qualifiées avec QUALIFIED (ce qui permet LIKEDS) ° EXTFILE et EXTMBR pour choix du fichier à l'exécution ° une spécif C en vrai format libre (délimitée par /free , /end-free) ° et diverses modifications mineures |
spécifs C en format libre il s'agit de lignes blanches (sans la lettre C en colonne 6) situées entre /free et /end-free (colonne 7) l'instruction peut être éclatée sur plusieurs lignes (sans caractère + ) la fin de CHAQUE instruction étant marquée par " ; " /free test(E) date ; // commentaire if not %error ; date = date + %DAYS(1) ; nbjours = %DIFF(date : undimanche : *DAYS); joursemaine = %rem(nbjours : 7); if joursemaine < 1; joursemaine = joursemaine + 1; endif; *inlr = *on; endif; return; /end-free |
remarques : les colonnes 6 et 7 DOIVENT être à blanc. si vous copiez une partie de source (/COPY ou /INCLUDE) le source copié est supposé contenir des spécif C en format fixe. si ce n'est pas le cas, le source copié doit contenir lui-même /free et /end-free. le niveau de contrôle n'est pas accessible en format libre : -soit vous codez une spécif C en format fixe, puis vos spécif C en format libre en dessous (tout action doit être conditionnée par IF *inlx ...) -soit vous renvoyez à un sous-programme par une spécif C totale et vous écrivez le sous programme en format libre. les noms de champs peuvent dépasser 14 caractères en format libre. |
pour les ordres EVAL et CALLP, l'ordre est facultatif. semaine = semaine + 1 ; qcmdexc('WRKSPLF' : 7); // Prototype obligatoire !! pour les autres ordres,acceptés en format libre,la règle est la suivante : ordre(option) [facteur1] facteur2 ; CHAIN nocli clientf1 ; READ(N) clientf1 ; les ordres invalides en format libre on été substitués par une fonction intégrée (souvent nouvelle en V5R10) , soit sont considérés comme des ordres devenus obsolètes (MOVE, GOTO, SETON, BITOFF) . vous trouverez ci-dessous les ordres acceptés et refusés en format libre : |
les codes opération suivants peuvent être utilisés en format libre ACQ BEGSR CALLP CHAIN CLEAR CLOSE COMMIT DEALLOC DELETE DOU DOW DSPLY DUMP ELSE ELSEIF* ENDxx ENDSR EVAL EVALR EXCEPT EXFMT EXSR FEOD FOR FORCE IF IN ITER LEAVE LEAVESR MONITOR* NEXT ON-ERROR* OPEN OTHER OUT POST READ READC READE READP READPE REL RESET RETURN ROLLBK SELECT SETGT SETLL SORTA TEST UNLOCK UPDATE WHEN WRITE * indique un ordre nouveau en V5R10 |
les codes opération suivants NE supportent PAS le format libre : ADD ADDDUR ALLOC ANDxx BITOFF BITON CABxx CALL CALLB CAS CAT CHECK CHECKR COMP DEFINE DIV DO DOUxx DOWxx END EXTRCT GOTO IFxx KFLD KLIST LOOKUP MHHZO MHLZO MLHZO MLLZO MOVE MOVEL MULT MVR OCCUR ORxx PARM PLIST REALLOC SCAN SETOFF SETON SHTDN SQRT SUB SUBDR SUBST TAG TESTB TESTN TESTZ TIME WHENxx XFOOT XLATE Z-ADD Z-SUB Pour la plupart d'entre eux, vous trouverez un service équivalent sous forme d'une fonction intégrée (%LOOKUP , %CHECK) sauf les déclarations (KLIST, PLIST etc...) qui restent en format fixe. |
Exemple: rechercher DBGVIEW et ajouter ou remplacer par DBGVIEW(*SOURCE) -------------------------------------------------------------------------- c *entry plist c parm param c parm nouvelle_cmd c parm nouvelle_lg /free if modif_ok ; command_string = %SUBST(param : offset + 1 : lg); pos = %scan('DBGVIEW' : command_string); if pos = 0; nouvelle_cmd = %trim(command_string) + ' DBGVIEW(*SOURCE)'; else; nouvelle_cmd = %replace('DBGVIEW(*SOURCE) ' : command_string : pos : %scan(' ' : command_string : pos) - p ; endif; nouvelle_lg = %len(%trim(nouvelle_cmd)); endif; *inlr = *on; /end-free |
Nouvelles fonctions intégrées : %DAYS(n) convertit un entier en nombre de jours (durée) ainsi que : %YEARS , %MONTHS , %HOURS , %MINUTES , %SECONDS et %MSECONDS ce qui permet les calculs de date en format libre : plustard = maintenant - %DAYS(45) + %MONTHS(nbm) ; %DIFF(date2 : date1 : *code) retourne l'écart qui sépare deux dates ecart_en_mois = %diff(datliv : datcmd : *MONTHS) ; %DATE(chaine : *code) convertit en date, une zone caractère ou numérique. date = %DATE('16/08/01' *DMY) ; (sans argument, retourne aujourd'hui) |
ainsi que les fonctions %TIME et %TIMESTAMP qui convertissent une zone (chaine ou numérique) respectivement en heure et horodatage. ou bien retourne l'heure ou l'horodatage en cours... .... %SUBDT(date1 : *code) extrait une partie d'une date, d'une heure ou d'un horodatage. jour = %SUBDT(datcrt : *D) ; %CHECK(chaîne:variable[:debut]) vérifie que tous les caractères de "variable" sont bien l'un des caractères indiqués dans "chaîne". "debut" indique le début de recherche dans variable (dft = 1) invalide = %CHECK('0123456789' : qte); //ne contient que des chiffres? if invalide > 0 ; // si non (invalide est positif) |
%CHECKR(chaîne:variable[:debut]) idem %CHECK, mais la recherche commence par la droite. %LOOKUP(arg : tableau [:départ {:nombremaxi}] recherche si l'un des éléments de "tableau" est égal à "arg". si oui, la position est retournée, sinon 0. la recherche commence à "départ" et se poursuit pendant "nombremaxi" postes la recherche est réalisée par égalité stricte. %LOOKUPGE , %LOOKUPGT , %LOOKUPLE , %LOOKUPLT idem à %LOOKUP mais la recherche est faite par supériorité ou égalité, supériorité , infériorité ou égalité, infériorité stricte. ne fonctionne qu'avec des tableaux triés. |
%TLOOKUP(arg : table [:table-alternée] ) recherche dans un table %TLOOKUPGE , %TLOOKUPGT , %TLOOKUPLE , %TLOOKUPLT idem %TLOOKUP, mais avec un critère autre que l'égalité. %XLATE(de : a : chaine [:debut]) convertit chaine en remplacant chaque caractère se trouvant dans "de" par le caractère de même position dans "a". la transformation commence à "debut". Dmin C 'abcdefghijklmnopqrstuvwxyz' DMAJ C 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' nouveau = %XLATE(min : MAJ : Adresse); |
%ALLOC(nb) fournit un pointeur vers un nouvel espace mémoire. "nb" indique la taille souhaitée en octets. %REALLOC(ptr : nb) fournit un pointeur vers un nouvel espace mémoire plus grand, dans lequel les données pointées par "ptr" ont été copiées. "nb" indique toujours l'espace souhaité. %OCCUR(nom-de-ds) permet de manipuler les occurences d'une DS à occurences multiples x = %OCCUR(DS) ; // retrouve l'occurence en cours %OCCUR(DS1) = 1 ; // positionne sur l'occurence 1 |
%SHTDN indique si le système est en train de s'arrèter (arrêt controlé) if %SHTDN; %SQRT(nombre) fournit la racine carrèe. si nombre est en virgule flottante, le résultat l'est aussi, sinon il est en numérique packé. ces nouvelles fonctions viennent donc remplacer les codes opération : ADDDUR (%DAYS, %MONTHS, etc...) SUBDUR (%DIFF) EXTRCT (%SUBDT) ALLOC REALLOC, LOOKUP , CHECK/CHECKR XLATE* LOOKUP SHTDN SQRT .......................................................................... |
. code op. : solution de remplacement en format libre. : .........................................................................: : ADD : opérateur + : : ADDDUR : opérateur + avec %YEARS, %DAYS, %MINUTES, etc... : : ALLOC : %ALLOC : : ANDxx : opérateur AND : : BITOFF,BITON: (pas d'équivalent) : : CABxx : (pas d'équivalent) : : CALL, CALLB : CALLP : : CASxx : SELECT avec EXSR : : CAT : opérateur + (entre deux chaînes) : : CHECK : %CHECK : : CHECKR : %CHECKR : : COMP : IF ... : : DEFINE : Spécif D : : DIV : opérateur / ou %DIV() : : DO : FOR i =1 to 10... : : DOUxx, DOWxx: DOU et DOW en format libre : : END : ENDIF, ENDDO etc. : : EXTRCT : %SUBDT : .........................................................................: .......................................................................... |
. code op. : solution de remplacement en format libre. : .......................................................................... : GOTO : (pas d'équivalent) : : IFxx : IF A <> 10 : : LOOKUP : %LOOKUP, %LOOKUPxx (tableaux) %TLOOKUP, %TLOOKUPxx (TAB): : MOVE : EVALR ou EVAL : : MOVEA : EVAL : : MOVEL : EVAL : : MULT : opérateur * : : MVR : %REM : : MxxZO : (pas d'équivalent) : : OCCUR : %OCCUR : : ORxx : opérateur OR : : PARM : Spécif D (sauf *ENTRY) : : PLIST : (idem) : : REALLOC : %REALLOC : : SCAN : %SCAN : : SETOFF,SETON: EVAL : : SHTDN : %SHTDN : : SQRT : %SQRT : :........................................................................: .......................................................................... |
. code op. : solution de remplacement en format libre. : :........................................................................: : SUB : opérateur - : : SUBDUR : opérateur - avec %YEARS, %DAYS, %MINUTES : : SUBST : %SUBST : : TAG : (pas d'équivalent) : : TESTB : (pas d'équivalent) : : TESTN : (pas d'équivalent) : : TESTZ : (pas d'équivalent) : : TIME : %DATE, %TIME and %TIMESTAMP : : WHENxx : WHEN a = B : : XFOOT : %XFOOT : : XLATE : %XLATE : : Z-ADD,Z-SUB : EVAL : :........................................................................: pour tout ce qui est Move,Movel Seton,Setoff, n'utilisez plus d'ordre : [*inlr = *on ; CPT = CPT + 1; etc...] les ordres suivant sont à abandonner de toutes facons : SETON, SETOFF (ainsi que l'emploi des indicateurs), BITON, BITOFF, TESTB. ainsi que GOTO, CABxx et TAG bien sûr! |
EXTFILE, EXTMBR mot-clés en spécif F permettant de fournir le nom réel du fichier en traitement (évite des OVRDBF). EXTFILE(nom) le nom peut être une constante ou une variable (nom simple ou qualifié) si le fichier est ouvert par le RPG, la variable soit alors être renseignée : - soit par le mot-clé INZ (en spécif D) - soit être un paramètre recu. - soit une variable globale sinon, le fichier doit être ouvert par le pgm (USROPN) EXTMBR(nom-du-membre ou *FIRST ou *ALL) *FIRST et *ALL doivent être indiqués en quotes ('*FIRST') |
dans les deux cas si un OVRDBF est actif, l'ouverture par le RPG en subira les effets. soit une spécif F : Fentree if E disk EXTFILE(nouveau) USROPN /free nouveau = 'QTEMP/MONFICHIER' ; open entree; ... le fichier ouvert sera MONFICHIER dans QTEMP si la commande OVRDBF MONFICHIER TOFILE(TOTO) a été lancée, le fichier ouvert sera TOTO. nb: si une commande OVRDBF ENTREE TOFILE(TRUC) est active elle sera ignorée le RPG cherchant à ouvrir MONFICHIER et non ENTREE. ("entree" est le nom dans le pgm uniquement) DS qualifiée : |
le mot-clé QUALIFIED asscié à une définition de DS autorise la manipulation des sous-zones sous la forme : nomDS.nomdezone ce qui permet d'avoir un champs définit dans deux DS différentes. ATTENTION, c'est considéré par RPG COMME DEUX CHAMPS DISTINCTS. Dds1 DS QUALIFIED D zone1 5 D zone2 3 ds1.zone1 = *blank; cela permet aussi de définir deux fois la même DS avec LIKEDS Dds2 LIKEDS(ds1) ds2.zone1 = *all'X' ; |
les deux DS sont automatiquement qualifiées. seule la structure de la DS est dupliquée. les mot-clés OCCUR, INZ, NOOPT ne le sont pas. encore une fois ce sont deux espaces mémoire différents ne contenant pas les mêmes valeurs. vous pouvez préciser sur la deuxième DS : INZ(*likeds) le mot-clé LIKEDS est très pratique pour un passage de DS en tant que paramètre dans les procédures : déclarez la DS en tant que variable globale (spécif D hors procédure) puis utilisez LIKEDS dans l'interface de procédure (spécif D, PI) et dans les paramètres recus par la procédure (spécif D, PR) |
nouvelle gestion des erreurs : MONITOR / ENDMON il s'agit de définir un groupe d'instructions devant être monitorées. si une erreur survient, le contrôle est transmis au premier ON-ERROR, si tout se passe normalement, on saute à l'instruction qui suit le ENDMON. ON-ERROR n° | ou n°1 : n°2 : n°3 | ou *FILE, *PROGRAM , *ALL gère une erreur spécifique ou une série d'erreurs dans un bloque MONITOR. les erreurs sont gérées dans l'ordre d'écriture, vous devez donc écrire du plus spécifique (une seule erreur) au plus large (*ALL), comme les MONMSG du CL. si une erreur survient pendant le traitement du code associé à un ordre on-error, l'erreur elle même n'est pas gérée (risque de boucle) |
vous pouvez préciser un ordre MONITOR dans un ordre ON-ERROR, pour éviter cela. vous pouvez imbriquer les ordres MONITOR, il seront examinés dans l'ordre. MONITOR ; chain nocli clientf1 ; if %found ; chaine = %subst(tbl(x) : %scan('*' : tbl(x) + 1) endif; on-error 1211 ; // fichier non ouvert ... on-error *FILE ; // autres erreurs fichier ... on error 00100:00121 ; // erreur de chaîne ou d'indice .... on-error *ALL ; // autres erreurs (MONMSG CPF0000) ... ENDMON; |
divers : -------- nouvel ordre ELSEIF :place directment un IF dans un ELSE avec un seul ENDIF IF condition1 ; ELSEIF condition2 ; ELSEIF condition3 ; ELSE ; ENDIF; OFLIND [indicateur d'overflow pour les PRTF] admet maintenant un indicateur nommé (défini de type N en spécif D) PREFIX [spécif F], peut se terminer par un point (.) /INCLUDE vient compléter /COPY en ce sens qu'il est exécuté APRES l'appel au pré-compilateur SQL (et avant le compilateur RPG, bien sur). |