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