-- AddressTranslationImpl.mesa (last edited by: AOF: January 30, 1981 10:38 AM)(2048)\i3bI22Bi
-- Function: Developement Common Software used to maniputlate various fields of the NetworkAddress, specifically by translating to/from strings to NSAddress.NetworkAddresses.

DIRECTORY
AddressTranslation USING [Field],
Socket USING [AssignNetworkAddress],
NSAddress USING [HostNumber, broadcastHostNumber, NetworkAddress, SocketNumber,
nullNetworkAddress, NetworkNumber, nullNetworkNumber, GetProcessorID],
PrincOpsUtils USING [BITAND, BITNOT, BITOR, BITSHIFT];

AddressTranslationImpl: PROGRAM
IMPORTS PrincOpsUtils, Socket, NSAddress
EXPORTS AddressTranslation =
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}(635)\i173I65b20B152b14B54b6B2b6B2b5B2b8B4b22B103i139I1bi29B21I1i44I1i36I1i17I1i40I1i42I1i18I1i36I1i
-- Local constants, types and variables
NSAddressElement: PUBLIC TYPE = NSAddress.NetworkAddress;
NetworkAddress: PUBLIC TYPE = NSAddress.NetworkAddress;

--Procedures (in alphabetical order)e12\i40I119i37I

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;e12\1b20B151b14B
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 [NSAddress.HostNumber]*16)+2)/3;
shift: INTEGER ← SIZE [NSAddress.HostNumber] MOD 3;
hN: NSAddress.HostNumber ← NSAddress.GetProcessorID [];
IF shift = 0 THEN shift ← 3;
THROUGH [0..timesToShift) DO
c ← ShiftFieldLeft [@hN, SIZE [NSAddress.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;e12\b18B42i143I229b14B82b14B125b20B47b20B13b20B
AppendMyNetworkNumber: PUBLIC PROCEDURE [s: STRING] =
BEGIN
lnA: NSAddress.NetworkAddress ← Socket.AssignNetworkAddress [];
AppendNetworkNumber [s, LOOPHOLE [lnA, NetworkAddress].net];
END;e12\b21B81b20B8b19B
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;
AppendNSAddressElement [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;e12\b20B68i194I76b19B44b14B102b20B47b20B
AppendNetworkNumber: PUBLIC PROCEDURE
[s: STRING, net: NSAddress.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 [NSAddress.NetworkNumber]*16)+2)/3;
shift: INTEGER ← SIZE [NSAddress.NetworkNumber] MOD 3;
IF shift = 0 THEN shift ← 3;
THROUGH [0..timesToShift) DO
c ← ShiftFieldLeft [@net, SIZE [NSAddress.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;e12\b19B82i149I264b14B129b20B47b20B13b20B
AppendNSAddressElement: PUBLIC PROCEDURE
[s: STRING, sE: NSAddressElement] =
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 [NSAddress.HostNumber]*16)+2)/3;
shift: INTEGER ← SIZE [NSAddress.HostNumber] MOD 3;
IF shift = 0 THEN shift ← 3;
AppendNetworkNumber [s, sE.net];
THROUGH [0..timesToShift) DO
c ← ShiftFieldLeft [@sE.host, SIZE [NSAddress.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;e12\b20B66i187I216b19B59b14B130b20B47b20B13b20B
BadSyntax: PUBLIC ERROR [field: AddressTranslation.Field] = CODE;e12\b9B
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 = PrincOpsUtils.BITNOT [PrincOpsUtils.BITSHIFT [177777B, -shift]];
ptr ← ptr+len; lost ← 0;
THROUGH [0..len) DO
ptr ← ptr-1;
lost ← PrincOpsUtils.BITAND [ptr^, saveMask];
ptr^ ← PrincOpsUtils.BITSHIFT [ptr^, shift];
ptr^ ← PrincOpsUtils.BITOR [ptr^, new];
new ← lost ← PrincOpsUtils.BITSHIFT [lost, shift-16];
ENDLOOP;
END;e12\b14B112i173I43b6B9b8B117b6B42b8B39b5B43b9B
StringOverflow: PUBLIC ERROR = CODE;e12\b14B
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 ← StringToNSAddressElement [s];
FOR sI IN [0..s.length) DO
SELECT field FROM
net, host => --These are handled be StringToNSAddressElement
BEGIN
IF s[sI] = '# THEN field ← SUCC [field];
END;
socket =>
BEGIN
IF PrincOpsUtils.BITAND [nA.socket, 160000B] # 0
OR s[sI] NOT IN ['0..'8) THEN GOTO syntax;
nA.socket ← PrincOpsUtils.BITOR [PrincOpsUtils.BITSHIFT [nA.socket, 3], s[sI]-'0];
END;
ENDCASE;
ENDLOOP;
EXITS
syntax => ERROR BadSyntax [socket];
END;e12\b22B68i41I2i21I1i189I71b21B110b21B166b6B121b5B9b8B114b9B
StringToNetworkNumber: PUBLIC PROCEDURE [s: STRING]
RETURNS [nN: NSAddress.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 ← NSAddress.nullNetworkNumber;
FOR sI IN [0..s.length) DO
IF s[sI] = '# THEN
BEGIN
lnA: NSAddress.NetworkAddress ← Socket.AssignNetworkAddress [];
IF nN = NSAddress.nullNetworkNumber THEN
nN ← LOOPHOLE [lnA, NetworkAddress].net;
RETURN;
END;
IF (ShiftFieldLeft [ptrToNet, SIZE [NSAddress.NetworkNumber], 3, s[sI]-'0] # 0)
OR (s[sI] NOT IN ['0..'8)) THEN EXIT;
ENDLOOP;
ERROR BadSyntax [net];e12\b21B81i41I2i21I1i89I223b20B171b14B140b9B
END;
StringToNSAddressElement: PUBLIC PROCEDURE [s: STRING]
RETURNS [sE: NSAddressElement] =
-- 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 [NSAddress.HostNumber];
field: {net, host, socket} ← net;
sE ← NSAddress.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 ← NSAddress.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 NSAddressElement
ENDCASE;
ENDLOOP;
EXITS syntax => ERROR BadSyntax [host];
END;e12\b21B67i41I2i21I1i170I199b21B175b21B212b14B271b9B
END. -- AddressTranslationImple24(2048)\4i4b
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." (635)\i
Time: July 29, 1980 12:12 PM By: AOF Action: SIGNALs => ERRORs \i
Time: January 30, 1981 10:38 AM By: AOF Action: Ripped out unsupported code \i