Using %BITAND to Test Bits

Q. I have an interface program that has several single position character fields. Each field had has eight sub fields (each bit has a different meaning). In my old thinking I would have used TESTB and tested each bit assigning a different indicator per bit:

C                   TestB     '0'           HexVal                   01
C TestB '1' HexVal 02
C TestB '2' HexVal 03
C TestB '3' HexVal 04
C TestB '4' HexVal 05
C TestB '5' HexVal 06
C TestB '6' HexVal 07
C TestB '7' HexVal 08

I have reviewed the %BITAND function, which is what IBM says maps to free form, but I just don’t understand it. I have done lots of Google searches and found a few examples but I must admit I don’t understand them. I’m trying to use free form RPG, and I really don’t want to use indicators.

A. TESTB and %BITAND are not directly correspondable, so I can understand your confusion.

The RPG Reference says, “%BITAND returns the bit-wise ANDing of the bits of all the arguments. That is, the result bit is ON when all of the corresponding bits in the arguments are ON, and OFF otherwise.” That’s pretty obtuse if you’re not a computer scientist.

Let’s assume you have two single-byte character fields. One has a bit pattern of 01100110 and the other has a bit pattern of 11110001. If you bit-wise AND the the bits of the two fields, the result is 01100000. That is, if a corresponding bit is ‘1’ in BOTH of the fields, the result bit will also be ‘1’ — in any other case, the result bit will be ‘0’.

Understanding that, we can use %BITAND to emulate TESTB. We must first define a few constants that reflect the bit pattern we want to test. In your case, you asked about testing each bit separately, so we can define eight constants. Then, it’s just a matter of individually %BITANDing your test character with each of the constants, and checking to see if the result matches the constant.

The following program accepts a single character parameter, and returns messages regarding the bit test results for that character. So you might call it with

CALL MYPGM 'F'

and the results would be:

Bit 0 is *On
Bit 1 is *On
Bit 2 is *Off
Bit 3 is *Off
Bit 4 is *Off
Bit 5 is *On
Bit 6 is *On
Bit 7 is *Off

because “F” has a bit pattern of 11000110.

  // ----------------------------- Main procedure PR/PI
D Main PR Extpgm('MYPGM')
D 1 CONST

D Main PI
D Hexval 1 CONST

// ---------------------------------------- Constants
// Bit0 = 10000000
// Bit1 = 01000000
// Bit2 = 00100000
// Bit3 = 00010000
// Bit4 = 00001000
// Bit5 = 00000100
// Bit6 = 00000010
// Bit7 = 00000001

D Bit0 C X'80'
D Bit1 C X'40'
D Bit2 C X'20'
D Bit3 C X'10'
D Bit4 C X'08'
D Bit5 C X'04'
D Bit6 C X'02'
D Bit7 C X'01'

/Free
If %Bitand(Hexval:Bit0) = Bit0;
Dsply 'Bit 0 is *On';
Else;
Dsply 'Bit 0 is *Off';
Endif;

If %Bitand(Hexval:Bit1) = Bit1;
Dsply 'Bit 1 is *On';
Else;
Dsply 'Bit 1 is *Off';
Endif;

If %Bitand(Hexval:Bit2) = Bit2;
Dsply 'Bit 2 is *On';
Else;
Dsply 'Bit 2 is *Off';
Endif;

If %Bitand(Hexval:Bit3) = Bit3;
Dsply 'Bit 3 is *On';
Else;
Dsply 'Bit 3 is *Off';
Endif;

If %Bitand(Hexval:Bit4) = Bit4;
Dsply 'Bit 4 is *On';
Else;
Dsply 'Bit 4 is *Off';
Endif;

If %Bitand(Hexval:Bit5) = Bit5;
Dsply 'Bit 5 is *On';
Else;
Dsply 'Bit 5 is *Off';
Endif;

If %Bitand(Hexval:Bit6) = Bit6;
Dsply 'Bit 6 is *On';
Else;
Dsply 'Bit 6 is *Off';
Endif;

If %Bitand(Hexval:Bit7) = Bit7;
Dsply 'Bit 7 is *On';
Else;
Dsply 'Bit 7 is *Off';
Endif;

*Inlr = *On;
Return;
/End-free

If you wanted to check multiple bits in a single test, it would be a simple matter of defining additional constants that matched the bit pattern you wanted to test. For example if you wanted to test bits 0 and 4, you’d define a constant with a value of X’88’ (bit pattern 10001000).