<> <> <> 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; <> 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: BOOL_ FALSE; r: ROPE_ NIL; 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: CHAR_ IF 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.