-- Copyright (C) 1983 by Xerox Corporation. All rights reserved. --File ExtendedStringImpl.mesa - to convert arbitrarily long fields to strings --last editted by AOF 16-Feb-83 15:41:50 DIRECTORY Environment USING [bitsPerWord], ExtendedString USING [], Heap USING [systemZone], Inline USING [BITOR, BITSHIFT, BITAND, LongCOPY, HighHalf, LowHalf], String USING [AppendChar]; ExtendedStringImpl: PROGRAM IMPORTS Heap, Inline, String EXPORTS ExtendedString = BEGIN InvalidBase: PUBLIC ERROR = CODE; Array: TYPE = LONG POINTER TO ArraySequence; ArraySequence: TYPE = RECORD[SEQUENCE length: CARDINAL OF CARDINAL]; ConvertToBase: PROC [ field: LONG POINTER, size, base: CARDINAL, array: Array] = BEGIN bit, index: CARDINAL; Copy: TYPE = LONG POINTER TO CopySequence; CopySequence: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF WORD]; copy: Copy ← Heap.systemZone.NEW[CopySequence[size]]; Inline.LongCOPY[field, size, copy]; array[0] ← 0; FOR index IN[1..array.length) DO array[index] ← base; ENDLOOP; THROUGH [0..size*Environment.bitsPerWord) DO bit ← ShiftFieldLeft[copy, size]; FOR index ← 0, index + 1 UNTIL array[index] = base DO array[index] ← array[index] * 2 + bit; IF array[index] >= base THEN BEGIN array[index] ← array[index] - base; bit ← 1; IF array[index + 1] = base THEN array[index + 1] ← 0; END ELSE bit ← 0; ENDLOOP; ENDLOOP; Heap.systemZone.FREE[@copy]; END; ShiftFieldLeft: PROC[ptr: LONG POINTER, size: CARDINAL] RETURNS [lost: CARDINAL] = --Shift field pointed to by "ptr" and of size (words) "size" left 1 place. --Save the bit lost off the left end in "lost". BEGIN new: WORD ← 0; ptr ← ptr + size; THROUGH [0..size) DO ptr ← ptr - 1; lost ← Inline.BITAND[ptr↑, 100000B]; --this bit lost off left end ptr↑ ← Inline.BITSHIFT[ptr↑, 1]; --now shift field segment ptr↑ ← Inline.BITOR[ptr↑, new]; --lost on left, gained on right lost ← new ← Inline.BITSHIFT[lost, 1-Environment.bitsPerWord]; ENDLOOP; END; AppendNumber: PUBLIC PROC [ field: LONG POINTER, size: CARDINAL, base: CARDINAL, string: LONG STRING] = BEGIN array: Array; digit, length, index: CARDINAL; char: STRING ← "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"L; length ← SELECT base FROM IN[2..8) => (size*Environment.bitsPerWord)+1, IN[8..10) => (size*Environment.bitsPerWord+3)/3+1, IN[10..16) => (size*Environment.bitsPerWord)/3+1, IN[16..36] => (size*Environment.bitsPerWord)/4+1, ENDCASE => ERROR InvalidBase; array ← Heap.systemZone.NEW[ArraySequence[length]]; ConvertToBase[field, size, base, array]; FOR index IN[0..array.length) DO IF array[index] = base THEN EXIT; ENDLOOP; FOR digit DECREASING IN [0..index) DO String.AppendChar[string, char[array[digit]]]; ENDLOOP; Heap.systemZone.FREE[@array]; END; AppendDecimal: PUBLIC PROC[ field: LONG POINTER, size: CARDINAL, string: LONG STRING] = {AppendNumber[field, size, 10, string]}; AppendOctal: PUBLIC PROC[ field: LONG POINTER, size: CARDINAL, string: LONG STRING] = {AppendNumber[field, size, 8, string]}; AppendHex: PUBLIC PROC[ field: LONG POINTER, size: CARDINAL, string: LONG STRING] = {AppendNumber[field, size, 16, string]}; StringToNumber: PUBLIC PROC [ field: LONG POINTER, size: CARDINAL, base: CARDINAL, string: LONG STRING] = BEGIN new: LONG CARDINAL; address: LONG POINTER TO CARDINAL; index, overflow, subfield: CARDINAL; FOR index: CARDINAL IN [0..size) DO address ← field + index; address↑ ← 0B; ENDLOOP; FOR index IN [0..string.length) DO overflow ← SELECT string[index] FROM IN['0..'9] => string[index] - '0, IN['A..'Z] => string[index] - 67C, ENDCASE => 0; FOR subfield DECREASING IN [0..size) DO address ← field + subfield; new ← LONG[address↑] * LONG[base] + LONG[overflow]; overflow ← Inline.HighHalf[new]; address↑ ← Inline.LowHalf[new]; ENDLOOP; ENDLOOP; END; StringToDecimal: PUBLIC PROC[ field: LONG POINTER, size: CARDINAL, string: LONG STRING] = {StringToNumber[field, size, 10, string]}; StringToOctal: PUBLIC PROC[ field: LONG POINTER, size: CARDINAL, string: LONG STRING] = {StringToNumber[field, size, 8, string]}; END...