Aller au contenu

%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.