-- AddressTranslationImpl.mesa (last edited by: AOF: January 30, 1981 10:38 AM)
-- Function: Developement Common Software used to maniputlate various fields of the NetworkAddress, specifically by translating to/from strings to System.NetworkAddresses.
DIRECTORY
AddressTranslation USING [Field],
Socket USING [AssignNetworkAddress],
SpecialSystem USING [HostNumber, broadcastHostNumber, NetworkAddress, SocketNumber,
nullNetworkAddress, NetworkNumber, nullNetworkNumber, GetProcessorID],
System USING [NetworkAddress],
Inline USING [BITAND, BITNOT, BITOR, BITSHIFT];
AddressTranslationImpl: PROGRAM
IMPORTS Inline, Socket, SpecialSystem
EXPORTS AddressTranslation, System =
BEGIN
-- This module implements the address translation interface. It translates strings to internal records, and internal records to strings.
-- All numbers are in octal.
-- <network address> := <net>#<host>#<socket>
-- <system element> := <net>#<host>#
-- <network number> := <net>
-- <net> := {a 32 bit number} | <empty>
-- <host> := <broadcast> | <Dmachine>
-- <broadcast> := *
-- <Dmachine> := {48 bit processor ID}
-- <socket> := {16 bit number}
-- Local constants, types and variables
SystemElement: PUBLIC TYPE = SpecialSystem.NetworkAddress;
NetworkAddress: PUBLIC TYPE = SpecialSystem.NetworkAddress;
--Procedures (in alphabetical order)
AddCharacterToString: PUBLIC PROCEDURE [c: CHARACTER, s: STRING] =
BEGIN
IF s.length < s.maxlength THEN {s[s.length] ← c; s.length ← s.length+1}
ELSE ERROR StringOverflow;
END;
AppendMyHostNumber: PUBLIC PROCEDURE [s: STRING] =
BEGIN
--Adds ASCII represenation of the local host number to the string ’s.’ If the host number is null, then at least on ’0’ will be in the string.
c: CHARACTER;
noSuppress: BOOLEAN ← FALSE;
timesToShift: CARDINAL = ((SIZE [SpecialSystem.HostNumber]*16)+2)/3;
shift: INTEGER ← SIZE [SpecialSystem.HostNumber] MOD 3;
hN: SpecialSystem.HostNumber ← SpecialSystem.GetProcessorID [];
IF shift = 0 THEN shift ← 3;
THROUGH [0..timesToShift) DO
c ← ShiftFieldLeft [@hN, SIZE [SpecialSystem.HostNumber], shift, 0]+’0;
shift ← 3;
IF (noSuppress ← noSuppress OR c#’0) THEN AddCharacterToString [c, s];
ENDLOOP;
IF ~noSuppress THEN AddCharacterToString [’0, s];
AddCharacterToString [’#, s];
END;
AppendMyNetworkNumber: PUBLIC PROCEDURE [s: STRING] =
BEGIN
lnA: System.NetworkAddress ← Socket.AssignNetworkAddress [];
AppendNetworkNumber [s, LOOPHOLE [lnA, NetworkAddress].net];
END;
AppendNetworkAddress: PUBLIC PROCEDURE
[s: STRING, nA: NetworkAddress] =
BEGIN
--Adds ASCII represenation of the client specified network address to the string ’s.’ If the network address is null, then at least on ’0’ will be in the string for each of the three positions.
c: CHARACTER;
shift: INTEGER ← 1;
noSuppress: BOOLEAN ← FALSE;
AppendSystemElement [s, nA];
THROUGH [0..6) DO
c ← ShiftFieldLeft [@nA.socket, 1, shift, 0]+’0;
shift ← 3;
IF (noSuppress ← noSuppress OR c#’0) THEN AddCharacterToString [c, s];
ENDLOOP;
IF ~noSuppress THEN AddCharacterToString [’0, s];
END;
AppendNetworkNumber: PUBLIC PROCEDURE
[s: STRING, net: SpecialSystem.NetworkNumber] =
BEGIN
--Adds ASCII represenation of the local network number to the string ’s.’ If the network number is null, then at least on ’0’ will be in the string.
c: CHARACTER;
noSuppress: BOOLEAN ← FALSE;
timesToShift: CARDINAL = ((SIZE [SpecialSystem.NetworkNumber]*16)+2)/3;
shift: INTEGER ← SIZE [SpecialSystem.NetworkNumber] MOD 3;
IF shift = 0 THEN shift ← 3;
THROUGH [0..timesToShift) DO
c ← ShiftFieldLeft [@net, SIZE [SpecialSystem.NetworkNumber], shift, 0]+’0;
shift ← 3;
IF (noSuppress ← noSuppress OR c#’0) THEN AddCharacterToString [c, s];
ENDLOOP;
IF ~noSuppress THEN AddCharacterToString [’0, s];
AddCharacterToString [’#, s];
END;
AppendSystemElement: PUBLIC PROCEDURE
[s: STRING, sE: SystemElement] =
BEGIN
--Adds ASCII represenation of the client specified system element to the string ’s.’ If the system element is null, then at least on ’0’ will be in the string for each of the two fields.
c: CHARACTER;
noSuppress: BOOLEAN ← FALSE;
timesToShift: CARDINAL = ((SIZE [SpecialSystem.HostNumber]*16)+2)/3;
shift: INTEGER ← SIZE [SpecialSystem.HostNumber] MOD 3;
IF shift = 0 THEN shift ← 3;
AppendNetworkNumber [s, sE.net];
THROUGH [0..timesToShift) DO
c ← ShiftFieldLeft [@sE.host, SIZE [SpecialSystem.HostNumber], shift, 0]+’0;
shift ← 3;
IF (noSuppress ← noSuppress OR c#’0) THEN AddCharacterToString [c, s];
ENDLOOP;
IF ~noSuppress THEN AddCharacterToString [’0, s];
AddCharacterToString [’#, s];
END;
BadSyntax: PUBLIC ERROR [field: AddressTranslation.Field] = CODE;
ShiftFieldLeft: PROCEDURE
[ptr: POINTER, len: CARDINAL, shift: INTEGER, new: CARDINAL]
RETURNS [lost: CARDINAL] =
-- Shift field pointed to by "ptr" and of length (words) "len" left "shift" places. Save the bits lost off the left end in "lost" and add bits "new" to right end of field.
BEGIN
saveMask: UNSPECIFIED = Inline.BITNOT [Inline.BITSHIFT [177777B, -shift]];
ptr ← ptr+len; lost ← 0;
THROUGH [0..len) DO
ptr ← ptr-1;
lost ← Inline.BITAND [ptr↑, saveMask];
ptr↑ ← Inline.BITSHIFT [ptr↑, shift];
ptr↑ ← Inline.BITOR [ptr↑, new];
new ← lost ← Inline.BITSHIFT [lost, shift-16];
ENDLOOP;
END;
StringOverflow: PUBLIC ERROR = CODE;
StringToNetworkAddress: PUBLIC PROCEDURE [s: STRING]
RETURNS [nA: NetworkAddress] =
-- string must be in the following format:
-- <network address> := <net>#<host>#<socket> | #<host>#<socket>
-- <net> may be defaulted and the assumed value will be the primary net number.
-- <host> may NOT be defaulted.
-- <socket> may NOT be defaulted.
BEGIN
sI: CARDINAL;
field: {net, host, socket} ← net;
nA ← StringToSystemElement [s];
FOR sI IN [0..s.length) DO
SELECT field FROM
net, host => --These are handled be StringToSystemElement
BEGIN
IF s[sI] = ’# THEN field ← SUCC [field];
END;
socket =>
BEGIN
IF Inline.BITAND [nA.socket, 160000B] # 0
OR s[sI] NOT IN [’0..’8) THEN GOTO syntax;
nA.socket ← Inline.BITOR [Inline.BITSHIFT [nA.socket, 3], s[sI]-’0];
END;
ENDCASE;
ENDLOOP;
EXITS
syntax => ERROR BadSyntax [socket];
END;
StringToNetworkNumber: PUBLIC PROCEDURE [s: STRING]
RETURNS [nN: SpecialSystem.NetworkNumber] =
-- string must be in the following format:
-- <network address> := <net>#
-- <net> may be defaulted and the assumed value will be the primary net number.
BEGIN
sI: CARDINAL ← 0;
ptrToNet: POINTER ← @nN;
nN ← SpecialSystem.nullNetworkNumber;
FOR sI IN [0..s.length) DO
IF s[sI] = ’# THEN
BEGIN
lnA: System.NetworkAddress ← Socket.AssignNetworkAddress [];
IF nN = SpecialSystem.nullNetworkNumber THEN
nN ← LOOPHOLE [lnA, NetworkAddress].net;
RETURN;
END;
IF (ShiftFieldLeft [ptrToNet, SIZE [SpecialSystem.NetworkNumber], 3, s[sI]-’0] # 0)
OR (s[sI] NOT IN [’0..’8)) THEN EXIT;
ENDLOOP;
ERROR BadSyntax [net];
END;
StringToSystemElement: PUBLIC PROCEDURE [s: STRING]
RETURNS [sE: SystemElement] =
-- string must be in the following format:
-- <network address> := <net>#<host># | #<host>#
-- <net> may be defaulted and the assumed value will be the primary net number.
-- <host> may NOT be defaulted, but may be one of four formats
BEGIN
sI: CARDINAL;
defined: BOOLEAN ← FALSE;
size: CARDINAL = SIZE [SpecialSystem.HostNumber];
field: {net, host, socket} ← net;
sE ← SpecialSystem.nullNetworkAddress;
sE.net ← StringToNetworkNumber [s];
FOR sI IN [0..s.length) DO
IF s[sI] = ’# THEN field ← SUCC [field] ELSE
SELECT field FROM
net => NULL; --This is already been handled by StringToNetworkNumber
host =>
BEGIN
IF ~defined AND (s[sI] = ’*)
THEN sE.host ← SpecialSystem.broadcastHostNumber
ELSE IF (s[sI] NOT IN [’0..’8)) OR (ShiftFieldLeft [@sE.host, size, 3, s[sI]-’0] # 0)
THEN GO TO syntax;
defined ← TRUE;
END;
socket => RETURN; --Socket is assumed null for SystemElement
ENDCASE;
ENDLOOP;
EXITS syntax => ERROR BadSyntax [host];
END;
END. -- AddressTranslationImpl
LOG
Time: June 9, 1980 1:50 PM By: AOF Action: created file.
Time: July 8, 1980 12:35 PM By: AOF Action: Forced at least one ’0’ on null fields. Eliminated two superflous routines..
Time: July 8, 1980 3:52 PM By: AOF Action: Removed TRAILING ZERO SUPPRESSION "feature."
Time: July 29, 1980 12:12 PM By: AOF Action: SIGNALs => ERRORs
Time: January 30, 1981 10:38 AM By: AOF Action: Ripped out unsupported code