%BITOR
OU logique bit à bit
Combine deux valeurs (ou plus) bit par bit : un bit du résultat vaut 1 dès qu'il vaut 1 dans au moins un opérande, ce qui permet d'activer des indicateurs sans toucher aux autres.
Syntaxe
%BITOR(expression1 : expression2)
%BITOR(expression1 : expression2 : expression3 …)
expression1, expression2…- Les valeurs à combiner : des entiers ou des zones caractère. Au moins deux opérandes, davantage si besoin.
- Résultat
- Pour des entiers : le nombre dont les bits sont à 1 s'ils le sont dans au moins un opérande. Pour des zones caractère : une chaîne de la longueur du plus long opérande, calculée octet par octet.
À quoi ça sert
Quand plusieurs droits ou options sont rangés dans un seul entier, %BITOR sert à en ajouter un : droits = %bitor(droits : ECRITURE). Les autres bits ne bougent pas, et l'opération est sans danger si le bit était déjà à 1.
Il permet aussi de construire une valeur à partir de constantes nommées, comme le font les API qui attendent une somme d'options.
Exemple 1 : Ajouter des droits
**free
// %BITOR : activer des bits dans un mot de droits, sans toucher aux autres.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-c LECTURE 1;
dcl-c ECRITURE 2;
dcl-c SUPPRESS 4;
dcl-s droits uns(10) inz(0);
snd-msg 'Depart : [' + %char(droits) + ']';
droits = %bitor(droits : LECTURE);
snd-msg '+ lecture : [' + %char(droits) + ']';
// Ajouter plusieurs droits d'un coup
droits = %bitor(droits : ECRITURE : SUPPRESS);
snd-msg '+ ecr + suppr : [' + %char(droits) + ']';
// Activer un bit deja actif ne change rien
droits = %bitor(droits : LECTURE);
snd-msg '+ lecture (encore): [' + %char(droits) + ']';
// Piege : additionner au lieu de faire un OU casse le mot de droits
droits = droits + LECTURE;
snd-msg 'droits + lecture : [' + %char(droits) + ']';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Depart : [0]
+ lecture : [1]
+ ecr + suppr : [7]
+ lecture (encore): [7]
droits + lecture : [8]
On part de 0 et on ajoute la lecture (1), puis l'écriture (2) et la suppression (4) en un seul appel : 7. Ajouter une seconde fois la lecture ne change rien. La dernière ligne montre la différence avec l'addition : 7 + 1 fait 8, un autre droit.
Exemple 2 : OU sur des octets
**free
// %BITOR sur des zones caracteres : OU logique octet par octet.
ctl-opt dftactgrp(*no) actgrp(*new);
// API C standard : convertit des octets en texte hexadecimal
dcl-pr cvthc extproc('cvthc');
cible pointer value;
source pointer value;
longueur int(10) value;
end-pr;
dcl-s res1 char(1);
dcl-s res3 char(3);
dcl-s res4 char(4);
res1 = %bitor(x'F0' : x'05');
snd-msg 'F0 | 05 : ' + hex(%addr(res1) : 1);
res4 = %bitor(x'12000000' : x'00340000' : x'00005600');
snd-msg '3 operandes : ' + hex(%addr(res4) : 4);
// Longueurs differentes
res3 = %bitor(x'000000' : x'F0');
snd-msg '000000 | F0 : ' + hex(%addr(res3) : 3);
res3 = %bitor(x'AAAAAA' : x'0F');
snd-msg 'AAAAAA | 0F : ' + hex(%addr(res3) : 3);
*inlr = *on;
dcl-proc hex;
dcl-pi *n varchar(16);
adresse pointer value;
longueur int(10) value;
end-pi;
dcl-s texte char(16);
cvthc(%addr(texte) : adresse : longueur * 2);
return %subst(texte : 1 : longueur * 2);
end-proc;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
F0 | 05 : F5
3 operandes : 12345600
000000 | F0 : F00000
AAAAAA | 0F : AFAAAA
F0 ou 05 donne F5. Avec trois opérandes, chacun apporte ses octets : 12000000, 00340000 et 00005600 se combinent en 12345600. Quand les longueurs diffèrent, le résultat a la longueur du plus long et les octets sans vis-à-vis sont recopiés tels quels (AAAAAA et 0F donnent AFAAAA).
Le piège
Ne remplacez pas un OU par une addition. droits + LECTURE donne le même résultat que %bitor tant que le bit est absent, puis dérive dès qu'il est déjà présent : sur 7, l'addition renvoie 8, c'est-à-dire un tout autre droit, alors que %bitor(7 : 1) renvoie 7.