DIRECTORY Basics, Basics16, OSMiscOps USING [Copy], Rope USING [Fetch, Length, ROPE, Text, TextRep], SafeStorage USING [GetSystemZone], TargetConversions, TargetConversionsPrivate; TargetConversionsImpl: CEDAR PROGRAM IMPORTS Basics, Basics16, OSMiscOps, Rope, SafeStorage EXPORTS TargetConversions SHARES Rope = BEGIN OPEN TargetConversions, TargetConversionsPrivate; ByteSequence: TYPE = Rope.ROPE; Reader: TYPE = REF ReaderRep; ReaderRep: PUBLIC TYPE = TargetConversionsPrivate.ReaderRep; Writer: TYPE = REF WriterRep; WriterRep: PUBLIC TYPE = TargetConversionsPrivate.WriterRep; Word: TYPE = Bits32; nullWord: Word = LOOPHOLE[LONG[0]]; bytesPerWord: NAT = LAST[ByteLength]; z: ZONE ¬ SafeStorage.GetSystemZone[]; InsufficientBits: PUBLIC ERROR = CODE; InvalidArgument: PUBLIC ERROR = CODE; NotImplemented: PUBLIC ERROR = CODE; NotAligned: PUBLIC ERROR = CODE; Card32ToBits32: PROC [c: Card32] RETURNS [Bits32] = INLINE { RETURN [LOOPHOLE[Basics.FFromCard32[c]]]; }; CharToBits32: PROC [c: CHAR] RETURNS [Bits32] = INLINE { RETURN [LOOPHOLE[Bytes[0, 0, 0, c.ORD]]]; }; Int32ToBits32: PROC [i: Int32] RETURNS [Bits32] = INLINE { RETURN [LOOPHOLE[Basics.FFromInt32[i]]]; }; Real32ToBits32: PROC [r: Real32] RETURNS [Bits32] = INLINE { RETURN [LOOPHOLE[Basics.FFromInt32[LOOPHOLE[r]]]]; }; BytesToBits32: PROC [bytes: Bytes] RETURNS [Bits32] = INLINE { RETURN [LOOPHOLE[bytes]]; }; Bits32ToCard32: PROC [b: Bits32] RETURNS [Card32] = INLINE { RETURN [Basics.Card32FromF[LOOPHOLE[b]]]; }; Bits32ToChar: PROC [b: Bits32] RETURNS [CHAR] = INLINE { bytes: Bytes = LOOPHOLE[b]; RETURN [VAL[bytes[0]]]; }; Bits32ToInt32: PROC [b: Bits32] RETURNS [Int32] = INLINE { RETURN [Basics.Int32FromF[LOOPHOLE[b]]]; }; Bits32ToReal32: PROC [b: Bits32] RETURNS [Real32] = INLINE { RETURN [LOOPHOLE[Basics.Int32FromF[LOOPHOLE[b]]]]; }; Bits32ToBytes: PROC [b: Bits32] RETURNS [Bytes] = INLINE { RETURN [LOOPHOLE[b]]; }; CharToByte: PROC [c: CHAR] RETURNS [BYTE] = INLINE { RETURN [ORD[c]]; }; ByteToChar: PROC [b: BYTE] RETURNS [CHAR] = INLINE { RETURN [VAL[b]]; }; bank: CARD = 65536; bigEndianOrder: Bytes = LOOPHOLE[(1*bank)+(2*256+3)]; littleEndianOrder: Bytes = LOOPHOLE[(3*256*bank+2*bank)+(1*256)]; princOpsOrder: Bytes = LOOPHOLE[(2*256*bank+3*bank)+(1)]; byteOrder: Bytes = [0, 1, 2, 3]; Half: TYPE = PACKED ARRAY [0..bitsPerHalf) OF [0..1]; bitsPerHalf: NAT = bitsPerWord/2; nullHalf: Half = LOOPHOLE[0]; onesHalf: Half = LOOPHOLE[177777B]; Halves: TYPE = PACKED ARRAY [0..1] OF Half; HalfShift: PROC [x: Half, len: INTEGER] RETURNS [Half] = INLINE { RETURN [LOOPHOLE[Basics16.BITSHIFT[LOOPHOLE[x], len]]]; }; HalfAnd: PROC [x,y: Half] RETURNS [Half] = INLINE { RETURN [LOOPHOLE[Basics16.BITAND[LOOPHOLE[x], LOOPHOLE[y]]]]; }; HalfOr: PROC [x,y: Half] RETURNS [Half] = INLINE { RETURN [LOOPHOLE[Basics16.BITOR[LOOPHOLE[x], LOOPHOLE[y]]]]; }; WordAnd: PROC [x,y: Word] RETURNS [Word] = INLINE { RETURN [LOOPHOLE[Basics.BITAND[LOOPHOLE[x], LOOPHOLE[y]]]]; }; WordOr: PROC [x,y: Word] RETURNS [Word] = INLINE { RETURN [LOOPHOLE[Basics.BITOR[LOOPHOLE[x], LOOPHOLE[y]]]]; }; BitOffsetInByte: PROC [bits: INT] RETURNS [[0..7]] = INLINE { RETURN [Basics16.BITAND[7, Basics.LowHalf[LOOPHOLE[bits]]]]; }; BitOffsetInWord: PROC [bits: INT] RETURNS [BitIndex] = INLINE { RETURN [Basics16.BITAND[LAST[BitIndex], Basics.LowHalf[LOOPHOLE[bits]]]]; }; ShiftBitsLeft: PROC [word: Word, shift: BitLength] RETURNS [Word] = --INLINE-- { halves: Halves ¬ LOOPHOLE[word, Halves]; halves[0] ¬ HalfOr[HalfShift[halves[0], shift], HalfShift[halves[1], shift-bitsPerHalf]]; halves[1] ¬ HalfShift[halves[1], shift]; RETURN [LOOPHOLE[halves]]; }; ShiftBitsRight: PROC [word: Word, shift: BitLength] RETURNS [Word] = --INLINE-- { halves: Halves ¬ LOOPHOLE[word, Halves]; halves[1] ¬ HalfOr[HalfShift[halves[1], -shift], HalfShift[halves[0], bitsPerHalf-shift]]; halves[0] ¬ HalfShift[halves[0], -shift]; RETURN [LOOPHOLE[halves]]; }; MaskBitsLeft: PROC [bits32: Word, leftBits: BitLength] RETURNS [Word] = --INLINE-- { halves: Halves ¬ LOOPHOLE[bits32, Halves]; SELECT leftBits FROM <= bitsPerHalf => { halves[0] ¬ HalfAnd[halves[0], HalfShift[onesHalf, bitsPerHalf-leftBits]]; halves[1] ¬ nullHalf; }; < bitsPerWord => halves[1] ¬ HalfAnd[halves[1], HalfShift[onesHalf, bitsPerWord-leftBits]]; ENDCASE; RETURN [LOOPHOLE[halves]]; }; BitsToBytes: PROC [bits: CARD] RETURNS [CARD] = INLINE { RETURN [Basics.BITRSHIFT[bits, 3]]; }; SignCheck: PROC [int: Int32, rightBits: BitLength] = { SELECT rightBits FROM 0 => ERROR InvalidArgument; < bitsPerWord => { limit: Int32 = Bits32ToInt32[ShiftBitsLeft[Int32ToBits32[1], rightBits-1]]; IF int NOT IN [-limit..limit) THEN ERROR InvalidArgument; }; ENDCASE; }; SignExtend: PROC [int: Int32, rightBits: BitLength] RETURNS [Int32] = { bits32: Bits32 ¬ Int32ToBits32[int]; SELECT rightBits FROM 0 => ERROR InvalidArgument; < bitsPerWord => { signBitOn: Bits32 ¬ nullBits32; signIndex: BitIndex ¬ bitsPerWord-rightBits; signBitOn[signIndex] ¬ 1; bits32[signIndex] ¬ ORD[NOT VAL[bits32[signIndex]]]; int ¬ Bits32ToInt32[Card32ToBits32[Bits32ToCard32[bits32]-Bits32ToCard32[signBitOn]]]; }; ENDCASE; RETURN [int]; }; EnsureBytes: PROC [writer: Writer, bytes: NAT] RETURNS [REF TEXT] = { buffer: REF TEXT ¬ writer.buffer; bufLen: NAT ¬ bytes; IF bytes > buffer.maxLength THEN TRUSTED { oldLen: NAT ¬ buffer.length; newLen: NAT ¬ IF bytes > LAST[NAT]/2 THEN bytes+256 ELSE bytes*2; new: REF TEXT ¬ z.NEW[TEXT[newLen]]; new.length ¬ bytes; OSMiscOps.Copy[ from: LOOPHOLE[buffer, LONG POINTER] + SIZE[TEXT[0]], nwords: WORDS[TEXT[oldLen]] - WORDS[TEXT[0]], to: LOOPHOLE[new, LONG POINTER] + SIZE[TEXT[0]]]; writer.buffer ¬ buffer ¬ new; }; RETURN [buffer]; }; FlushWriterWord: PROC [writer: Writer] = { IF writer.dirty THEN { word: Bits32 = writer.partialWord; buffer: REF TEXT; bytes: Bytes ¬ Bits32ToBytes[word]; bits: INT ¬ writer.bitPos; offset: BitIndex = BitOffsetInWord[bits]; bPos: CARDINAL; IF offset # 0 THEN bits ¬ bits - offset; bPos ¬ BitsToBytes[bits]; buffer ¬ EnsureBytes[writer, bPos+bytesPerWord]; TRUSTED { OSMiscOps.Copy[ from: @bytes, nwords: WORDS[Bytes], to: LOOPHOLE[buffer, LONG POINTER] + SIZE[TEXT[bPos]]]; }; writer.dirty ¬ FALSE; }; }; AdvanceWriterPos: PROC [writer: Writer, new: INT] = { newOffset: BitIndex ¬ BitOffsetInWord[new]; old: INT ¬ writer.bitPos; oldOffset: BitIndex ¬ BitOffsetInWord[old]; buffer: REF TEXT ¬ writer.buffer; IF new > writer.bitsWritten THEN writer.bitsWritten ¬ new; IF (new-newOffset) # (old-oldOffset) THEN { IF writer.dirty THEN FlushWriterWord[writer]; IF new >= writer.bitsWritten THEN { bPos: INT ¬ BitsToBytes[new+(bitsPerWord-1)]; buffer ¬ EnsureBytes[writer, bPos]; writer.partialWord ¬ nullWord; buffer.length ¬ bPos; } ELSE { bPos: NAT ¬ BitsToBytes[new-newOffset]; bytes: Bytes ¬ nullBytes; TRUSTED { OSMiscOps.Copy[ from: LOOPHOLE[buffer, LONG POINTER] + SIZE[TEXT[bPos]], nwords: WORDS[Bytes], to: @bytes]; }; writer.partialWord ¬ BytesToBits32[bytes]; }; }; writer.bitPos ¬ new; }; PutBits32: PROC [writer: Writer, bits32: Bits32, start: BitIndex, bits: BitLength, mask: BOOL ¬ FALSE] = { IF bits # 0 THEN { pos: INT ¬ writer.bitPos; offset: BitIndex ¬ BitOffsetInWord[pos]; rem: NAT ¬ (bitsPerWord-offset); IF start+bits > bitsPerWord THEN ERROR InvalidArgument; IF start # 0 THEN bits32 ¬ ShiftBitsLeft[bits32, start]; IF mask THEN bits32 ¬ MaskBitsLeft[bits32, bits]; IF offset # 0 THEN { writer.partialWord ¬ WordOr[writer.partialWord, ShiftBitsRight[bits32, offset]]; writer.dirty ¬ TRUE; bits32 ¬ ShiftBitsLeft[bits32, rem]; IF bits < rem THEN { new: INT ¬ writer.bitPos ¬ pos + bits; IF new > writer.bitsWritten THEN writer.bitsWritten ¬ new; RETURN; }; AdvanceWriterPos[writer, pos ¬ pos + rem]; bits ¬ bits - rem; }; IF bits # 0 THEN { writer.partialWord ¬ bits32; writer.dirty ¬ TRUE; AdvanceWriterPos[writer, pos ¬ pos + bits]; }; }; }; GetBits32: PROC [reader: Reader, start: BitIndex, len: BitLength] RETURNS [bits32: Bits32 ¬ nullBits32] = { IF len # 0 THEN { offset: BitIndex ¬ BitOffsetInWord[reader.bitsRead]; rem: NAT = bitsPerWord - offset; bitsAvail: INT = reader.bitsLength-reader.bitsRead; index: INT ¬ reader.bytesRead; lastByteIndex: INT ¬ reader.lastByteIndex; IF bitsAvail < len THEN ERROR InsufficientBits; IF start+len > bitsPerWord THEN ERROR InvalidArgument; bits32 ¬ MaskBitsLeft[ShiftBitsLeft[reader.partialWord, offset], len]; IF len > rem THEN { ReadAhead[reader]; bits32 ¬ WordOr[bits32, ShiftBitsRight[reader.partialWord, len-rem]]; IF start+len # bitsPerWord THEN bits32 ¬ MaskBitsLeft[bits32, len]; }; IF start # 0 THEN bits32 ¬ ShiftBitsRight[bits32, start]; reader.bitsRead ¬ reader.bitsRead + len; IF BitOffsetInWord[reader.bitsRead] = 0 THEN ReadAhead[reader]; }; }; ReadAhead: PROC [reader: Reader] = { index: INT ¬ reader.bytesRead; lastByteIndex: INT ¬ reader.lastByteIndex; bytes: Bytes ¬ nullBytes; FOR i: ByteIndex IN ByteIndex DO x: INT ¬ index+i; IF x > lastByteIndex THEN EXIT; bytes[i] ¬ CharToByte[Rope.Fetch[reader.buffer, x]]; reader.bytesRead ¬ x+1; ENDLOOP; reader.partialWord ¬ BytesToBits32[bytes]; }; Bits32ToByteSequence: PROC [bits32: Bits32, start: BitIndex, len: BitLength, mask: BOOL ¬ FALSE] RETURNS [ByteSequence ¬ NIL] = { IF start # 0 THEN bits32 ¬ ShiftBitsLeft[bits32, start]; IF mask THEN bits32 ¬ MaskBitsLeft[bits32, len]; IF len # 0 THEN { bytes: Bytes = Bits32ToBytes[bits32]; byteLen: ByteLength = (len+7)/8; new: Rope.Text ¬ z.NEW[Rope.TextRep[byteLen]]; new.length ¬ byteLen; FOR i: NAT IN [0..byteLen) DO new[i] ¬ ByteToChar[bytes[i]]; ENDLOOP; RETURN [new]; }; }; ByteSequenceToBits32: PROC [seq: ByteSequence, start: BitIndex, len: BitLength] RETURNS [bits32: Bits32 ¬ nullBits32] = { bytes: Bytes ¬ nullBytes; byteLen: ByteLength = (len+7)/8; IF byteLen > Rope.Length[seq] THEN ERROR InvalidArgument; FOR i: NAT IN [0..byteLen) DO bytes[i] ¬ CharToByte[Rope.Fetch[seq, i]]; ENDLOOP; bits32 ¬ BytesToBits32[bytes]; SELECT start+len FROM > bitsPerWord => ERROR InvalidArgument; < bitsPerWord => IF len MOD 8 # 0 THEN bits32 ¬ MaskBitsLeft[bits32, len]; ENDCASE; IF start # 0 THEN bits32 ¬ ShiftBitsRight[bits32, start]; }; NewWriter: PUBLIC PROC RETURNS [Writer] = { RETURN [NEW[WriterRep ¬ [bitsWritten: 0, partialWord: nullWord, dirty: FALSE, buffer: z.NEW[TEXT[16]]]]]; }; ResetWriter: PUBLIC PROC [writer: Writer] = { writer.bitsWritten ¬ writer.bitPos ¬ 0; writer.partialWord ¬ nullWord; writer.buffer.length ¬ 0; writer.dirty ¬ FALSE; }; WriterContents: PUBLIC PROC [writer: Writer] RETURNS [ByteSequence ¬ NIL] = { nB: NAT = BitsToBytes[writer.bitsWritten+7]; IF writer.dirty THEN FlushWriterWord[writer]; -- force out the partial word IF nB # 0 THEN TRUSTED { overhead: NAT = SIZE[TEXT[0]]; contents: Rope.Text ¬ z.NEW[Rope.TextRep[nB]]; contents.length ¬ nB; OSMiscOps.Copy[ from: LOOPHOLE[writer.buffer, LONG POINTER] + overhead, nwords: WORDS[TEXT[nB]] - WORDS[TEXT[0]], to: LOOPHOLE[contents, LONG POINTER] + overhead]; RETURN [contents]; }; }; BitsWritten: PUBLIC PROC [writer: Writer] RETURNS [INT] = { RETURN [writer.bitsWritten]; }; PutBool: PUBLIC PROC [writer: Writer, bool: Bool] = { PutBits32[writer, Card32ToBits32[ORD[bool]], bitsPerWord-1, 1]; }; PutByteSeq: PUBLIC PROC [writer: Writer, seq: ByteSequence, len: INT] = { IF len > 0 THEN { buffer: REF TEXT = EnsureBytes[writer, len]; offset: BitIndex = BitOffsetInWord[writer.bitsWritten]; IF offset # 0 THEN ERROR NotAligned; FOR i: INT IN [0..len) DO PutBits32[writer, CharToBits32[Rope.Fetch[seq, i]], bitsPerWord-8, 8]; ENDLOOP; }; }; PutCard: PUBLIC PROC [writer: Writer, card: Card32, bits: BitLength] = { IF bits # 0 THEN PutBits32[writer, Card32ToBits32[card], bitsPerWord-bits, bits]; }; PutCard32: PUBLIC PROC [writer: Writer, card: Card32] = { PutBits32[writer, Card32ToBits32[card], 0, bitsPerWord]; }; PutChar: PUBLIC PROC [writer: Writer, char: Char] = { PutBits32[writer, CharToBits32[char], bitsPerWord-8, 8]; }; PutInt: PUBLIC PROC [writer: Writer, int: Int32, bits: BitLength] = { SignCheck[int, bits]; PutBits32[writer, Int32ToBits32[int], bitsPerWord-bits, bits]; }; PutInt32: PUBLIC PROC [writer: Writer, int: Int32] = { PutBits32[writer, Int32ToBits32[int], 0, bitsPerWord]; }; PutPadBits: PUBLIC PROC [writer: Writer, bits: BitLength] = { PutBits32[writer, nullBits32, 0, bits]; }; PutReal: PUBLIC PROC [writer: Writer, real: Real] = { WITH real SELECT FROM real32: real32 Real => PutBits32[writer, Real32ToBits32[real32.real32], 0, bitsPerWord]; ENDCASE => ERROR NotImplemented; }; SetOutputIndex: PUBLIC PROC [writer: Writer, bits: INT] = { SELECT TRUE FROM bits < 0 => ERROR InvalidArgument; BitsToBytes[bits] > (LAST[NAT]-20) => ERROR InvalidArgument; ENDCASE; AdvanceWriterPos[writer, bits]; }; GetOutputIndex: PUBLIC PROC [writer: Writer] RETURNS [INT] = { RETURN [writer.bitPos]; }; NewReader: PUBLIC PROC [seq: ByteSequence, start: INT ¬ 0, len: INT ¬ LAST[INT]] RETURNS [reader: Reader] = { reader ¬ z.NEW[ReaderRep]; InitReader[reader, seq, start, len]; }; InitReader: PUBLIC PROC [reader: Reader, seq: ByteSequence, start: INT ¬ 0, len: INT ¬ LAST[INT]] = { lim: INT = Rope.Length[seq]; IF start < 0 OR start > lim THEN ERROR InvalidArgument; IF len < 0 THEN len ¬ 0 ELSE len ¬ MIN[len, lim-start]; reader­ ¬ [ bitsRead: 0, bytesRead: start, lastByteIndex: start+len-1, bitsLength: len*8, partialWord: nullWord, buffer: seq]; IF reader.bitsLength # 0 THEN ReadAhead[reader]; }; RemainingBits: PUBLIC PROC [reader: Reader] RETURNS [INT] = { RETURN [reader.bitsLength-reader.bitsRead]; }; BitsRead: PUBLIC PROC [reader: Reader] RETURNS [INT] = { RETURN [reader.bitsRead]; }; GetBool: PUBLIC PROC [reader: Reader] RETURNS [Bool] = { bits32: Bits32 = GetBits32[reader, 0, 1]; RETURN [VAL[bits32[0]]]; }; GetByteSequence: PUBLIC PROC [reader: Reader, len: INT] RETURNS [ByteSequence] = { offset: BitIndex ¬ BitOffsetInWord[reader.bitsRead]; IF offset # 0 THEN ERROR NotAligned; IF len > 0 THEN { lim: NAT ¬ len; new: Rope.Text ¬ z.NEW[Rope.TextRep[lim]]; FOR pos: NAT IN [0..lim) DO new[pos] ¬ ByteToChar[Bits32ToBytes[GetBits32[reader, 0, 8]][0]]; ENDLOOP; RETURN [new]; }; RETURN [NIL]; }; GetCard: PUBLIC PROC [reader: Reader, bits: BitLength] RETURNS [Card32 ¬ 0] = { IF bits # 0 THEN { bits32: Bits32 = GetBits32[reader, bitsPerWord-bits, bits]; RETURN [Bits32ToCard32[bits32]]; }; }; GetCard32: PUBLIC PROC [reader: Reader] RETURNS [Card32] = { RETURN [Bits32ToCard32[GetBits32[reader, 0, bitsPerWord]]]; }; GetChar: PUBLIC PROC [reader: Reader] RETURNS [Char] = { RETURN [Bits32ToChar[GetBits32[reader, bitsPerWord-8, 8]]]; }; GetInt: PUBLIC PROC [reader: Reader, bits: BitLength] RETURNS [Int32 ¬ 0] = { IF bits = 0 THEN ERROR InvalidArgument; RETURN [SignExtend[Bits32ToInt32[GetBits32[reader, bitsPerWord-bits, bits]], bits]]; }; GetInt32: PUBLIC PROC [reader: Reader] RETURNS [Int32] = { RETURN [Bits32ToInt32[GetBits32[reader, 0, bitsPerWord]]]; }; SkipPadBits: PUBLIC PROC [reader: Reader, bits: BitLength] = { [] ¬ GetBits32[reader, 0, bits]; }; GetReal: PUBLIC PROC [reader: Reader, kind: RealKind ¬ real32] RETURNS [Real] = { IF kind # real32 THEN ERROR NotImplemented; RETURN [[real32[Bits32ToReal32[GetBits32[reader, 0, bitsPerWord]]]]]; }; SetInputIndex: PUBLIC PROC [reader: Reader, bits: INT] = { offset: BitIndex; SELECT bits FROM < 0, > reader.bitsLength => ERROR InvalidArgument; ENDCASE; offset ¬ BitOffsetInWord[bits]; IF offset # 0 THEN bits ¬ bits - offset; reader.bytesRead ¬ BitsToBytes[bits]; ReadAhead[reader]; IF offset # 0 THEN [] ¬ GetBits32[reader, 0, offset]; }; BoolToByteSeq: PUBLIC PROC [bool: Bool] RETURNS [ByteSequence] = { bits32: Bits32 ¬ nullBits32; bits32[0] ¬ ORD[bool]; RETURN [Bits32ToByteSequence[bits32, 0, 1]]; }; CardToByteSeq: PUBLIC PROC [card: Card32, bits: BitLength] RETURNS [ByteSequence] = { RETURN [Bits32ToByteSequence[Card32ToBits32[card], bitsPerWord-bits, bits]]; }; Card32ToByteSeq: PUBLIC PROC [card: Card32] RETURNS [ByteSequence] = { RETURN [Bits32ToByteSequence[Card32ToBits32[card], 0, bitsPerWord]]; }; CharToByteSeq: PUBLIC PROC [char: Char] RETURNS [ByteSequence] = { bytes: Bytes ¬ nullBytes; bytes[0] ¬ CharToByte[char]; RETURN [Bits32ToByteSequence[BytesToBits32[bytes], 0, 8]]; }; IntToByteSeq: PUBLIC PROC [int: Int32, bits: BitLength] RETURNS [ByteSequence] = { SignCheck[int, bits]; RETURN [Bits32ToByteSequence[Int32ToBits32[int], bitsPerWord-bits, bits]]; }; Int32ToByteSeq: PUBLIC PROC [int: Int32] RETURNS [ByteSequence] = { RETURN [Bits32ToByteSequence[Int32ToBits32[int], 0, bitsPerWord]]; }; RealToByteSeq: PUBLIC PROC [real: Real] RETURNS [ByteSequence] = { WITH real SELECT FROM real32: real32 Real => RETURN [Bits32ToByteSequence[Real32ToBits32[real32.real32], 0, bitsPerWord]]; ENDCASE => ERROR NotImplemented; }; ByteSeqToBool: PUBLIC PROC [seq: ByteSequence] RETURNS [Bool] = { RETURN [VAL[ByteSequenceToBits32[seq, 0, 1][0]]]; }; ByteSeqToCard: PUBLIC PROC [seq: ByteSequence, bits: BitLength] RETURNS [Card32] = { IF bits = 0 THEN ERROR InvalidArgument; RETURN [Bits32ToCard32[ByteSequenceToBits32[seq, bitsPerWord-bits, bits]]]; }; ByteSeqToCard32: PUBLIC PROC [seq: ByteSequence] RETURNS [Card32] = { RETURN [Bits32ToCard32[ByteSequenceToBits32[seq, 0, bitsPerWord]]]; }; ByteSeqToChar: PUBLIC PROC [seq: ByteSequence] RETURNS [Char] = { RETURN [Bits32ToChar[ByteSequenceToBits32[seq, bitsPerWord-8, 8]]]; }; ByteSeqToInt: PUBLIC PROC [seq: ByteSequence, bits: BitLength] RETURNS [Int32] = { IF bits = 0 THEN ERROR InvalidArgument; RETURN [SignExtend[Bits32ToInt32[ByteSequenceToBits32[seq, bitsPerWord-bits, bits]], bits]]; }; ByteSeqToInt32: PUBLIC PROC [seq: ByteSequence] RETURNS [Int32] = { RETURN [Bits32ToInt32[ByteSequenceToBits32[seq, 0, bitsPerWord]]]; }; ByteSeqToReal: PUBLIC PROC [seq: ByteSequence, kind: RealKind ¬ real32] RETURNS [Real] = { IF kind # real32 THEN ERROR NotImplemented; RETURN [[real32[Bits32ToReal32[ByteSequenceToBits32[seq, 0, bitsPerWord]]]]]; }; END. : TargetConversionsImpl.mesa Copyright Σ 1986, 1988, 1991 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) July 26, 1988 1:20:35 am PDT Willie-s, September 24, 1991 4:50 pm PDT This implementation is customized to Dragon, although I hope to have shown where other machines can be plugged in. In the external implementation more significant bytes are put out before less significant bytes for multi-byte numbers. This implementation assumes that in the declaration PACKED ARRAY Index OF BOOL the more significant bits have lower indexes than the less significant bits. We also assume that the representations for packed arrays that occupy bitsPerWord bits can be freely overlaid EXCEPT for packed arrays where the element size is bitsPerWord bits. Types & constants Temporary Global variables The zone for all allocations in the intermediate code phase. In the non-Cedar world this becomes an UNCOUNTED ZONE. Exceptions Raised when a Get& operation is called and not enough bits remain in the reader to deliver the value. Raised when an argument is illegal. Raised when an operation calls for a translation not supported by the implementation (as in use of Real when the kind is not real32). Raised when an operation needs at least byte alignment and the stream is not byte aligned. Internal Conversions Utilities Useful for fixing up byte order Sign extension, with the assumption that the left bits (bitsPerWord-rightBits) are all zeros. The old partial word is no longer valid Writing to extend the length We need to get a new partial word from the buffer Puts out the given unsigned number using the low-order BitLength bits. There are already bits in the output buffer No need yet to force out a complete word. Aligned and stuff to move into the partial word. The valid bits are all left-justified, other bits are 0s We must read some more to get enough At this point bits32 is left-justified, and right-padded with 0s. We exhausted the bits in the partial word, so we need some more Bit Stream Writers Returns a new bit stream writer with no bits. Resets the writer to ground zero, but retains intermediate storage for the sake of efficiency. Returns the byte sequence corresponding to the currently written contents of the given writer. NIL will be returned if there are no bits in the stream. Returns the number of bits currently written to the stream. Useful for hairy alignment problems not covered by PutAlignment. Puts out the given 1-bit boolean value. Puts out the first len bytes of the given byte sequence. Puts out the given unsigned number using the low-order BitLength bits. Puts out the given bitsPerWord-bit unsigned number. PutCard32[w, c] is the same as (but faster than) PutCard[w, c, bitsPerWord]. Puts out the given character. Puts out the given signed number using the low-order bits of int. The given Int32 number must have correct sign extension (not currently checked for). Puts out the given bitsPerWord-bit signed number. PutInt32[w, i] is the same as (but faster than) PutInt[w, i, bitsPerWord]. Puts out the requested number of padding bits. Puts out the given Real. Sets the bit position in the writer. Returns the bit position in the writer. Bit Stream Readers Returns a new bit stream Reader with initial contents given by the ByteSequence. Initializes an existing Reader with contents given by the ByteSequence. Returns the number of remaining bits in the reader. Returns the number of remaining bits read from the reader. Reads a 1-bit boolean value. Reads a sequence of bytes, len gives the number of bytes. Reads an unsigned number, # of bits given by BitLength. Reads a bitsPerWord-bit unsigned number. Reads an 8-bit character. Reads a signed number, # of bits given by BitLength, and properly extends the sign (if necessary). Reads a bitsPerWord-bit signed number. Skips a given number of padding bits. Reads an IEEE floating-point number with the specified number of bits. Sets the bit position in the reader. Simple Types to Byte Sequences These operations are present for efficiency. An operation of the form &ToByteSeq[&&] has the same behavior (more or less) as: {w: Writer _ NewWriter[]; Put&[w, &&]; RESULT[BitStreamToByteSeq[w]]}; Byte Sequences to Simple Types These operations are present for efficiency. An operation of the form val _ ByteSeqTo&[&&] has the same behavior (more or less) as: val _ Get&[NewReader[&&]]; Κ”–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ Οeœ=™HK™0K™(—˜šΟk ˜ Kšœ˜Kšœ ˜ Kšœ žœ˜Kšœžœžœ˜0Kšœ žœ˜"Kšœ˜Kšœ˜——K˜šΟnœžœž˜$Kšžœ.˜6Kšžœ˜Kšžœ˜ Kšœžœžœ-˜:K˜Kšœr™rK™K™wK™Kš œ4žœžœžœžœ½žœ>™ΟK˜—head2™šœžœžœ˜Kšœ ™ K˜—Kšœžœžœ ˜šœ žœžœ&˜Kšžœžœ ˜K˜K˜—šŸœžœ žœ žœ˜˜>K˜K˜—šŸœž œ!˜6Kšœ}™}Kšœ6˜6K˜K˜—šŸ œž œ&˜=Kšœ.™.Kšœ'˜'K˜K™—šŸœž œ!˜5Kšœ™šžœžœž˜KšœX˜XKšžœžœ˜ —K˜K˜—šŸœž œžœ˜;Kšœ$™$šžœžœž˜Kšœ žœ˜"Kšœžœžœ žœ˜Kšœ'™'Kšžœ˜K˜K˜——™šŸ œžœžœžœ žœžœžœžœ˜mKšœP™PKšœ žœ ˜Kšœ$˜$K˜K˜—šŸ œžœžœ,žœ žœžœžœ˜eKšœG™GKšœžœ˜Kšžœ žœ žœžœ˜7Kšžœ žœ žœžœ˜7šœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ —Kšžœžœ˜0K˜K˜—š Ÿ œžœžœžœžœ˜=Kšœ3™3Kšžœ%˜+K˜K˜—š Ÿœžœžœžœžœ˜8Kšœ:™:Kšžœ˜K˜K˜—šŸœžœžœžœ ˜8K™Kšœ)˜)Kšžœžœ ˜K˜K˜—š Ÿœžœžœžœžœ˜RK™9Kšœ4˜4Kšžœ žœžœ ˜$šžœ žœ˜Kšœžœ˜Kšœžœ˜*šžœžœžœ ž˜KšœA˜AKšžœ˜—Kšžœ˜ K˜—Kšžœžœ˜ K˜K˜—šŸœžœžœ#žœ˜OKšœ7™7šžœ žœ˜Kšœ;˜;Kšžœ˜ K˜—K˜K˜—šŸ œžœžœžœ ˜K™%Kšœ ˜ Kšœ˜K˜—šŸœžœžœ+žœ ˜QKšœ žœ9™FKšžœžœžœ˜+Kšžœ?˜EK˜K˜—šŸ œžœžœžœ˜:Kšœ$™$Kšœ˜šžœž˜Kšœžœ˜2Kšžœ˜—Kšœ˜Kšžœ žœ˜(Kšœ%˜%Kšœ˜Kšžœ žœ#˜5K˜K˜——šœ™šœ~™~Kšœ'žœ™FK™—šŸ œžœžœžœ˜BKšœ˜Kšœ žœ˜Kšžœ&˜,K˜—K˜šŸ œžœžœ!žœ˜UKšžœF˜LK˜K˜—šŸœžœžœžœ˜FKšžœ>˜DK˜K˜—šŸ œžœžœžœ˜BK˜Kšœ˜Kšžœ4˜:K˜K˜—šŸ œžœžœžœ˜RKšœ˜KšžœD˜JK˜K˜—šŸœžœžœžœ˜CKšžœ<˜BK˜K˜—šŸ œžœžœžœ˜Bšžœžœž˜šœ˜KšžœG˜M—Kšžœžœ˜ —K˜K˜——šœ™šœ„™„Kšœ™K™—šŸ œžœžœžœ ˜AKšžœžœ&˜1K˜—K˜šŸ œžœžœ&žœ ˜TKšžœ žœžœ˜'KšžœE˜KK˜K˜—šŸœžœžœžœ ˜EKšžœ=˜CK˜K˜—šŸ œžœžœžœ ˜AKšžœ=˜CK˜K˜—šŸ œžœžœ&žœ ˜RKšžœ žœžœ˜'KšžœV˜\K˜K˜—šŸœžœžœžœ ˜CKšžœ<˜BK˜K˜—šŸ œžœžœ.žœ ˜ZKšžœžœžœ˜+KšžœG˜MK˜K˜——Kšžœ˜K˜K˜—…—F pΪ