-- AddressImpl.mesa  -  edited by:
--  Poskanzer	12-Sep-83 15:09:24
--  Bruce	19-Oct-83 14:43:18

-- Address is intended to be an easy-to-use interface to the various network address routines.  StringsToNetworkAddress[] turns your strings into a network address, much like AddressTranslation.StringToNetworkAddress[].  NetworkAddressToString[] turns a network address back into a string.  Both will raise AddressTrouble if anything goes wrong.

DIRECTORY
  AddressTranslation USING [
    BadSyntax, CHLookupProblem, OtherCHProblem, ScanError,
    StringToNetworkAddress],
  ExtendedString USING [AppendOctal, StringToNumber],
  Format USING [HostNumber, StringProc],
  String USING [
    AppendChar, AppendOctal, AppendString, InvalidNumber, StringToNumber],
  System USING [NetworkAddress, nullSocketNumber, SocketNumber],
  Address USING [];

AddressImpl: PROGRAM
  IMPORTS AddressTranslation, ExtendedString, Format, String EXPORTS Address =
  BEGIN

  AddressTrouble: PUBLIC ERROR [reason: LONG STRING] = CODE;

  StringsToNetworkAddress: PUBLIC PROCEDURE [
    host: LONG STRING, socket: System.SocketNumber ← System.nullSocketNumber,
    net: LONG STRING ← NIL] RETURNS [addr: System.NetworkAddress] =
    BEGIN
    addrString: STRING = [200];
    temp: STRING = [200];
    fieldSize: CARDINAL = 4;
    invalidNumber: BOOLEAN;
    number: CARDINAL;
    field: ARRAY [0..fieldSize) OF CARDINAL;
    addrString.length ← 0;
    -- First the net number.
    temp.length ← 0;
    AppendWithoutDashes[temp, net];
    invalidNumber ← FALSE;
    number ← String.StringToNumber[temp, 10 
      ! String.InvalidNumber => {invalidNumber ← TRUE; CONTINUE}];
    IF NOT invalidNumber THEN
      BEGIN
      String.AppendOctal[addrString, number];
      addrString.length ← addrString.length - 1;  -- Get rid of the 'B since AddressTranslation barfs on it.
      END;
    String.AppendString[addrString, "."L];
    -- Now the host - try interpreting it as a number, default base 10.
    temp.length ← 0;
    AppendWithoutDashes[temp, host];
    IF Alphabetic[temp] THEN String.AppendString[addrString, host]
    ELSE {
      ExtendedString.StringToNumber[@field, fieldSize, 10, temp];
      ExtendedString.AppendOctal[@field, fieldSize, addrString]};
    String.AppendString[addrString, "."L];
    addr ← AddressTranslation.StringToNetworkAddress[ addrString !
      AddressTranslation.BadSyntax => ERROR AddressTrouble["Bad syntax."L];
      AddressTranslation.CHLookupProblem =>
        ERROR AddressTrouble["Clearinghouse lookup problem."L];
      AddressTranslation.OtherCHProblem =>
        ERROR AddressTrouble["Clearinghouse problem"L];
      AddressTranslation.ScanError =>
        ERROR AddressTrouble["Illegal character"L]].addr;
    addr.socket ← socket;
    END --StringsToNetworkAddress-- ;

  Alphabetic: PROC [s: STRING] RETURNS [BOOLEAN] = {
    char: CHARACTER;
    IF s.length = 0 THEN RETURN[TRUE];
    char ← s[s.length-1];
    SELECT char FROM
      'H, 'h, 'X, 'x, IN['a..'f], IN['A..'F], IN ['0..'9] => NULL;
      ENDCASE => RETURN[TRUE];
    FOR i: CARDINAL IN [0..s.length-1) DO
      c: CHARACTER = s[i];
      SELECT c FROM
        IN['a..'f], IN['A..'F], IN ['0..'9] => NULL;
	ENDCASE => RETURN[TRUE];
      ENDLOOP;
    RETURN[FALSE]};
    
  NetworkAddressToString: PUBLIC PROCEDURE [
    addr: System.NetworkAddress, proc: Format.StringProc] =
    BEGIN  --NetworkAddressToString--
    --!! should look up name in clearinghouse.
    Format.HostNumber[proc, addr.host, productSoftware];
    END --NetworkAddressToString-- ;


  -- Internal procedures.

  AppendWithoutDashes: PROCEDURE [to: LONG STRING, from: LONG STRING] =
    BEGIN
    IF from # NIL THEN
      FOR i: CARDINAL IN [0..from.length) DO
        IF from[i] # '- THEN String.AppendChar[to, from[i]]; ENDLOOP;
    END;


  END.