Unformatter.mesa
last edited by Willie-Sue, April 6, 1984 2:43:26 pm PST
lisfted from Unformatter.mesa, HGM, 30-Oct-82 17:25:51
DIRECTORY
Basics USING [bitsPerWord, BITOR, BITSHIFT, HighHalf, LowHalf],
NSPilotSystem USING [broadcastHostNumber, HostNumber, NetworkAddress, NetworkNumber,
  SocketNumber],
Rope,   -- using lots
Unformat;
Unformatter: MONITOR
IMPORTS Basics, Rope
EXPORTS Unformat =
BEGIN
Error: PUBLIC ERROR = CODE;
UnrecognizedFormatOption: ERROR = CODE;
NetFormat: TYPE = Unformat.NetFormat;
ROPE: TYPE = Rope.ROPE;
HostNumber: PUBLIC PROC[r: ROPE, format: NetFormat ← octal]
RETURNS [host: NSPilotSystem.HostNumber] =
BEGIN
digits: Digits;
radix: CARDINAL;
IF r.Equal["*"] THEN RETURN[NSPilotSystem.broadcastHostNumber];
radix ← RopeToDigits[r, @digits, format];
DigitsToNumber[@host, SIZE[NSPilotSystem.HostNumber], radix, @digits];
END;
NetworkAddress: PUBLIC PROC[r: ROPE, format: NetFormat ← octal]
RETURNS [address: NSPilotSystem.NetworkAddress] =
BEGIN
net: ROPE;
host: ROPE;
socket: ROPE;
finger: INT ← 0;
len: INT← r.Length[];
UNTIL finger = len DO
c: CHAR = r.Fetch[finger];
finger ← finger + 1;
SELECT c FROM
'#, '. => EXIT;
ENDCASE => net← net.Concat[Rope.FromChar[c]];
REPEAT FINISHED => ERROR Error; -- Both delimiters missing
ENDLOOP;
UNTIL finger = len DO
c: CHAR = r.Fetch[finger];
finger ← finger + 1;
SELECT c FROM
'#, '. => EXIT;
ENDCASE => host← host.Concat[Rope.FromChar[c]];
REPEAT FINISHED => ERROR Error; -- second delimiter missing
ENDLOOP;
UNTIL finger = len DO
c: CHARACTER = r.Fetch[finger];
finger ← finger + 1;
socket← socket.Concat[Rope.FromChar[c]];
ENDLOOP;
address.net ← NetworkNumber[net, format];
address.host ← HostNumber[host, format];
address.socket ← SocketNumber[socket, format];
END;
NetworkNumber: PUBLIC PROC[r: ROPE, format: NetFormat ← octal]
RETURNS [networkNumber: NSPilotSystem.NetworkNumber] =
BEGIN
digits: Digits;
radix: CARDINAL;
radix ← RopeToDigits[r, @digits, format];
DigitsToNumber[@networkNumber, SIZE[NSPilotSystem.NetworkNumber], radix, @digits];
END;
SocketNumber: PUBLIC PROC[r: ROPE, format: NetFormat ← octal]
RETURNS [socketNumber: NSPilotSystem.SocketNumber] =
BEGIN
digits: Digits;
radix: CARDINAL;
radix ← RopeToDigits[r, @digits, format];
DigitsToNumber[@socketNumber, SIZE[NSPilotSystem.SocketNumber], radix, @digits];
END;
bitsPerPSCharacter: CARDINAL = 2; -- I don't want to think about the dashes
bitsPerOctalCharacter: CARDINAL = 3;
bitsPerHexCharacter: CARDINAL = 4;
minBitsPerCharacter: CARDINAL =
MIN[bitsPerPSCharacter, bitsPerOctalCharacter, bitsPerHexCharacter];
maxCharsInHostNumber: CARDINAL =
SIZE[NSPilotSystem.HostNumber]*Basics.bitsPerWord/minBitsPerCharacter+1;
maxCharsInNetworkNumber: CARDINAL =
SIZE[NSPilotSystem.NetworkNumber]*Basics.bitsPerWord/minBitsPerCharacter+1;
maxCharsInSocketNumber: CARDINAL =
SIZE[NSPilotSystem.SocketNumber]*Basics.bitsPerWord/minBitsPerCharacter+1;
maxCharsInNetworkAddress: CARDINAL =
maxCharsInNetworkNumber+1+maxCharsInHostNumber+1+maxCharsInSocketNumber;
maxDigits: CARDINAL =
MAX[maxCharsInHostNumber, maxCharsInNetworkNumber, maxCharsInSocketNumber];
Digits: TYPE = ARRAY [0..maxDigits) OF CARDINAL;
RopeToDigits: PROC[r: ROPE, digits: POINTER TO Digits, format: NetFormat]
RETURNS[radix: CARDINAL] =
BEGIN
finger: CARDINAL ← maxDigits;
digits^ ← ALL[0];
radix ← 0;
FOR i: INT DECREASING IN [0..r.Length[]) DO
c: CHAR ← r.Fetch[i];
digit: CARDINAL;
SELECT c FROM
'- =>
BEGIN
IF radix # 0 AND radix # 10 THEN ERROR Error;
radix ← 10;
LOOP;
END;
'H, 'h =>
BEGIN
IF radix # 0 AND radix # 16 THEN ERROR Error;
radix ← 16;
LOOP;
END;
IN ['0..'9] => digit ← c - '0;
IN ['A..'F] =>
BEGIN
IF radix # 0 AND radix # 16 THEN ERROR Error;
radix ← 16;
digit ← c - 'A + 10;
END;
IN ['a..'f] =>
BEGIN
IF radix # 0 AND radix # 16 THEN ERROR Error;
radix ← 16;
digit ← c - 'a + 10;
END;
ENDCASE => ERROR Error;
IF finger = 0 THEN ERROR Error;
finger ← finger - 1;
digits[finger]← digit;
ENDLOOP;
IF radix = 0 THEN
BEGIN
SELECT format FROM
octal => radix ← 8;
hex => radix ← 16;
ENDCASE => ERROR;
END;
END;
DigitsToNumber: PROC[
  data: LONG POINTER, words, radix: CARDINAL, digits: POINTER TO Digits] =
BEGIN
overflow: CARDINAL;
FOR i: CARDINAL IN [0..words) DO (data + i)^ ← 0; ENDLOOP;
FOR k: CARDINAL IN [0..maxDigits) DO
overflow ← digits[k];
FOR i: CARDINAL DECREASING IN [0..words) DO
temp: LONG CARDINAL;
temp ← LONG[(data + i)^]*radix + overflow;
(data + i)^ ← Basics.LowHalf[temp];
overflow ← Basics.HighHalf[temp];
ENDLOOP;
ENDLOOP;
IF overflow # 0 THEN ERROR Error;
END;
the following are from FormatImpl
HostNumberToRope:
PUBLIC PROC[hostNumber: NSPilotSystem.HostNumber, format: NetFormat← octal]
  RETURNS[r: ROPE] =
BEGIN
IF hostNumber = NSPilotSystem.broadcastHostNumber THEN RETURN["*"]
ELSE RETURN[DoField[@hostNumber, SIZE[NSPilotSystem.HostNumber], format]];
END;
DoField: PROC[data: POINTER, words: CARDINAL, format: NetFormat] RETURNS[r: ROPE] =
BEGIN
digits: Digits;
base: CARDINAL;
SELECT format FROM
octal => base ← 8;
hex => base ← 16;
productSoftware => base ← 10;
ENDCASE => ERROR UnrecognizedFormatOption;
ConvertToDigits[data, words, base, @digits];
r← DoDigits[@digits, base = 10];
IF base = 16 THEN r← r.Concat["H"];
END;
DoDigits: PROC[digits: POINTER TO Digits, dashes: BOOL] RETURNS[ROPE] =
BEGIN
something: BOOLFALSE;
r: ROPENIL;
FOR i: CARDINAL IN [0..maxDigits) DO
v: CARDINAL ← digits[i];
IF dashes AND something AND (maxDigits - i) MOD 3 = 0 THEN r← r.Concat["-"];
IF v # 0 AND ~something THEN
BEGIN
IF dashes THEN
BEGIN
SELECT maxDigits - i FROM
1 => r← r.Concat["0-00"];
2 => r← r.Concat["0-0"];
3 => r← r.Concat["0-"];
ENDCASE => NULL;
END;
IF v > 9 THEN r← r.Concat["0"]; -- Leading digit for Hex case
something ← TRUE;
END;
IF something THEN
BEGIN
c: CHARIF v > 9 THEN v - 10 + 'A ELSE v + '0;
r← r.Concat[Rope.FromChar[c]];
END;
ENDLOOP;
IF ~something THEN
BEGIN
IF FALSE AND dashes THEN r← r.Concat["0-00"];
r← r.Concat["0"];
END;
RETURN[Rope.Flatten[r]];
END;
ConvertToDigits: PROC[field: POINTER, size, base: CARDINAL, digits: POINTER TO Digits] =
BEGIN
digits^ ← ALL[0];
THROUGH [0..size*Basics.bitsPerWord) DO
bit: CARDINAL ← ShiftFieldLeft[field, size, 1];
FOR i: CARDINAL DECREASING IN [0..maxDigits) DO
digits[i] ← digits[i]*2 + bit;
IF digits[i] >= base THEN BEGIN digits[i] ← digits[i] - base; bit ← 1; END
ELSE bit ← 0;
ENDLOOP;
ENDLOOP;
END;
ShiftFieldLeft: PROC[data: POINTER, words: CARDINAL, shift: INTEGER]
RETURNS [left: CARDINAL] =
BEGIN
right: WORD ← 0;
data ← data + words;
THROUGH [0..words) DO
data ← data - 1;
left ← Basics.BITSHIFT[data^, shift - 16];
data^ ← Basics.BITOR[Basics.BITSHIFT[data^, shift], right];
right ← left;
ENDLOOP;
END;
END.