Aller au contenu

Instruction RPG full free · IBM i (AS/400) · Déclarations

DCL-S

Déclarer une zone autonome

Déclare une variable simple (texte, nombre, date, indicateur…) avec son type, sa longueur et, si on veut, sa valeur de départ.

Syntaxe

dcl-s nom type(longueur [: décimales]) [inz[(valeur)]] [dim(n)] [static] [const];
dcl-s nom like(autreZone);
dcl-s nom char(20) inz('Dupont SA');
dcl-s nom packed(9:2) dim(12);
nom
Le nom de la variable, sans distinction de majuscules et minuscules.
type
char, varchar, packed, zoned, int, uns, float, ind, date, time, timestamp, pointer… avec longueur et décimales entre parenthèses.
inz[(valeur)]
Valeur de départ. Sans valeur entre parenthèses, la valeur par défaut du type (blancs, zéro).
like(zone)
Prend le même type et la même longueur qu'une autre zone, pour que les deux évoluent ensemble.
dim(n)
Déclare un tableau de n éléments.
static
Dans une procédure : garde la valeur d'un appel à l'autre.
Effet
Aucun indicateur ni %FOUND. La déclaration réserve la place en mémoire et, avec inz, y met la valeur de départ. Sans inz, une zone alphanumérique est remplie de blancs et une zone numérique à zéro.

À quoi ça sert

C'est la déclaration la plus courante. Chaque variable est déclarée avec son type, sur une ligne, à l'endroit où l'on en a besoin : dans la partie déclarative du programme pour une zone globale, ou au début d'une procédure pour une zone locale. En RPG IV en colonnes, il fallait une spécification D avec le type en colonne 40 ; ici, tout est lisible d'un seul coup d'œil.

Le choix du type compte : packed ou zoned pour un montant (pas d'erreur d'arrondi), int pour un compteur, varchar quand la longueur varie et qu'on veut éviter les blancs de fin, ind pour un booléen.

Exemple 1 : Les types courants

**free
// DCL-S : declarer des zones autonomes de types varies.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s nomClient char(20)    inz('Dupont SA');
dcl-s ville     varchar(30) inz('Montpellier');
dcl-s solde     packed(9:2) inz(1250.50);
dcl-s nbCmd     int(10)     inz(12);
dcl-s actif     ind         inz(*on);
dcl-s creation  date        inz(d'2020-03-15');
dcl-s note      char(10);
dcl-s cumul     packed(7:2);
dcl-s copie     like(nomClient);

copie = 'Martin et fils';

snd-msg 'Client  : [' + nomClient + ']';
snd-msg 'Ville   : [' + ville + '] longueur ' + %char(%len(ville));
snd-msg 'Solde   : ' + %char(solde);
snd-msg 'Commandes : ' + %char(nbCmd);
snd-msg 'Actif   : ' + %char(actif);
snd-msg 'Creation: ' + %char(creation);
snd-msg 'Note    : [' + note + ']';
snd-msg 'Cumul   : ' + %char(cumul);
snd-msg 'Copie   : [' + copie + ']';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Client  : [Dupont SA           ]
Ville   : [Montpellier] longueur 11
Solde   : 1250.50
Commandes : 12
Actif   : 1
Creation: 2020-03-15
Note    : [          ]
Cumul   : .00
Copie   : [Martin et fils      ]

Un char(20) est complété par des blancs (visibles grâce aux crochets), un varchar a la longueur de son contenu (11 pour Montpellier). Sans inz, la note vaut des blancs et le cumul vaut zéro. like(nomClient) donne à copie exactement le même type : char(20).

Exemple 2 : Un texte trop long est tronqué en silence

**free
// DCL-S : un texte trop long est tronque en silence, sans aucune erreur.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s ville   char(5);
dcl-s longue  varchar(5);
dcl-s montant packed(5:2);

ville = 'Montpellier';
longue = 'Montpellier';
montant = 123.456;

snd-msg 'char(5)      : [' + ville + ']';
snd-msg 'varchar(5)   : [' + longue + ']';
snd-msg 'packed(5:2)  : ' + %char(montant);

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

char(5)      : [Montp]
varchar(5)   : [Montp]
packed(5:2)  : 123.45

Mettre « Montpellier » dans un char(5) ou un varchar(5) donne Montp, sans erreur, sans message. Les décimales en trop d'un nombre sont aussi perdues sans arrondi : 123,456 devient 123,45.

Exemple 3 : Un nombre trop grand fait planter le programme

**free
// DCL-S : un nombre trop grand pour la zone fait planter le programme.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-s quantite packed(3:0);

quantite = 999;
snd-msg 'Avant   : ' + %char(quantite);
quantite = 1250;
snd-msg 'Apres   : ' + %char(quantite);

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Avant   : 999
Erreur : RNQ0103 - (C G D F) Cible pour opération numérique trop petite pour contenir résultat.

Pour un nombre, c'est l'inverse : mettre 1250 dans une zone packed(3:0) déclenche l'erreur RNQ0103 (MCH1210). Le programme s'arrête avant d'afficher la deuxième ligne.

Le piège

Un texte est tronqué sans bruit, un nombre fait une erreur. Dans l'exemple 2, « Montpellier » devient Montp dans un char(5) et dans un varchar(5) : personne ne vous prévient et vous écrirez une ville tronquée dans le fichier. Les décimales en trop disparaissent de la même manière. Mais la partie entière d'un nombre ne se perd pas : exemple 3, 1250 dans un packed(3:0) arrête le programme avec RNQ0103.

La parade pour le texte : dimensionner large, ou comparer %len avant d'affecter. Pour les nombres, déclarer assez de chiffres, ou protéger l'affectation par un monitor.