Cette évolution est apportée par une PTF (SI51094)
Cette mise à jour apporte un format libre complet : plus de spécifications H, F, D et P.
Plus besoin de /free /end-free, les colonnes 6 et 7 à blanc suffisent.
on peut mixer (est-ce une bonne pratique ?) :
read fichier; C MOVEA *ALL'0' *IN exfmt ecran; IF *in03; ..... |
Donc les colonnes 6 et 7, sont encore réservées :
Regardons les différentes étapes, dans l'ordre d'écriture
:
ctl-opt OPTION(*NODEBUGIO : *SRCSTMT) ALWNULL(*USRCTL) ; |
ctl-opt OPTION(*NODEBUGIO : *SRCSTMT) |
Type | Ajout | Opérations admises |
I | Lecture | |
I | A | Lecture/écriture |
U | Lecture/mise à jour/suppression (la ligne lue est verrouillé) |
|
U | A | Toute opération (lecture avec verrouillage) |
O | écriture | |
C | lecture/écriture (EXFMT) |
C'est une notion importante en RPG Tout les champs ayant le même nom, sont stockés au même espace mémoire (mémoire GAP) lors de la lecture (spécif I implicites) Donc la lecture du fichier commande possédant NOCLI, peut effacer la valeur actuelle de NOCLI telle que vous l'avez reçue du fichier clients si la zone s'appelle pareil dans le programme ! |
DCL-F FICHIER1 KEYED ; // Fichier BdeD en lecture par clé |
// associe à un fichier avec INDARA, une DS contenant des variables // indicateurs (IND).Cette DS est utilisée A LA PLACE de *IN DCL-F ECRAN WORKSTN INDDS(indic); DCL-DS Indic LEN(99); sortie ind pos(3); retour ind pos(12); sflclr ind pos(40); END-DS; //en code : if not sortie; sflcrl = *ON; ... |
Type | remarque | équivalent D | paramètres |
BINDEC | binaire "décimal" | B | Bindec(lg [:décimales]) |
CHAR | alphanumérique | A | Char(lg, max 16 Mo) |
DATE | date | D | Date(format [séparateur]) |
FLOAT | notation scientifique | F | Float(lg) |
GRAPH | DBCS | G | Graph(lg) |
IND | Indicateur (booléen) | N | |
INT | Binaire (compatible C et API) | I | Int(lg -> 3 ,5 10 ou 20) |
OBJECT | pour Java (JNI) | O | Object(*JAVA : classe) |
PACKED | numérique packé | P | Packed(lg, max 30[:décimales]) |
POINTER | pointeur | * | [*PROC] |
TIME | heure | T | Time(format [:séparateur]) |
TIMESTAMP | horodatage | Z | (nb de décimales depuis 7.2-> 0 à 12) |
UCS2 | Unicode | C | UCS2(lg) |
UNS | binaire non signé | U | Uns(lg) |
VARCHAR | Alphanumérique à taille variable | A + VARYING | Varchar(lg) |
VARGRAPH | DBCS à taille variable | G + VARYING | Vargraph(lg) |
VARUCS2 | Unicode à taille variable | C + VARYING | Varucs2(lg) |
ZONED | Numérique étendu | S | Zoned(lg[:décimales]) |
DCL-S compteur INT(5); DCL-S flag IND; DCL-S message CHAR(30); |
DCL-S DEVISE CHAR(1) DIM(15); |
2 possibilités pour les déclarer DIM(*AUTO:nbmax) ou DIM(*VAR:nbmax)
DIM(*AUTO:nbmax)
nbmax postes au maximum (ici nbmax)
La dimension du tableau s'incrémente au fur et à mesure des affectations dans les postes par nom-tableau(*NEXT)
DIM(*VAR:nbmax)
nbmax postes au maximum (ici nbmax)
La dimension doit être définie explicitement par la BIF %elem(nombre de postes) pour pouvoir affecter des valeurs dans les postes
Restrictions sur les tableaux à dimension variable
- Ne peut être que pour un tableau autonome, ou une DS de type tableau
- Ne peut pas être utilisé dans des spécif. C
tbcepage = %LIST('Syrah' : 'carbernet' : 'grenache); // 3 postes |
Ancienne version | nouvelle version |
DCL-DS Clients QUALIFIED; id INT(10); nom VARCHAR(50); ville VARCHAR(50); cdes LIKEDS(cde_template) DIM(100); nbcdes INT(10); END-DS Clients; |
DCL-DS nom-de-ds EXT EXTNAME('MAREFERENCE') END-DS;
DCL-DS nom-de-ds LIKEDS(autreds) ;
remarquez qu'il n'y a pas de END-DS avec LIKEDS et LIKEREC.
- DCL-SUBF quand la sous-zone porte le même nom qu'une instruction RPG (Select par exemple)
- Les mots-clés sont en partie les mêmes que sur la spécif D, excepté :
- OVERLAY où il n'est plus admis de faire référence à la DS, utiliser POS à la place
// exemple INFDS DCL-F fichier DISK(*EXT) INFDS(fichierInfo); DCL-DS fichierInfo; msgid CHAR(7) POS(46); END-DS; DCL-F ecran WORKSTN; |
Les déclarations de fichiers et de variables peuvent être mélangées !
DCL-DS client; |
Indique qu'une sous-zone démarre à la même position qu'une autre
Peut la recouvrir même si elle est plus longue ce qui n'est pas possible avec OVERLAY
sorte de variable, externe au programme, il en existe deux types : |
DCL-DS client qualified; |
DCL-DS AdresseMDL ADR1 CHAR(25); ADR2 CHAR(30); CEDEX CHAR(15); END-DS; |
DCL-DS DSmodele QUALIFIED TEMPLATE; |
DCL-DS article QUALIFIED DIM(20); |
dcl-ds ds_dep TEMPLATE; |
|
! RPG-III ! signification ! commentaires !---------!--------------------!-------------------------------------------------- ! ! ! ! 6 ! C ! ! ! ! ! 7-8 ! Niveau de contrôle ! Lx (Cycle) ! ! ou ! ! ! Continuation ! AN/OR ! ! ! ! 9-17 ! Conditions ! NxxNxxNxx (un indicateur = une condition) ! ! ! ! 18-27 ! Facteur 1 ! les noms sont limités à 6c, les constantes à 10. ! ! ! ! 28-32 ! Code opération ! L'ordre ! ! ! ! 33-42 ! Facteur 2 ! Toujours 10 positions. ! ! ! ! 43-48 ! zone résultat ! la limite de 6c. est là ! ! ! ! 49-51 ! longueur ! Définition de la zone résultat ! 52 ! nbr de décimales ! ! ! ! ! 53 ! options ! H=Arrondi, N=Nolock (lecture sans verrouillage) ! ! ! ! 54-59 ! indics résultants ! >><<== !---------!--------------------!--------------------------------------------------- |
EN RPG IV (transition GAP3 -> GAP4)
Même logique, les colonnes sont plus larges (nom de zones sur 10c. et non 6)
! RPG-IV ! signification ! commentaires !---------!--------------------!----------------------------------------------- ! ! ! ! 6 ! C ! ! ! ! ! 7-8 ! Niveau de contrôle ! Lx (Cycle) ! ! ou ! ! ! Continuation ! AN/OR ! ! ! ! 9-11 ! Conditions ! Nxx (un indicateur = une condition) ! ! ! ! 19-25 ! Facteur 1 ! les noms sont à 14 position maxi ! ! ! dans cette spécif C ! ! ! ! 26-35 ! Code opération(O) ! Options possibles : ! ! ! (H) arrondi ! ! ! (N) Read with no lock ! ! ! (D) manipulation d'une date,(T) une heure ! ! ! (Z) " d'un horodatage. |
Codes opérations élémentaires : | remarques | CL0N01Factor1+++++++Opcode&ExtFactor2+++++++Result++++++++Len++D+HiLoEq A ADD B C | C = A + B | (si A est omis : C = C + B | | A SUB B C | C = A - B A MULT B C | C = A * B A DIV B C | C = A / B MVR D | reste dans D | MOVE X Y | ALPHA uniquement (conseillé), sans mise à blanc, cadrage à DROITE | MOVEL X Y | move LEFT | Z-ADD 0 N | N = 0 NUMERIQUE uniquement | Z-SUB 1 N | N = -1 | |
Facteur 2 étendu (V3R10/1995)
Format libre (V5R10/2001)
Pour les ordres historiques acceptés en format libre,
|
EN 2015 (TR3) avec **FREE, on peut commencer colonne 1
// deux ordres identiques eval machaine = 'Bonjour'; |
Chaînes et tableaux
machaine = 'Bonjour'; Bon = %SUBST(machaine : 1 : 3) ; |
DCL-S DEVISE CHAR(1) DIM(15); |
dcl-ds ds_dep TEMPLATE; |
Depuis la 7.4, lorsque cette fonction s'applique à un tableau à taille variable déclaré avec DIM(*AUTO ou *VAR)
- Elle peut être aussi cible d'une valeur.
- Comme cible d'une valeur cette fonction permet de modifier le nombre actuel de postes du tableau
- %ELEM(montableau) = Nouveau_nombre_de_postes;
- Elle admet un deuxième argument en paramètre
- Comme cible
- Avec l'argument *ALLOC, le nombre de postes alloués sera modifié, si la nouvelle valeur est plus grande que celle en cours
%elem(montableau:*ALLOC) = Nbpostes
- Avec l'argument *KEEP, les éléments renseignés jusqu'à l'indice indiqué seront conservés lors de la diminution puis agrandissement
- Sans argument *KEEP, lors de la réatribution de la taille du tableau, les éléments seront initialisés
%elem(montableau:*KEEP) = Nbpostesdont le contenu est conservé
- Comme source
- Avec l'argument *ALLOC, retourne le nombre de postes actuellement alloués d'un tableau dynamique
Nbpostes = %elem(montableau:*ALLOC)
- Avec l'argument *MAX, retourne la dimension maximale d'un tableau dynamique
NbpostesMax = %elem(montableau:*MAX)
%LOOKUP (RPG) , LOOKUP(GAP)
pos = %lookup('$' : devise); |
DCL-DS TBDEVISE QUALIFIED DIM(15); DEVISE CHAR(1); TAUX PACKED(5 , 2); END-DS |
Structuration
DOU | DOW |
Condition pour arrêter | Condition pour faire |
Dou (meteo = 'Pluie') | Dow (meteo = 'Beau') |
On fait au moins une fois (en fait le test est sur ENDDO) |
On peut faire 0 fois |
GAP III | RPG 4 |
DO | FOR |
C DO 10 I |
FOR i=1 to 10 by 2; |
faire 10 fois en variant i , par pas de 2 | faire 10 fois en variant i par pas de 2 |
Entrées/Sorties
- Tous ces ordres possèdent un paramètre supplémentaire : UneDS
- Cela permet de placer les données lues dans une DS ou de lire les données à écrire depuis une DS
- C'est obligatoire pour les fichiers déclarés dans une procédure, pour lesquels il n'y a plus de spécif. I et O.
- C'est facultatif pour les autres, les spécif. I et O placent automatiquement les données lues dans des variables de même nom
- Tous ces ordres peuvent générer une erreur
- en spécif C interceptée par un indicateur dans la colonne << (celle du mlieu)
- en format libre, mettre l'option (E) et tester IF %Error()
- fichier vs format
- Tous les ordres de lecture acceptent nom-fichier ou nom-format
- Les ordres de sortie (WRITE/UPDATE, ...) n'acceptent qu'un nom de format
Sauf à utiliser USROPN (UC en GAPIII), les fichiers sont ouverts en début de pgm, fermés en fin.
- Avec USROPN :
- OPEN fichier
- CLOSE fichier
- READ fichier
- lecture séquentielle du premier au dernier
- en fin de fichier, déclenche %EOF (ou indicateur == en spécif C)
- READP fichier
- lecture séquentielle du dernier au premier
- en début de fichier, déclenche %EOF (ou indicateur == en spécif C)
- CHAIN critère fichier (en GAPIII : critère CHAIN fichier)
- Accès direct à une ligne du fichier
- En cas de lecture aboutie, déclenche %FOUND
- Critères possibles
- N° de rang (si KEYED absent)
- une clé
- nom de zone simple
si plusieurs lignes correspondent, seule la première est lue- une clé composée
- Historiquement définition des clés par KLIST
- Aujourd'hui (freeForm)
CHAIN (societe : nocli) fichier ;
SETLL critère fichier
- positionnement par égalité ou, à défaut, par supériorité
- SETGT critère fichier
- positionnement par supériorité
- en Spécif C
- == indique un positionnement par égalité (%EQUAL)
- >> indique un non positionnement (not %FOUND)
- Soit le fichier
rang clé 1 A1 2 A2 3 B2 4 C1 5 C1 6 D1
SETLL SETGT clé rang est vrai (*ON) rang est vrai (*ON) A1 1 %EQUAL() ou == 2 %FOUND() A2 2 %EQUAL() ou == 3 %FOUND() A3 3 %FOUND() 3 %FOUND() C1 4 %EQUAL ou == 6 %FOUND() FF not %FOUND() ou >> not %FOUND() ou >>
- READE critère fichier
- lit l'enregistrement suivant s'il a la même clé (suite à SETLL par ex.), %EOF sinon.
- READPE critère fichier
- lit l'enregistrement précédent s'il a la bonne clé (suite à SETGT par ex.), %EOF sinon.
- UNLOCK fichier
- déverrouille (libère) le dernier enregistrement lu
Les enregistrements sont verrouillés lors d'une lecture d'un fichier en *UPDATE
si la lecture ne peut pas avoir lieu --> %ERROR()
et déverrouillés lors d'une mise à jour UPDATE /DELETE, au pire lors du CLOSE
- CLEAR [*NOKEY] format
- met à blanc la totalité du format (*NOKEY : sauf les zones clés)
- WRITE format
- écriture d'une nouvelle ligne
- DELETE format
- suppression de la dernière ligne lue
- UPDATE format
- mise à jour de la dernière ligne lue (toutes les zones)
- UPDATE format %FIELDS(zone1 : zone2 : ...)
- Mise à jour de certaines zones uniquement
- COMMIT
- validation des actions base de données précédentes
- le fichier doit avoir été déclaré avec le mot-clé COMMIT
- la commande STRCMTCTL doit avoir été passée
- ROLBK
- Invalidation des actions base de données précédentes
- mêmes pré-requis que COMMIT
- EXFMT
- affichage puis lecture d'un format de DSPF
- READC
- lecture séquentielle des lignes modifiées dans un sous-fichier (DSPF)
Coder en format libre
- Codes Opération en format libre
Code |
Exemple |
EVAL (evalr) |
eval(H) montant = (qte * prix) * (1 + (tva /100) ); |
IF | if *in30; |
DOU | Dou %EOF; |
DOW | Dow not *in03 and not *in12; |
SELECT |
SELECT ; |
FOR | FOR i = 1 to 15 ; |
CALLP | callp QCMDEXC('wrksplf' : 7)// nécessite un prototype via DCL-PR (CALLP facultatif) |
----------- | format libre V5 |
BEGSR/ ENDSR |
BEGSR toto; |
CHAIN | CHAIN(N) nocli clientf1 ; |
CLEAR | Clear *nokey clientf1; // remise à blanc de clientf1 sauf les clés |
CLOSE | Close clientp1; |
COMMIT | Commit; // validation de la dernière transaction |
DELETE | delete clientf1; |
DSPLY | dsply 'voulez-vous continuer ?' 'QSYSOPR' rep; |
EVAL-CORR |
eval-CORR DS1 = DS2; // toutes les zones de même nom sont copiées. |
ELSE | if a = B; |
ELSEIF | if a = B; |
EXFMT | Exfmt image; |
EXSR | Exsr monsouspro; // exécute monsouspro |
FEOD | FEOD entcdep1 ; // force écriture physique dans entcdep1 |
FOR-EACH | FOR-EACH wcep IN %list('Syrah' : 'grenache' : 'carignan'); |
IN | IN *lock dataarea ; // lecture d'une data aréa (avec verrou) |
ITER | iter; // (saute un tour de boucle (dans un FOR par exemple) |
LEAVE | leave; // (sortie anticipée d'une boucle) |
LEAVESR | leavesr; // (sortie anticipée d'un sous programme) |
MONITOR | Monitor; // (démarre un groupe d'instructions sous contrôle) |
ON-ERROR | Monitor; |
OPEN | OPEN CLientp1; |
OUT | OUT dataarea; // mise à jour d'une data -area |
POST |
Post Ecran01; // met à jour l'INFDS d'Ecran01 |
READ/readp |
dow not %eof; |
READE/ |
READe nocde detdcep1; //lecture du suivant si la clé égale nocde. |
READC |
READC FE; // lecture séquentielle des lignes modifiés dans sous fichier FE. |
RESET |
RESET datastructure; // réattribut les valeurs initiales. [INZ( ).] |
RETURN |
return: // sortie anticipée d'un programme |
ROLBK | rolbk; // annulation de la dernière transaction |
SETLL/setgt |
SETLL nocli entcdef1; // se positionne sur la première commande |
SORTA |
Sorta tbldestva ;//(tri le tableau, avant la V7, il doit être déclaré ASCEND/DESCEND) |
SORTA (A | D) |
SORTA(D) clientDS(*).depart; //Depuis la V7, compatible avec DS qualifiées et le critère de tri peut être dynamique |
TEST(E |
test(ed) *ISO datechar; // test DATECHAR avant conversion. |
UNLOCK |
if *in12 ; |
UPDATE |
else ; |
WRITE |
write clientf1; // ajout d 'un nouveau client. |
XML-INTO |
xml-into DS1 %xml(data); // lecture XML et placement dans DS1. |
Pour le type SQLRPGLE
EXEC SQL |
EXEC SQL |
Options pour les codes opération
Code |
Exemple |
(H) | réalisation d'un arrondi lors de l'opération. |
(N) | lecture sans verrouillage. |
(M) | pour un calcul, travailler avec une précision maxi (un seul arrondi en fin d'opération). |
(R) | pour un calcul, travailler avec la même précision que la variable résultat (arrondi à chaque opération). |
(E) | Erreur gérée (pour tous les ordres avec indicateur en <<). |
(D | T | Z) | pour TEST (date, heure, horodatage). |
(A | D) | pour SORTA (V7R1), indique dynamiquement le critère de tri. |
Fonctions intégrées
Fonction(x) |
Retourne |
Exemple |
%ADDR | l'adresse d'une variable | EVAL prt= %addr(data) |
%ELEM | donne le nombre d'occurrences d'un tableau ou d'une DS | if I < %elem(tbl_tva) |
%SUBST | extraction d'une chaîne de caractère | if %subst(raisoc : 1 : 1) <> ' ' |
%SIZE | donne la longueur déclarée d'une variable | if %SUBST(nom : %size(nom): 1) = *blank |
%DECPOS | donne le nombre de décimales | |
%TRIM | élimination des espaces d'extrémité | eval NP = %trim(nom) + ' ' + %trim(prenom) |
%TRIML|%TRIMR | élimination des blancs de gauche/de droite | |
%PARMS | indique le nombre de paramètres recus | if %parms > 2 |
%ABS | valeur absolue | |
%DEC %DECH |
transforme une suite de chiffres ou une date en numérique packé |
eval DATAMJ = %dec(DATCDE : *YMD) |
%INT %INTH |
transforme une valeur numérique
ou caractère au format binaire signé |
|
%UNS %UNSH |
transforme une valeur numérique
ou caractère au format binaire non signé |
|
%FLOAT |
transforme une valeur numérique ou caractère au format virgule flottante (scientifique) | |
%EDITFLT |
transforme de virgule flottante vers chaîne | |
%EDITC |
transforme du numérique en chaine avec
application d'un Edit code (comme EDTCDE DDS) |
eval msg = 'date de traitement' + |
%EDITW |
idem %EDITC mais avec un mot d'édition (EDTWRD) | |
%CHAR | transforme date ou numérique en chaîne | ZoneChar=%CHAR(ZoneDec) // 000123,45- ==> '-123,45' |
%STR | transforme une chaine RPG en chaîne compatible C (pointeur vers une chaine terminée par x'00' ) |
|
%LEN |
retourne la longueur d'une expression | if %len(%trim(nom)) > 2 eval L = %len(zone-variable) |
%SCAN |
recherche position d'une chaîne de caractères | eval chaine = 'ILE/RPG-IV' |
%REPLACE | remplace par une chaîne l'information située à la position indiquée | //var1 = 'AS/400' |
%NULLIND |
test la valeur nulle sur un champ base de données | IF %NULLIND(datcmd) = *ON |
%OPEN |
indique si un fichier est ouvert | if %open(clients) |
%EOF |
indique si l'on est fin de fichier | dow not %eof(clients) |
%ERROR |
indique si on est en erreur (à utiliser suite à un code avec option (E).) |
if %error |
%STATUS |
indique le n° d'erreur (code status) | if %error and %status(clients) = 1252 |
%EQUAL |
indique un positionnement par égalité (SETLL) |
|
%FOUND |
indique un positionnement réalisé(SETLL,SETGT) une recherche aboutie (CHAIN) |
|
---- V4R40 ---- |
||
%GRAPH |
conversion en DBCS | |
%UCS2 |
conversion en UNICODE | |
%XFOOT |
somme d'un tableau | eval total = %xfoot(tb_salaire) + prime |
%DIV |
résultat de la division (entiers uniquement) | |
%REM |
reste de la division (entiers uniquement) | if %rem(an : 4 )= 0 |
---- V5R10 ---- |
||
%CHECK | la position du premier caractère invalide (0 si tous sont OK) | Eval pos = %check('0123456789.' : variable) |
%CHECKR | Idem %CHECK, mais droite-> gauche. | |
%DATE | convertit une variable (alpha ou dec) en date ou, sans argument, retourne la date du jour. | eval datcmd = %DATE(datchar : *YMD0)//(c'est un zéro) |
%DAYS | indique un nombre de jours dans un calcul | eval datliv = datcmd + %DAYS(15) |
%DIFF | exprime un écart entre deux dates ou deux heures | eval ecart = %DIFF(datliv : datcmd : *DAYS) |
%SUBDT | extrait une partie d'une date | eval annee = %SUBDT(datliv : *YEARS) |
%HOURS | exprime un nombre d'heures dans un calcul | eval demain = maintenant + %hours(18) |
%LOOKUP |
indique si un élément est présent dans un tableau | eval pos = %lookup('$' : monnaies) |
%MINUTES | exprime un nombre de minutes dans un calcul | voir %HOURS() |
%MONTHS | exprime un nombre de mois dans un calcul | voir %DAYS() |
%MSECONDS | exprime un nombre de microsecondes dans un calcul |
voir %HOURS |
%SECONDS |
exprime un nombre de secondes dans un calcul | voir %HOURS() |
%SHTDN |
indique si le JOB ou le système est en phase d'arrêt | if %SHTDN |
%TIME |
convertit une variable (alpha ou dec) en heure ou, sans argument, retourne l'heure en cours. | if %time(pointage : *HMS) = T'23:59:59' |
%XLATE | transforme une variable aphanumérique | eval resultat = %XLATE('abcdef' : 'ABCDEF' : origine) |
%YEARS | exprime un nombre d'années dans un calcul | voir %DAYS |
---- V5R20 ---- |
||
%KDS | Utilisation d'une DS en tant que liste de clés sur un CHAIN. | CHAIN %KDS(dscli) clientf1; |
%FIELDS | Mise à jour d'une liste finie de zones lors d'un UPDATE . | Update clientf1 %FIELDS(nomcli : depcli : ville) ; |
%BITNOT | inverse les bits | %BITNOT(x'00') = x'FF' |
%BITOR | applique un OU logique bit à bit | %BITOR(x'F0' : x'0F') = x'FF' |
%BITAND | applique un ET logique bit à bit | %BITAND(x'F1' : x'1F') = x'11' |
%BITXOR | applique un OU exclusif bit à bit | %BITXOR(x'F1' : x'1F') = x'EE' [1110 1110) |
---- V5R30 ---- |
||
%SUBARR | une partie d'un tableau | resultat = %xfoot( %subarr(tbl : i : 5) )// 5 postes |
---- V5R40 ---- |
||
%XML | coordonnées des données XML à lire (cf XML-INTO) | xml-into DS1 %xml(data) // parse data pour placement dans DS1 |
---- V7R10 ---- |
||
%LOOKUP |
indique si un élément est présent dans une DS à dimension | pos = %lookup(44 : clientDS(*).depart ); |
%SCANRPL | recherche et remplace une chaîne | eval resultat = %SCANRPL('GAP' : 'RPG' : origine) |
%PARMNUM | retourne la position d'un paramètre | if %parms > %parmnum(nocli) // nocli transmis ? |
---- V7R30 ---- |
||
%SCANR |
comme %scan mais dans le sens droite vers gauche | eval chaine = 'ILE/RPG-IV' |
%MAX |
Retourne la plus grande valeur (TR2) | maxi = %max(priha: prirv: privente); |
%MIN |
Retourne la plus petite valeur (TR2) | datecheance = %min(datliv : datfac) + %days(60); |
%PROC |
Retourne le pgm ou la procédure en cours (TR3) | monpgm = %proc(); |
---- V7R40 ---- | ||
%ELEM | nombre d'occurrences d'un tableau ou d'une DS à taille variable admet un deuxième paramètre | Cible avec 1 seul paramètre: %ELEM(montableau) = Nouveau nombre de postes Cible avec 2 paramètres %ELEM(montableau:*ALLOC) = nombre de poste alloués %ELEM(montableau:*KEEP) = nombre de postes dont le contenu est conservé |
Source Nombre de postes alloués = %ELEM(montableau:*ALLOC) Nombre de postes max = %ELEM(montableau:*MAX) |
||
%LIST |
considère une série de valeurs comme un tableau (TR9) | tbcepage = %list('Syrah' : 'grenache' : 'carignan') |
%RANGE |
avec opérateur IN , pour tester une plage de valeurs (TR9) | if caractere in %range('a' : 'z') |
%LOWER et %UPPER |
Conversion en minuscule ou majuscule (7.3 TR10 / 7.4 TR4) | min = %lower( 'Bonjour !' ) |
%SPLIT |
Permet de découper une chaîne de caractères dans tableau (7.3 TR10 / 7.4 TR4). Renvoie un tableau temporaire | lignes = %split( tableau ) |
%MAXARR et %MINARR |
Renvoie l'index de la plus grande ou plus petite valeur dans un tableau (7.3 TR11 / 7.4 TR5) | idx = %maxarr( tableau ) |
Les codes opération suivants NE peuvent PAS être saisie en 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.
Proposition de remplacement des codes invalides en format libre
Code Opération |
Remplacement |
Exemple |
ADD | + | EVAL A = A +1 ou A = A+1 ou A+=1 |
ADDDUR | + | Datliv = datcmd + %DAYS(45) |
ALLOC | %alloc | |
ANDxx | (test en libre) | if A=B AND compteur<>0 |
CABxx | (à éviter) | |
CALL | CALLP + DCL-PR avec EXTPGM | CALLP pgmA (parm1 : parm2) |
CALLB | CALLP + DCL-PR avec EXTPROC | idem |
CASxx | IF + EXSR | |
CAT | + | Message = 'date de traitement' + DATCHAR |
CHECK | %check | pos = %check('0123456789-+,' : qtechar) |
CHECKR | %checkr | idem |
*LIKE DEFINE | déclaration DCL-S avec LIKE( ) | |
*DTAARA DEFINE | déclaration DCL-S avec DTAARA( ) | |
DIV | / | |
DO | FOR | FOR i = 1 to 50 |
DOUxx | DOU | Dou %eof |
DOWxx | DOW | Dow not %eof |
END | ENDxx (déjà recommandé avant) | |
ENDCS | cf CAS | |
EXTRCT | %subdt | mois = %SUBDT(DATCMD : *M) |
GOTO | c'est quoi ? ;-) | GOTO DEBUT -> ITER GOTO FIN -> LEAVE |
IFxx | IF | if GAP = 4 |
KFLD | %KDS ou directement (K1 :K2) | CHAIN (societe: nocli) clientf1 |
KLIST | (cf ci-dessus) | |
LOOKUP | %lookup | tva = %lookup(code : tbtva) |
MOVE | EVALR , Convertir avec les fonction intégrées | datcmd = %DATE(datchar:*ISO) ou chaine = %char(datcmd) |
MOVEL | EVAL , idem pour les conversions | |
MOVEA | Définition d'une zone CHAR en recouvrement puis %SUBST |
DCL-S IND99_p POINTER INZ(%addr(*in)); DCL-S ind99 CHAR(99) BASED(IND99_p); MOVEA '010' *in(80) -> %SUBST(IND99 : 80 : 3) = '010'; |
MULT | * | |
MVR | %rem | if %rem(AN : 4) = 0 |
ORxx | cf ANDxx | |
PARM | DCL-PR | |
PLIST | cf PARM | |
REALLAOC | %realloac | |
SCAN | %scan | QUATRE = %scan('4' : 'RPG4') |
SETOFF | *inxx = *off; | |
SETON | *inxx = *on; | |
SUB | - | |
SUBDUR | - | HIER = AUJOURDHUI - %days(1) |
ou SUBDUR | %diff | UN = %DIFF(aujourdhui : hier) |
SUBST | %subst | |
TAG | cf GOTO | |
TESTN | %check | if %check('0123456789' : QTECHAR) > 0 |
TIME | %date() ou %time() | aujourdhui = %date() |
WHENxx | WHEN | |
XFOOT | %xfoot | TVA = %xfoot(tbmt) * TAUX |
XLATE | %xlate | GRAND = %xlate(minuscules: majuscules: PETIT) |
Z-ADD | EVAL | |
Z-SUB | EVAL - |
Les dates existent depuis 1992, elles sont reconnues par le RPG depuis 1995
DDS | SQL | RPG (D) | FreeForm RPG | |
date | L | DATE | D | Date(*format) |
heure | T | TIME | T | Time(*format) |
horodatage | Z | TIMESTAMPT | Z | timestamp |
- Formats
- *DMY : exemple 15/01/14 (15 janvier 2014)
- *YMD : exemple 99/12/31 (31 Décembre 1999)
- *ISO : exemple 2015-12-01
Sans indication, cela sera *ISO, et cela sera parfait , beaucoup plus simple.
- si vous initialisez des dates, mettez une constante structurée comme suit :
- D'xxxx-xx-xx' (format indiqué par spécif H ou Ctl-Opt)
- T'xx:xx:xx'
- Z'xxxx-xx-xx.xx.xx.xx.xxxxxx'
![]()
- toutes les comparaisons ont du sens :
- même si les formats sont différents
- entre une date et un horodatage, entre une heure et un horodatage.
- les conversions sont assurées
- A condition de préciser un format
- format simple pour une zone numérique (*DMY, *ISO)
- format suivi du séparateur pour une zone caractère (*DMYs)
s | exemple | ||
/ | le séparateur est / | *DMY/ | 15/06/14 |
. | le séparateur est . | *EUR. | 15.06.2014 |
& | l'espace | *ISO& | 2014 06 15 |
0 | pas de séparateur | *ISO0 | 20140615 |
pour récupérer date/heure en cours
datnum = 991215; |
Calculs
%SUBDT(Z'2014-07-21-15.20.26.123456789012':*SECONDS:10:8) -> extrait 26,12345678 |
// fin de mois du 26 Mars = 26 Avril - 26 jours findemois = DATC + %MONTH(1) - %DAYS( %SUBDT(DATC+%MONTH(1)):*DAYS)) |
Appel de programmes CALL
Sur IBM i , un programme, quelque soit le langage, peut appeler un programme (avec passage de paramètres)
le passage de paramètres est un passage de paramètre par référence (par adresse) c.a.d en entrée/sortie
En spécif C
Prototypes/Interface de Procédures
-> L'ordre CALL n'existe plus en format libre
Il faut à la place déclarer le programme et ses paramètres, cela s'appelle
avant,
en spécif D,
+-----------------------------------------------------------+
! DEXEC PR EXTPGM('PGMB') !
! D 6P 0 const !
+-----------------------------------------------------------+ PR indique qu'il s'agit d'un prototype (même positions que DS)
Aujourd'hui :
DCL-PR nom-de-prototype;
paramètre type mots-clés ;
END-PR [nom-de-prototype] ;
DCL-PR QCMDEXC EXTPGM; cde CHAR(50) CONST; cdl PACKED(15 : 5) CONST; END-PR; |
Utilisation ensuite :
Qcmdexc(cmd : %len(cmd)) ;
Qcmdexc('WRKSPLF': 7) ;
DCL-PR DayOfWeek zoned(1); //retourne 1 à 7 datwrk DATE CONST; END-PR; |
DCL-PR MaFonction PACKED(5:0) END-PR; |
La réception des paramètres peut elle-même être réalisée
sur le même principe, avec une interface de procédure
DCL-PI nom-de-procédure | *N [type de retour]
paramètre type mots-clés ;
END-PI [nom-de-procédure] ;
Depuis la V7R10, le prototype n'est plus obligatoire pour le programme en cours
DCL-PI *N;
param char(10); END-PI;
dsply param; *INLR = *ON;
Comparaisons
Dwp_date s D Dwp_jour s 1 0 Dundimanche s D inz(D'1980-01-06') Dnbjours s 6 0 c *entry plist
c parm wp_date c parm wp_jour Dcl-S undimanche Date inz(D'1980-01-06'); Dcl-S nbjours Packed(6:0);
// Procedure interface (remplace *ENTRY PLIST) Dcl-Pi *N; wp_date Date; wp_jour Packed(1:0); End-Pi; ou bien (avant) --> Dcl-S undimanche Date inz(D'1980-01-06'); Dcl-S nbjours Packed(6:0);
// Procedure interface Dcl-Pi FREE01 ExtPgm; wp_date Date; wp_jour Packed(1:0); End-Pi;
Exemple avec un pgm utilisé en tant que web service
// fonction, retourne un booléen
DCL-PI *N IND END-PI;
CTL-OPT MAIN(Bonjour)
DCL-PROC Bonjour;
DCL-PI *N EXTPGM;
nom CHAR(10) CONST;
END-PI;
dsply ('bonjour ' + nom) ;
END-PROC;
Enfin, un
prototype peut faire référence à un programme externe ou à une procédure
Une procédure peut être comme un sous-programme ou externalisée dans un objet *SRVPGM
Elle possède ses propres variables (locales) et ses propres déclarations de fichier (DCL-F)
Dans ce dernier cas
- les entrées/sorties doivent être impérativement 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 fichiers ouverts.
DCL-PI interface de procédure;
...
END-PI;
...
END-PROC [nom-de-procédure] ;
Mots-clés importants
Comparaisons
Un Sous/pgm (BEGSR) devient une procédure (DCL-PROC)
h nomain |
Ctl-Opt nomain; |
DCL-PR lecture CHAR(50); code INT(10) CONST; END-PR; |
DCL-PROC getCdeSuivante; DCL-PI *N IND EXTPROC(*DCLCASE); commandeDS LIKEDS(commande_t); END-PI; DCL-F cdes STATIC; READ cdes commandeDS; RETURN %eof(cdes); END-PROC getCdeSuivante; |
Exemple de modernisation
Sur une base vinicole, un producteur ayant un ou plusieurs vins, chaque vin est constitué de UN à QUATRE cépages
pgm de constitution d'un fichier infocentre, contenant le nbr de vins, le cépage le plus utilisé et le nbr de cépages différentsdéclarations
boucle principale
![]()
Pour chaque producteur (nbr de vins, encave (oui/non) ? )
s/pgm de mémorisation d'un des cépages de ce vin
Calcul du cépage le plus utilisé par ce producteur et du nombre de cépages différents
![]()
le même en FreeForm
boucle principale
Notez qu'en fin de producteur, il suffit de trier la DS de type tableau en décroissant
sur le nombre, pour que le poste 1 contienne le cépage le plus utilisé !
Pour chaque producteur (nbr de vins, encave (oui/non) ? )
Remarquez l'appel à la procédure plutôt qu'au s/pgm
procédure de mémorisation d'un des cépages de ce vin
© Volubis