In the example of section 9.5, routines were presented to print out a cardinal value as a binary numeral by interpreting it as a BITSET using a CAST. A non-discriminated union can be employed instead, and that example re-coded as below.

MODULEShiftDemo2; (* Written by R.J. Sutcliffe *) (* to demonstrate the use of packedset *) (* using ISO standard Modula-2 *) (* last revision 1994 03 01 *)FROMSTextIOIMPORTWriteString, WriteLn, SkipLine, ReadChar, WriteChar;FROMSWholeIOIMPORTWriteCard, ReadCard;FROMSYSTEMIMPORTBITSPERLOC,SHIFT,ROTATE;CONSTmaxBitNum =BITSPERLOC*SIZE(CARDINAL) - 1;TYPECardSet =PACKEDSETOF[0..maxBitNum]; Card =RECORDCASE:BOOLEANOF(* undiscriminated variant *)TRUE: c :CARDINAL|FALSE: s : CardSetENDEND;PROCEDUREWriteCardBin (num: Card);VARcount :CARDINAL;BEGINFORcount := maxBitNumTO0BY-1DOIFcountINnum.sTHENWriteCard (1,1)ELSEWriteCard (0,1)END;IFcountMOD8 = 0 (* break into groups of 8 bits *)THENWriteChar (" ");END;END;ENDWriteCardBin;VARtheNumber : Card; answer :CHAR; again :BOOLEAN;BEGINWriteString ("This program illustrates bit shifting "); WriteLn;REPEATWriteString ("Enter the number to be shifted "); ReadCard (theNumber.c); SkipLine; WriteLn; WriteString ("The cardinal "); WriteCard (theNumber.c, 0); WriteString (" binary: "); WriteCardBin (theNumber); WriteLn; WriteString ("Shifted one position right yields "); theNumber.s :=SHIFT(theNumber.s, -1); WriteCard (theNumber.c, 0); WriteString (" binary: "); WriteCardBin (theNumber); WriteLn; WriteString ("and, then rotated one position right yields "); theNumber.s :=ROTATE(theNumber.s, -1); WriteCard (theNumber.c, 0); WriteString (" binary: "); WriteCardBin (theNumber); WriteLn; WriteString ("Do another? Y/N "); ReadChar (answer); SkipLine; again := (CAP(answer) = "Y");UNTILNOTagain;ENDShiftDemo2.

In addition, the binary printing routines could be altered to print in hexadecimal by putting hexadecimal digits together one at a time starting from the most significant bits in the bitset representation of a number. Here is a short demonstration program. Note the additional use of the case statement for the printing of each hexadecimal digit. It must distinguish between the case of decimal digits and non-decimal digits.

MODULEHexDemo; (* Written by R.J. Sutcliffe *) (* to demonstrate the use of variant records and case statements *) (* using ISO standard Modula-2 *) (* last revision 1995 03 24 *)FROMSTextIOIMPORTWriteString, WriteLn, SkipLine, ReadChar, WriteChar;FROMSWholeIOIMPORTWriteCard, ReadCard;FROMSYSTEMIMPORTBITSPERLOC;CONSTmaxBitNum =BITSPERLOC*SIZE(CARDINAL) - 1;TYPE(* allow interpretation of a cardinal as a set without casting *) Hex =CARDINAL[0..15]; BitCount = [0..maxBitNum]; CardSet =PACKEDSETOFBitCount; Card =RECORDCASE:BOOLEANOF(* undiscriminated variant *)TRUE: c :CARDINAL|FALSE: s : CardSetENDEND;PROCEDUREWriteCardBin (num: Card);VARcount :CARDINAL;BEGINFORcount := maxBitNumTO0BY-1DOIFcountINnum.sTHENWriteCard (1,1)ELSEWriteCard (0,1)END;IFcountMOD8 = 0 (* break into groups of 8 bits *)THENWriteChar (" ");END;END;ENDWriteCardBin;PROCEDUREWriteHexDigit (digit : Hex);BEGINCASEdigitOF0..9: (* numeric hex digit *) WriteChar (CHR(ORD("0") + digit));ELSE(* 10 -- 15 or A to E digits *) WriteChar (CHR(ORD("A") + digit - 10));END;ENDWriteHexDigit;PROCEDUREWriteCardHex (num: Card);VARcount, tcount :CARDINAL; temp : Card;BEGINtemp.c := 0; (* holder for four bits at a time *) tcount:= 4; (* count down from most significant bit *)FORcount := maxBitNumTO0BY-1DODEC(tcount); (* so, we actually start at three *)IFcountINnum.sTHEN(* transfer four bits to the temporary item *)INCL(temp.s, tcount)END;IFcountMOD4 = 0 (* break into nibbles *)THENWriteHexDigit (temp.c); (* and go print one digit *) temp.c := 0; (* now, reset for the next nibble *) tcount:= 4; (* and reset the count too *)END;END;ENDWriteCardHex;VAR(* main *) card : Card; answer :CHAR; again :BOOLEAN;BEGIN(* main *) WriteString ("This program illustrates binary and hex output "); WriteLn;REPEATWriteString ("Enter a cardinal number to be printed "); ReadCard (card.c); SkipLine; WriteString ("The cardinal "); WriteCard (card.c, 0); WriteString (" in binary is: "); WriteCardBin (card); WriteString (" and in hex is: "); WriteCardHex (card); WriteLn; WriteString ("Do another? Y/N "); ReadChar (answer); SkipLine; WriteLn; again := (CAP(answer) = "Y");UNTILNOTagain;ENDHexDemo.

Selected output from a run of this program follows to illustrate its correctness. As usual, user inputs are in bold.

This program illustrates binary and hexadecimal output Enter a cardinal number to be printed1The cardinal 1 in binary is: 00000000 00000000 00000000 00000001 and in hex is: 00000001 Do another? Y/NyEnter a cardinal number to be printed14The cardinal 14 in binary is: 00000000 00000000 00000000 00001110 and in hex is: 0000000E Do another? Y/NyEnter a cardinal number to be printed65535The cardinal 65535 in binary is: 00000000 00000000 11111111 11111111 and in hex is: 0000FFFF Do another? Y/NyEnter a cardinal number to be printed31415The cardinal 31415 in binary is: 00000000 00000000 01111010 10110111 and in hex is: 00007AB7 Do another? Y/NyEnter a cardinal number to be printed4294967295The cardinal 4294967295 in binary is: 11111111 11111111 11111111 11111111 and in hex is: FFFFFFFF Do another? Y/Nn

The reader will note that the implementation employed happened to use a thirty-two bit or eight hexadecimal digit representation for its cardinals, but that the program itself should work regardless of this, because of the way it is crafted.