Aller au contenu
*BLANKS · *ZEROS · *HIVAL · *LOVAL · *ALL · *START · RPG IV, RPG III, CL

Les constantes figuratives, *BLANKS, *HIVAL et les autres

La documentation les cite partout sans les expliquer en un seul endroit. Les voici réunies : ce que chaque constante met dans chaque type de zone, octet par octet, puis les pièges, de la structure remise à blanc à la clé décroissante, en RPG IV, en RPG III et en CL. Tout a été exécuté sur un IBM i 7.5.

23valeurs relevées, octet par octet
5programmes RPG et CL exécutés
5essais de compilation
00907le statut d'une structure à blanc

En une phrase

Une constante figurative est une valeur toute faite, écrite avec un astérisque et sans longueur : elle prend la taille et le type de la zone à laquelle on l'applique. nom = *blanks remplit nom de blancs, qu'elle fasse 6 ou 600 caractères.

Les constantes du RPG

On les emploie dans une affectation, une comparaison, un mot-clé INZ, et en colonné en facteur 1 ou 2. Toutes ne vont pas avec tous les types : le tableau donne ceux qu'admet la documentation.

ConstanteValeurZones admises
*BLANK, *BLANKSDes blancs (x'40')Caractère, graphique, UCS-2
*ZERO, *ZEROSDes zéros : '0' (x'F0') en caractère, 0 en numériqueCaractère, numérique
*HIVALLa plus grande valeur : x'FF' en caractère, le maximum de la zone en numérique et en dateCaractère, numérique, date, heure, horodatage
*LOVALLa plus petite valeur : x'00' en caractère, le minimum (négatif) en numériqueCaractère, numérique, date, heure, horodatage
*ALL'x..'Le texte répété jusqu'à remplir la zoneCaractère ; numérique avec des chiffres seulement
*ALLX'x1..'Les octets hexadécimaux répétésCaractère
*ALLG, *ALLULe même principe en graphique et en UCS-2Graphique, UCS-2
*ON, *OFF'1' et '0'Indicateur, caractère
*NULLPointeur nulPointeur, objet

*BLANK et *BLANKS, *ZERO et *ZEROS sont deux orthographes de la même constante. À ne pas confondre avec les fonctions %HIVAL et %LOVAL, plus récentes, qui renvoient la plus grande et la plus petite valeur d'une zone.

Exemple 1 Chaque type de zone

Ce que chaque constante met dans la zone

VALEURS applique les constantes à des zones de tous les types, puis range, pour chacune, ce qu'elle affiche et ses octets dans un fichier. La procédure noter lit les octets par un pointeur posé sur l'adresse de la zone :

**free
// Constantes figuratives : chaque zone reçoit une constante, puis
// on range ce qu'elle affiche et ses octets dans le fichier RESULTAT.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-f RESULTAT usage(*output);

dcl-s nom char(6);
dcl-s libelle varchar(6);
dcl-s montant packed(5:2);
dcl-s quantite zoned(5:0);
dcl-s compteur int(10);
dcl-s taux float(8);
dcl-s jour date(*iso);
dcl-s jourMdy date(*mdy);
dcl-s heure time(*iso);
dcl-s instant timestamp;
dcl-s trouve ind;
dcl-s adresse pointer;

nom = *blanks;
noter('*BLANKS' : 'char(6)' : '[' + nom + ']' : %addr(nom) : %size(nom));
nom = *zeros;
noter('*ZEROS' : 'char(6)' : '[' + nom + ']' : %addr(nom) : %size(nom));
nom = *loval;
noter('*LOVAL' : 'char(6)' : '' : %addr(nom) : %size(nom));
nom = *hival;
noter('*HIVAL' : 'char(6)' : '' : %addr(nom) : %size(nom));
nom = *all'AB';
noter('*ALL''AB''' : 'char(6)' : '[' + nom + ']' : %addr(nom) : %size(nom));
nom = *allx'5C';
noter('*ALLX''5C''' : 'char(6)' : '[' + nom + ']' : %addr(nom) : %size(nom));

libelle = 'AB';
libelle = *blanks;
noter('*BLANKS' : 'varchar(6) = ''AB''' : '[' + libelle + ']'
     : %addr(libelle) : %size(libelle));
libelle = 'AB';
libelle = *hival;
noter('*HIVAL' : 'varchar(6) = ''AB''' : ''
     : %addr(libelle) : %size(libelle));

montant = *hival;
noter('*HIVAL' : 'packed(5:2)' : %char(montant)
     : %addr(montant) : %size(montant));
montant = *loval;
noter('*LOVAL' : 'packed(5:2)' : %char(montant)
     : %addr(montant) : %size(montant));
quantite = *hival;
noter('*HIVAL' : 'zoned(5:0)' : %char(quantite)
     : %addr(quantite) : %size(quantite));
quantite = *loval;
noter('*LOVAL' : 'zoned(5:0)' : %char(quantite)
     : %addr(quantite) : %size(quantite));
compteur = *hival;
noter('*HIVAL' : 'int(10)' : %char(compteur)
     : %addr(compteur) : %size(compteur));
compteur = *loval;
noter('*LOVAL' : 'int(10)' : %char(compteur)
     : %addr(compteur) : %size(compteur));
taux = *hival;
noter('*HIVAL' : 'float(8)' : %char(taux) : %addr(taux) : %size(taux));

jour = *loval;
noter('*LOVAL' : 'date(*iso)' : %char(jour) : %addr(jour) : %size(jour));
jour = *hival;
noter('*HIVAL' : 'date(*iso)' : %char(jour) : %addr(jour) : %size(jour));
jourMdy = *loval;
noter('*LOVAL' : 'date(*mdy)' : %char(jourMdy : *iso)
     : %addr(jourMdy) : %size(jourMdy));
jourMdy = *hival;
noter('*HIVAL' : 'date(*mdy)' : %char(jourMdy : *iso)
     : %addr(jourMdy) : %size(jourMdy));
heure = *hival;
noter('*HIVAL' : 'time(*iso)' : %char(heure) : %addr(heure) : %size(heure));
instant = *hival;
noter('*HIVAL' : 'timestamp' : %char(instant)
     : %addr(instant) : %size(instant));

trouve = *on;
noter('*ON' : 'ind' : trouve : %addr(trouve) : %size(trouve));
adresse = *null;
noter('*NULL' : 'pointer' : '' : %addr(adresse) : %size(adresse));

*inlr = *on;

// Range une ligne : la constante, la zone, son affichage et ses octets.
dcl-proc noter;
  dcl-pi *n;
    pConstante varchar(20) const;
    pZone varchar(20) const;
    pAffiche varchar(60) const;
    pAdresse pointer value;
    pTaille int(10) value;
  end-pi;
  dcl-s octets char(40) based(pAdresse);

  PROGRAMME = 'VALEURS';
  ORDRE += 1;
  CONSTANTE = pConstante;
  ZONE = pZone;
  AFFICHE = pAffiche;
  BRUT = %subst(octets : 1 : pTaille);
  LONGUEUR = pTaille;
  write RESULTATR;
end-proc;

Le contenu du fichier après l'appel, tel que le programme l'a rangé :

ConstanteZoneAffichageOctets
*BLANKSchar(6)[      ]40 40 40 40 40 40
*ZEROSchar(6)[000000]F0 F0 F0 F0 F0 F0
*LOVALchar(6)-00 00 00 00 00 00
*HIVALchar(6)-FF FF FF FF FF FF
*ALL'AB'char(6)[ABABAB]C1 C2 C1 C2 C1 C2
*ALLX'5C'char(6)[******]5C 5C 5C 5C 5C 5C
*BLANKSvarchar(6) = 'AB'[      ]00 06 40 40 40 40 40 40
*HIVALvarchar(6) = 'AB'-00 06 FF FF FF FF FF FF
*HIVALpacked(5:2)999.9999 99 9F
*LOVALpacked(5:2)-999.9999 99 9D
*HIVALzoned(5:0)99999F9 F9 F9 F9 F9
*LOVALzoned(5:0)-99999F9 F9 F9 F9 D9
*HIVALint(10)21474836477F FF FF FF
*LOVALint(10)-214748364880 00 00 00
*HIVALfloat(8)+1.797693134862316E+3087F EF FF FF FF FF FF FF
*LOVALdate(*iso)0001-01-01F0 F0 F0 F1 60 F0 F1 60 F0 F1
*HIVALdate(*iso)9999-12-31F9 F9 F9 F9 60 F1 F2 60 F3 F1
*LOVALdate(*mdy)1940-01-01F0 F1 61 F0 F1 61 F4 F0
*HIVALdate(*mdy)2039-12-31F1 F2 61 F3 F1 61 F3 F9
*HIVALtime(*iso)24.00.00F2 F4 4B F0 F0 4B F0 F0
*HIVALtimestamp9999-12-31-24.00.00.000000F9 F9 F9 F9 60 F1 F2 60 F3 F1 60 F2 F4 4B F0 F0 4B F0 F0 4B F0 F0 F0 F0 F0 F0
*ONind1F1
*NULLpointer-00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*HIVAL sur une zone caractère
Des x'FF', pas des 9 : c'est l'octet le plus haut dans l'ordre de tri EBCDIC. Il ne s'affiche pas, d'où la colonne vide. Pour un nombre, *HIVAL donne bien des 9 : 999.99 sur un packed(5:2), octets 99 99 9F.
*LOVAL sur une zone numérique
La plus petite valeur, donc négative : -999.99, avec le signe D dans le dernier demi-octet. Sur un int(10), -2147483648.
varchar(6)
Les deux premiers octets portent la longueur. La zone valait 'AB' (longueur 2) : après *blanks, elle vaut 00 06 suivi de six blancs. La constante remplit la longueur maximale, pas la longueur courante.
date(*mdy)
Une date sur deux chiffres d'année ne couvre que 1940 à 2039 : son *LOVAL est le 1er janvier 1940 et son *HIVAL le 31 décembre 2039. En *iso, de 0001-01-01 à 9999-12-31.
time et timestamp
*HIVAL donne 24.00.00, une heure qu'aucune horloge n'affiche, mais valide pour le RPG.

Ce que le compilateur refuse

Chaque ligne ci-dessous a été compilée seule, dans un petit programme d'essai :

LigneZoneRésultatTexte du message
montant = *blanks;packed(5:2)RNF7416Les types de droite et de gauche ne concordent pas
jour = *blanks;dateRNF7416Les types de droite et de gauche ne concordent pas
trouve = *hival;indRNF7531Expression incorrecte pour attribution à l'indicateur
setgt *end CLIENTSI;fichierRNF5318Type de données de la valeur du Facteur 1 non admis
IF COND(&NOM *EQ *BLANKS)CL, *CHARcompileaucune erreur : *BLANKS est pris pour du texte

*BLANKS ne va qu'aux zones caractère : pour vider un nombre, c'est *zeros ou CLEAR. La dernière ligne, en CL, compile sans erreur : c'est justement le piège, expliqué plus bas.

Piège 1 Une structure à blanc

*BLANKS sur une structure : l'erreur de données décimales

Une structure est vue comme une seule zone caractère. client = *blanks met donc des blancs partout, y compris dans les sous-zones packées, qui ne contiennent plus un nombre valide. PIEGEDS essaie un calcul après chaque étape :

**free
// Le piège de *BLANKS sur une structure : les sous-zones numériques
// reçoivent des blancs, et le premier calcul tombe en erreur.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-f RESULTAT usage(*output);

dcl-ds client qualified;
  numero packed(5:0);
  nom char(10);
  solde packed(9:2);
end-ds;
dcl-s total packed(9:2);

noter('au départ, sans INZ');
client = *blanks;
noter('client = *BLANKS');
clear client;
noter('CLEAR client');
client = *blanks;
noter('à nouveau *BLANKS');
client.solde = 0;
noter('puis client.solde = 0');

*inlr = *on;

// Essaie un calcul sur la sous-zone numérique et range le résultat
// avec les octets de la structure.
dcl-proc noter;
  dcl-pi *n;
    pEtape varchar(30) const;
  end-pi;
  dcl-s octets char(40) based(adresse);
  dcl-s adresse pointer;

  monitor;
    total = client.solde + 1;
    AFFICHE = 'client.solde + 1 = ' + %char(total);
  on-error;
    AFFICHE = 'erreur, statut ' + %editc(%status : 'X');
  endmon;
  adresse = %addr(client);
  PROGRAMME = 'PIEGEDS';
  ORDRE += 1;
  CONSTANTE = pEtape;
  ZONE = 'client';
  BRUT = %subst(octets : 1 : %size(client));
  LONGUEUR = %size(client);
  write RESULTATR;
end-proc;
ÉtapeCalculOctets de client
au départ, sans INZerreur, statut 0090740 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
client = *BLANKSerreur, statut 0090740 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
CLEAR clientclient.solde + 1 = 1.0000 00 0F 40 40 40 40 40 40 40 40 40 40 00 00 00 00 0F
à nouveau *BLANKSerreur, statut 0090740 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40 40
puis client.solde = 0client.solde + 1 = 1.0040 40 40 40 40 40 40 40 40 40 40 40 40 00 00 00 00 0F
Au départ, sans INZ
La structure démarre à blanc, comme après *blanks : le calcul échoue déjà, avec le statut 00907 (erreur de données décimales). Le remède : inz sur la structure, qui met chaque sous-zone à la valeur de son type.
CLEAR client
Des zéros dans les sous-zones numériques (00 00 0F), des blancs dans la zone caractère : le calcul passe.
Puis client.solde = 0
Corriger une seule sous-zone suffit pour ce calcul, mais numero reste à blanc (40 40 40) : l'erreur attend le premier qui s'en servira.

Le remède a été vérifié sur la même machine : avec dcl-ds client qualified inz;, la structure démarre à 00 00 0F, blancs, 00 00 00 00 0F, et le calcul passe. MONITOR intercepte l'erreur ici ; sans lui, le programme serait interrompu par l'erreur de données décimales (MCH1202).

Piège 2 La clé décroissante

*LOVAL, *HIVAL, *START et *END dans un fichier

Pour lire un fichier depuis le début, on écrit souvent setll *loval. Le fichier CLIENTS contient trois clients (101, 205 et 310), lus par deux index : CLIENTSI par numéro croissant, CLIENTSD par numéro décroissant.

**free
// *LOVAL, *HIVAL, *START et *END pour se placer au début ou à la
// fin d'un fichier : sur une clé croissante, puis décroissante.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-f CLIENTSI keyed;                              // NUMERO croissant
dcl-f CLIENTSD keyed rename(CLIENTR : CLIENTRD);   // NUMERO décroissant
dcl-f RESULTAT usage(*output);

setll *loval CLIENTSI;
read CLIENTSI;
noter('SETLL *LOVAL, READ' : 'croissante' : %eof(CLIENTSI));
setll *start CLIENTSI;
read CLIENTSI;
noter('SETLL *START, READ' : 'croissante' : %eof(CLIENTSI));
setgt *hival CLIENTSI;
readp CLIENTSI;
noter('SETGT *HIVAL, READP' : 'croissante' : %eof(CLIENTSI));
setll *end CLIENTSI;
readp CLIENTSI;
noter('SETLL *END, READP' : 'croissante' : %eof(CLIENTSI));

setll *loval CLIENTSD;
read CLIENTSD;
noter('SETLL *LOVAL, READ' : 'décroissante' : %eof(CLIENTSD));
setll *start CLIENTSD;
read CLIENTSD;
noter('SETLL *START, READ' : 'décroissante' : %eof(CLIENTSD));
setgt *hival CLIENTSD;
readp CLIENTSD;
noter('SETGT *HIVAL, READP' : 'décroissante' : %eof(CLIENTSD));
setll *end CLIENTSD;
readp CLIENTSD;
noter('SETLL *END, READP' : 'décroissante' : %eof(CLIENTSD));

*inlr = *on;

// Range la ligne : le client lu, ou la fin de fichier.
dcl-proc noter;
  dcl-pi *n;
    pOrdres varchar(30) const;
    pCle varchar(20) const;
    pFin ind const;
  end-pi;

  PROGRAMME = 'LECTURE';
  ORDRE += 1;
  CONSTANTE = pOrdres;
  ZONE = 'clé ' + pCle;
  if pFin;
    AFFICHE = 'fin de fichier';
  else;
    AFFICHE = 'client ' + %char(NUMERO) + ' ' + %trim(NOM);
  endif;
  BRUT = *blanks;
  LONGUEUR = 0;
  write RESULTATR;
end-proc;
OrdresFichierRésultat
SETLL *LOVAL, READclé croissanteclient 101 DURAND
SETLL *START, READclé croissanteclient 101 DURAND
SETGT *HIVAL, READPclé croissanteclient 310 PETIT
SETLL *END, READPclé croissanteclient 310 PETIT
SETLL *LOVAL, READclé décroissantefin de fichier
SETLL *START, READclé décroissanteclient 310 PETIT
SETGT *HIVAL, READPclé décroissantefin de fichier
SETLL *END, READPclé décroissanteclient 101 DURAND

Sur la clé croissante, les quatre façons se valent. Sur la clé décroissante, setll *loval se place en fin de fichier, puisque la plus petite clé y est rangée en dernier : le READ ne lit rien. *start et *end, eux, désignent le début et la fin du fichier quel que soit l'ordre de la clé. Ils s'emploient avec SETLL : setgt *end est refusé à la compilation (RNF5318).

RPG III En colonnes

Les mêmes constantes en RPG III

Le RPG III (RPG/400) connaît les mêmes constantes, en facteur 1 ou 2 des MOVE, COMP et SETLL. Dans VAL3, NOM6 et BRUTN, MONT et BRUTM partagent les mêmes octets : la seconde zone sert à relever le contenu de la première.

     F* Constantes figuratives en RPG III : MOVE, COMP, SETLL, SETGT
     F* Chaque essai range la zone et ses octets dans le fichier RES3
     FCLIENTSIIF  E           K        DISK
     FRES3    O   E                    DISK
     I* NOM6 et BRUTN, MONT et BRUTM occupent les memes octets
     IZONES       DS
     I                                        1   6 NOM6
     I                                        1   6 BRUTN
     I                                    P   7   92MONT
     I                                        7   9 BRUTM
     C* Zones alphanumeriques
     C                     MOVE *BLANK    NOM6
     C                     MOVEL'*BLANK'  CTE
     C                     EXSR NOTERN
     C                     MOVE *ZERO     NOM6
     C                     MOVEL'*ZERO'   CTE
     C                     EXSR NOTERN
     C                     MOVE *ALL'AB'  NOM6
     C                     MOVEL'*ALL'    CTE
     C                     EXSR NOTERN
     C                     MOVE *HIVAL    NOM6
     C                     MOVEL'*HIVAL'  CTE
     C                     EXSR NOTERN
     C* Zone numerique packee (5,2)
     C                     MOVE *HIVAL    MONT
     C                     MOVEL'*HIVAL'  CTE
     C                     EXSR NOTERM
     C                     MOVE *LOVAL    MONT
     C                     MOVEL'*LOVAL'  CTE
     C                     EXSR NOTERM
     C                     MOVE *BLANK    MONT
     C                     MOVEL'*BLANK'  CTE
     C                     EXSR NOTERM
     C* Indicateurs : *ON et *OFF
     C                     MOVE *ON       *IN50
     C                     MOVEL'*ON'     CTE
     C                     MOVEL'*IN50'   ZONE
     C                     MOVE *IN50     AFFICH
     C                     EXSR ECRIRE
     C* Comparaison : NOM6 a blanc ?
     C                     MOVE *BLANK    NOM6
     C           NOM6      COMP *BLANK                   51
     C                     MOVEL'*BLANK'  CTE
     C                     MOVEL'*IN51'   ZONE
     C                     MOVE *IN51     AFFICH
     C                     EXSR ECRIRE
     C* Premier et dernier client
     C           *LOVAL    SETLLCLIENTSI
     C                     READ CLIENTSI                 90
     C                     MOVEL'*LOVAL'  CTE
     C                     EXSR NOTERC
     C           *HIVAL    SETGTCLIENTSI
     C                     READPCLIENTSI                 90
     C                     MOVEL'*HIVAL'  CTE
     C                     EXSR NOTERC
     C                     MOVE *ON       *INLR
     C* Range NOM6 avec ses octets
     C           NOTERN    BEGSR
     C                     MOVEL'CHAR 6'  ZONE
     C                     MOVELNOM6      AFFICH
     C                     MOVELBRUTN     BRUT
     C                     EXSR ECRIRE
     C                     ENDSR
     C* Range MONT avec ses octets
     C           NOTERM    BEGSR
     C                     MOVEL'P 5,2'   ZONE
     C                     MOVELBRUTM     BRUT
     C                     EXSR ECRIRE
     C                     ENDSR
     C* Range le client lu, ou la fin de fichier
     C           NOTERC    BEGSR
     C                     MOVEL'CLIENTSI'ZONE
     C  N90                MOVELNOM       AFFICH
     C   90                MOVEL'FIN'     AFFICH
     C                     EXSR ECRIRE
     C                     ENDSR
     C* Ecrit la ligne puis remet les zones a blanc
     C           ECRIRE    BEGSR
     C           ORDRE     ADD  1         ORDRE
     C                     WRITERES3R
     C                     MOVE *BLANK    CTE
     C                     MOVE *BLANK    ZONE
     C                     MOVE *BLANK    AFFICH
     C                     MOVE *BLANK    BRUT
     C                     ENDSR
CTEZONEAFFICHOctets
*BLANKCHAR 6-40 40 40 40 40 40
*ZEROCHAR 6000000F0 F0 F0 F0 F0 F0
*ALLCHAR 6ABABABC1 C2 C1 C2 C1 C2
*HIVALCHAR 6-FF FF FF FF FF FF
*HIVALP 5,2-99 99 9F
*LOVALP 5,2-99 99 9D
*BLANKP 5,2-00 00 0F
*ON*IN501-
*BLANK*IN511-
*LOVALCLIENTSIDURAND-
*HIVALCLIENTSIPETIT-

Une différence avec le full free : MOVE *BLANK vers la zone packée MONT est accepté, et y met des zéros (00 00 0F), comme la documentation le prévoit pour MOVE, alors que montant = *blanks est refusé en RPG IV. *ON et *OFF existent aussi : MOVE *ON allume l'indicateur 50.

Piège 3 Le faux ami du CL

En CL, *BLANKS n'est pas une constante

Le CL a ses valeurs spéciales, mais ce sont des valeurs de paramètres de commande (*LIBL, *CURLIB, *ALL…), pas des constantes figuratives. Écrire *BLANKS dans une condition compile pourtant :

/* En CL, *BLANKS n'est pas une constante figurative : le       */
/* compilateur l'accepte, mais compare la zone au texte *BLANKS. */
PGM
  DCL VAR(&NOM) TYPE(*CHAR) LEN(10)
  DCL VAR(&TEST) TYPE(*CHAR) LEN(30)
  DCL VAR(&VRAI) TYPE(*CHAR) LEN(3)

  /* &NOM est à blanc : on la compare à *BLANKS, puis à ' ' */
  CHGVAR VAR(&TEST) VALUE('vide, *EQ *BLANKS')
  CHGVAR VAR(&VRAI) VALUE('non')
  IF COND(&NOM *EQ *BLANKS) THEN(CHGVAR VAR(&VRAI) VALUE('oui'))
  CALLSUBR SUBR(NOTER)

  CHGVAR VAR(&TEST) VALUE('vide, *EQ un blanc')
  CHGVAR VAR(&VRAI) VALUE('non')
  IF COND(&NOM *EQ ' ') THEN(CHGVAR VAR(&VRAI) VALUE('oui'))
  CALLSUBR SUBR(NOTER)

  /* &NOM contient le texte *BLANKS */
  CHGVAR VAR(&NOM) VALUE('*BLANKS')
  CHGVAR VAR(&TEST) VALUE('texte *BLANKS, *EQ *BLANKS')
  CHGVAR VAR(&VRAI) VALUE('non')
  IF COND(&NOM *EQ *BLANKS) THEN(CHGVAR VAR(&VRAI) VALUE('oui'))
  CALLSUBR SUBR(NOTER)
  RETURN

  /* Range le test et son résultat dans RESULTAT */
  SUBR SUBR(NOTER)
    RUNSQL SQL('INSERT INTO RESULTAT VALUES(''VALCL'', +
             (SELECT COUNT(*) + 1 FROM RESULTAT WHERE +
             PROGRAMME = ''VALCL''), ''' *CAT &TEST *TCAT +
             ''', ''&NOM'', ''' *CAT &VRAI *TCAT ''', '' '', 0)') +
             COMMIT(*NONE) NAMING(*SYS)
  ENDSUBR
ENDPGM
TestCondition vraie ?
vide, *EQ *BLANKSnon
vide, *EQ un blancoui
texte *BLANKS, *EQ *BLANKSoui

La variable vide n'est pas égale à *BLANKS ; celle qui contient le texte *BLANKS, si. Pour tester une variable vide en CL, on la compare à ' ' : le blanc est complété à la longueur de la variable.

Sources

Les exemples ont été exécutés sur un IBM i 7.5 (voir la méthode). Les règles viennent de ces sources, consultées le 26 octobre 2026 :

  1. Figurative Constants, IBM, ILE RPG Reference 7.5. Liste des constantes et valeurs : *BLANKS réservé aux zones caractère, *HIVAL x'FF' ou valeur maximale, *ALL répété jusqu'à la longueur de la zone, *ON et *OFF.
  2. Rules for Figurative Constants, IBM, ILE RPG Reference 7.5. MOVE de *BLANK vers une zone numérique : des zéros ; comparaison entre deux constantes interdite.
  3. SETLL (Set Lower Limit), IBM, ILE RPG Reference 7.5. *START et *END indépendants de l'ordre de la clé ; *LOVAL et *HIVAL sur une clé décroissante.
  4. Date Data Type, IBM, ILE RPG Reference 7.5. *LOVAL et *HIVAL de chaque format de date : 0001-01-01 et 9999-12-31 en *ISO, 01/01/40 et 12/31/39 en *MDY.

Questions fréquentes

Qu'est-ce qu'une constante figurative en RPG ?

Une valeur toute faite, sans longueur, qui prend la taille et le type de la zone à laquelle on l'applique : *BLANKS remplit de blancs, *ZEROS de zéros, *HIVAL donne la plus grande valeur possible, *LOVAL la plus petite, *ALL'x' répète un texte.

Quelle différence entre *BLANK et *BLANKS ?

Aucune : ce sont deux orthographes de la même constante, comme *ZERO et *ZEROS.

Que vaut *HIVAL ?

Cela dépend de la zone. Sur une zone caractère, des x'FF' (pas des 9). Sur un packed(5:2), 999.99 ; sur un int(10), 2147483647 ; sur une date *ISO, 9999-12-31 ; sur une date *MDY, 2039-12-31. *LOVAL donne l'inverse : x'00', -999.99, -2147483648, 0001-01-01.

*LOVAL ou *START pour lire un fichier depuis le début ?

*START. Sur une clé croissante les deux donnent le premier enregistrement, mais sur une clé décroissante SETLL *LOVAL place en fin de fichier : le READ suivant ne lit rien. *START et *END ne dépendent pas de l'ordre de la clé. Ils s'emploient avec SETLL : SETGT *END est refusé à la compilation.

Pourquoi une structure remise à *BLANKS provoque-t-elle une erreur de données décimales ?

*BLANKS met des blancs (x'40') partout, y compris dans les sous-zones packées, qui ne contiennent alors plus un nombre valide : le premier calcul échoue avec le statut 00907. CLEAR, lui, met des blancs dans les zones caractère et des zéros dans les zones numériques.

Peut-on écrire *BLANKS en CL ?

Le compilateur l'accepte, mais le CL n'a pas de constante figurative : &NOM *EQ *BLANKS compare la variable au texte « *BLANKS ». Pour tester une variable vide, on la compare à ' ' : le CL complète le blanc à la longueur de la variable.