-- Copyright (C) 1984, 1985  by Xerox Corporation. All rights reserved. 
-- GateParameterNoDisk.mesa, HGM,  5-Oct-85 20:02:31
-- Updated: WIrish, 22-Jul-86  9:26:25
-- And various stubs...

DIRECTORY
  CmFile USING [Handle, TableError],
  Format USING [NetworkNumber],
  Process USING [Priority, priorityForeground],
  Put USING [Decimal, NetworkNumber, Number, Text, Line],
  StringLookUp USING [noMatch, TableDesc],
  String USING [
    AppendChar, AppendDecimal, AppendNumber, AppendString, EqualString],
  System USING [NetworkNumber, nullNetworkNumber],
  Token USING [Boolean, Decimal, FreeStringHandle, FreeTokenString, Handle, Item, NetworkNumber, Octal, StringToHandle, SyntaxError],

  Buffer USING [],
  BufferOps USING [Defaults, GetDefaults, SetDefaults],
  DriverTypes USING [DeviceType],
  Driver USING [GetDeviceChain, Network],
  ForwarderDefs USING [],
  Protocol1 USING [Family, GetContext, GetFamiltyUnit],
  PupDefs USING [PupPackageMake, SmashMyHostNumber],
  PupRouterDefs USING [NetworkContext],
  Router USING [SetNetworkID],
  RoutingTable USING [NetworkContext],
  
  GateDefs USING [],
  Indirect USING [Close, NextValue, OpenSection],
  PhoneCreate USING [CreatePhone],
  RoutingFudges USING [SetNSFudge, SetPupFudge],
  Trouble USING [Bug];

GateParameterNoDisk: PROGRAM
  IMPORTS
    CmFile, Format, Process, Put, String, Token,
    BufferOps, Driver, Indirect, PupDefs, Router, PhoneCreate, Protocol1, RoutingFudges, Trouble
  EXPORTS Buffer, GateDefs =
  BEGIN
  
  Network: PUBLIC TYPE = Driver.Network;

  SetupWindow: PUBLIC PROCEDURE = BEGIN END;

  ScanParameterFile: PUBLIC PROCEDURE RETURNS [
    priority: Process.Priority ← Process.priorityForeground,
    disableNSRouting: BOOLEAN ← FALSE] =
    BEGIN
    cmFile: CmFile.Handle;
    Option: TYPE = MACHINE DEPENDENT{
      ethernetOne(0), ethernet, sdlc, pupHostNumber, buffers,
      priority, disableNSRouting, extraPupHops, extraNsHops, extraHops,
      noMatch(StringLookUp.noMatch)};
    DefinedOption: TYPE = Option [ethernetOne..extraHops];
    CheckType: PROCEDURE [h: CmFile.Handle, table: StringLookUp.TableDesc]
      RETURNS [index: CARDINAL] = Indirect.NextValue;
    MyNextValue: PROCEDURE [
      h: CmFile.Handle,
      table: LONG DESCRIPTOR FOR ARRAY DefinedOption OF LONG STRING]
      RETURNS [index: Option] = LOOPHOLE[CheckType];
    optionTable: ARRAY DefinedOption OF LONG STRING ← [
      ethernetOne: "EthernetOne"L,
      ethernet: "Ethernet"L,
      sdlc: "SDLC"L,
      pupHostNumber: "Pup Host Number"L,
      buffers: "Buffers"L,
      priority: "Priority"L,
      disableNSRouting: "Disable NS Routing"L,
      extraPupHops: "Extra PUP Hops"L,
      extraNsHops: "Extra NS Hops"L,
      extraHops: "Extra Hops"L];
    phoneLines: CARDINAL ← 0;

    [] ← PupDefs.PupPackageMake[]; -- Probably redundant
    cmFile ← Indirect.OpenSection["Gateway"L];
    IF cmFile = NIL THEN
      BEGIN
      Message["Can't find [Gateway] section in Parameter file"L];
      RETURN;
      END;

    DO
      option: Option;
      option ← MyNextValue[cmFile, DESCRIPTOR[optionTable] !
        CmFile.TableError =>
          BEGIN
	  IF name[0] # '; THEN Message["Unrecognized parameter: ", name];
	  RETRY;
	  END];
      SELECT option FROM
        noMatch => EXIT;
        ethernetOne =>  -- <board> <Pup Net> <NS net> (octal) 
          BEGIN
          board: CARDINAL ← Token.Decimal[cmFile];
          pupNet: CARDINAL ← Token.Octal[cmFile];
          nsNet: System.NetworkNumber ← Token.NetworkNumber[cmFile, octal];
          SetPupNetworkID[board, ethernetOne, pupNet];
	  IF nsNet # System.nullNetworkNumber THEN
	    BEGIN
            CheckNSNetworkID[board, ethernetOne, nsNet];
            [] ← Router.SetNetworkID[board, ethernetOne, nsNet];
            END;
          PrintHost["EthernetOne"L, board, pupNet, nsNet];
          END;
        ethernet =>  -- <board> <Pup Net> <NS net> (octal) 
          BEGIN
          board: CARDINAL ← Token.Decimal[cmFile];
          pupNet: CARDINAL ← Token.Octal[cmFile];
          nsNet: System.NetworkNumber ← Token.NetworkNumber[cmFile, octal];
          SetPupNetworkID[board, ethernet, pupNet];
	  IF nsNet # System.nullNetworkNumber THEN
	    BEGIN
            CheckNSNetworkID[board, ethernet, nsNet];
            [] ← Router.SetNetworkID[board, ethernet, nsNet];
            END;
          PrintHost["Ethernet"L, board, pupNet, nsNet];
          END;
        sdlc =>  -- <Pup Host> <Pup Net> <Lines> (octal) 
          BEGIN
	  -- Line 0 must come first
          line: CARDINAL ← Token.Octal[cmFile];
          pupNet: CARDINAL ← Token.Octal[cmFile];
          nsNet: System.NetworkNumber ← Token.NetworkNumber[cmFile, octal];
          pupHost: CARDINAL ← Token.Octal[cmFile];
	  password: LONG STRING ← Token.Item[cmFile];
	  IF String.EqualString[password, "NIL"L] THEN
	    BEGIN
            [] ← Token.FreeTokenString[password];
	    password ← NIL;
	    END;
          phoneLines ← phoneLines + 1;
          PhoneCreate.CreatePhone[pupHost, pupNet, line, password];
          IF password # NIL THEN [] ← Token.FreeTokenString[password];
          SetPupNetworkID[phoneLines, phonenet, pupNet];
	  IF nsNet # System.nullNetworkNumber THEN
	    BEGIN
            CheckNSNetworkID[phoneLines, phonenet, nsNet];
            [] ← Router.SetNetworkID[phoneLines, phonenet, nsNet];
	    END;
          PrintSdlcInfo[pupHost, pupNet, line, phoneLines];
          END;
        pupHostNumber =>
          BEGIN
          me: CARDINAL ← Token.Octal[cmFile];
          PupDefs.SmashMyHostNumber[me];
          MessageOctal["Set my Pup Host Number to "L, me];
          END;
        buffers =>  -- <number> (decimal)
          BEGIN
	  defaults: ARRAY BufferOps.Defaults OF CARDINAL ← BufferOps.GetDefaults[];
          buffers: CARDINAL ← Token.Decimal[cmFile];
	  defaults[bias] ← defaults[bias] + buffers;
          BufferOps.SetDefaults[defaults];
          MessageDecimal["Added "L, buffers, " buffers to the system pool"L];
          END;
        priority =>  -- <priority> (decimal)
          BEGIN
          priority ← Token.Decimal[cmFile];
          MessageDecimal["Priority will be "L, priority];
          END;
        disableNSRouting =>  -- <boolean>
          BEGIN
          IF Token.Boolean[cmFile] THEN
            BEGIN
            Message["Deactivating NS Router"L];
	    disableNSRouting ← TRUE;
            END
          ELSE Message["Didn't deactivate NS Router"L];
          END;
        extraPupHops =>  -- <decimal>
         BEGIN
	  SetExtraPupHops[Token.Decimal[cmFile]];
          END;
        extraNsHops =>  -- <decimal>
         BEGIN
	  SetExtraNsHops[Token.Decimal[cmFile]];
          END;
        extraHops =>  -- <boolean> or <decimal>
	              -- FALSE -> 0, TRUE -> 1
          BEGIN
	  hopsToAdd: CARDINAL ← 0;
	  item: LONG STRING ← Token.Item[cmFile];
	  th: Token.Handle ← Token.StringToHandle[item];
	  th1: Token.Handle ← Token.StringToHandle[item];
          IF Token.Boolean[th ! Token.SyntaxError => BEGIN
	       hopsToAdd ← Token.Decimal[th1];
	       CONTINUE;
	       END;]
	     THEN hopsToAdd ← 1;
	  [] ← Token.FreeStringHandle[th];
	  [] ← Token.FreeStringHandle[th1];
	  [] ← Token.FreeTokenString[item];
	  SetExtraPupHops[hopsToAdd];
	  SetExtraNsHops[hopsToAdd];
          END;

        ENDCASE => ERROR;
      ENDLOOP;

    Indirect.Close[cmFile];

    END;

  SetExtraPupHops: PROCEDURE [hops: CARDINAL] =
    BEGIN
    IF hops > 0 THEN
       BEGIN
       MessageDecimal["Setting Extra PUP Hops to "L, hops];
       RoutingFudges.SetPupFudge[hops];
       END
    ELSE Message["There are no Extra PUP Hops"L];
    END;

  SetExtraNsHops: PROCEDURE [hops: CARDINAL] =
    BEGIN
    IF hops > 0 THEN
       BEGIN
       MessageDecimal["Setting Extra NS Hops to "L, hops];
       RoutingFudges.SetNSFudge[hops];
       END
    ELSE Message["There are no Extra NS Hops"L];
    END;

  SetPupNetworkID: PROCEDURE [
    physicalOrder: CARDINAL, medium: DriverTypes.DeviceType, newNetID: CARDINAL] =
    BEGIN
    ENABLE UNWIND => NULL;
    network: Driver.Network ← GetNthDevice[physicalOrder, medium];
    context: PupRouterDefs.NetworkContext ← Protocol1.GetContext[network, pup];
    family: Protocol1.Family ← Protocol1.GetFamiltyUnit[pup];
    IF context.pupNetNumber # 0 AND context.pupNetNumber # newNetID THEN
      BEGIN
      text: STRING = [200];
      String.AppendString[text, "Wrong Pup network number.  Expected: "L];
      String.AppendNumber[text, newNetID, 8];
      String.AppendString[text, ", Found: "L];
      String.AppendNumber[text, context.pupNetNumber, 8];
      Trouble.Bug[text];
      END;
    context.pupNetNumber ← newNetID;
    family.stateChanged[network, context, add];
    END;

  CheckNSNetworkID: PROCEDURE [
    physicalOrder: CARDINAL, medium: DriverTypes.DeviceType,
    newNetID: System.NetworkNumber] =
    BEGIN
    ENABLE UNWIND => NULL;
    network: Driver.Network ← GetNthDevice[physicalOrder, medium];
    context: RoutingTable.NetworkContext ← Protocol1.GetContext[network, ns];
    IF context.netNumber # System.nullNetworkNumber AND context.netNumber # newNetID THEN
      BEGIN
      text: STRING = [200];
      String.AppendString[text, "Wrong NS network number.  Expected: "L];
      AppendNetNumbers[text, newNetID];
      String.AppendString[text, ", Found: "L];
      AppendNetNumbers[text, context.netNumber];
      Trouble.Bug[text];
      END;
    network ← NIL;  -- Compiler and Debugger don't cooperate
    END;

  GetNthDevice: PROCEDURE [
    physicalOrder: CARDINAL, medium: DriverTypes.DeviceType]
    RETURNS [network: Driver.Network] =
    BEGIN
    i: CARDINAL ← 0;
    FOR network ← Driver.GetDeviceChain[], network.next UNTIL network = NIL DO
      IF network.device = medium THEN IF (i ← i + 1) = physicalOrder THEN RETURN;
      ENDLOOP;
    Trouble.Bug["Driver doesn't exist"L];
    network ← NIL;  -- Compiler and Debugger don't agree
    END;

  PrintHost: PROCEDURE [
    name: LONG STRING, board, pupNet: CARDINAL, nsNet: System.NetworkNumber] =
    BEGIN
    Put.Text[NIL, name];
    IF board # LAST[CARDINAL] THEN
      BEGIN Put.Text[NIL, " number "L]; Put.Number[NIL, board, [8, FALSE, TRUE, 0] ]; END;
    Put.Text[NIL, " is Pup network "L];
    Put.Number[NIL, pupNet, [8, FALSE, TRUE, 0] ];
    Put.Text[NIL, " and NS network "L];
    Put.NetworkNumber[NIL, nsNet, octal];
    Put.Text[NIL, " ("L];
    Put.NetworkNumber[NIL, nsNet, productSoftware];
    Put.Line[NIL, ")."L];
    END;

  PrintSdlcInfo: PROCEDURE [pupHost, pupNet: CARDINAL, line, driver: CARDINAL] =
    BEGIN
    Put.Text[NIL, "The "L];
    SELECT driver FROM
      1 => Put.Text[NIL, "first"L];
      2 => Put.Text[NIL, "second"L];
      3 => Put.Text[NIL, "third"L];
      4 => Put.Text[NIL, "forth"L];
      5 => Put.Text[NIL, "fifth"L];
      6 => Put.Text[NIL, "sixth"L];
      7 => Put.Text[NIL, "seventh"L];
      8 => Put.Text[NIL, "eighth"L];
      ENDCASE => {Put.Decimal[NIL, driver]; Put.Text[NIL, "th"L]; };
    Put.Text[NIL, " SDLC line (line "L];
    Put.Number[NIL, line, [8, FALSE, TRUE, 0] ];
    Put.Text[NIL, ") is Pup "L];
    Put.Number[NIL, pupNet, [8, FALSE, TRUE, 0] ];
    Put.Text[NIL, "#"L];
    Put.Number[NIL, pupHost, [8, FALSE, TRUE, 0] ];
    Put.Text[NIL, "#"L];
    Put.Line[NIL, "."L];
    END;

  MessageDecimal: PROCEDURE [
    one: LONG STRING, num: CARDINAL, two, three: LONG STRING ← NIL] =
    BEGIN
    text: STRING = [100];
    String.AppendString[text, one];
    String.AppendDecimal[text, num];
    IF two # NIL THEN String.AppendString[text, two];
    IF three # NIL THEN String.AppendString[text, three];
    String.AppendChar[text, '.];
    LogString[text];
    END;

  MessageOctal: PROCEDURE [
    one: LONG STRING, num: CARDINAL, two, three: LONG STRING ← NIL] =
    BEGIN
    text: STRING = [100];
    String.AppendString[text, one];
    String.AppendNumber[text, num, 8];
    IF two # NIL THEN String.AppendString[text, two];
    IF three # NIL THEN String.AppendString[text, three];
    String.AppendChar[text, '.];
    LogString[text];
    END;

  Message: PROCEDURE [one, two, three: LONG STRING ← NIL] =
    BEGIN
    text: STRING = [100];
    String.AppendString[text, one];
    IF two # NIL THEN String.AppendString[text, two];
    IF three # NIL THEN String.AppendString[text, three];
    String.AppendChar[text, '.];
    LogString[text];
    END;

  LogString: PROCEDURE [text: LONG STRING] = BEGIN Put.Line[NIL, text]; END;

  AppendNetNumbers: PROCEDURE [string: LONG STRING, net: System.NetworkNumber] =
    BEGIN
    words: RECORD [a, b: WORD] = LOOPHOLE[net];
    AppendNetNumber[string, net];
    IF words.b < 256 THEN
      BEGIN
      String.AppendString[string, " ("L];
      AppendNetNumberOctal[string, net];
      String.AppendString[string, ")"L];
      END;
    END;

  AppendNetNumber: PROCEDURE [string: LONG STRING, net: System.NetworkNumber] =
    BEGIN
    Append: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
      BEGIN String.AppendString[string, s]; END;
    Format.NetworkNumber[Append, net, productSoftware];
    END;

  AppendNetNumberOctal: PROCEDURE [string: LONG STRING, net: System.NetworkNumber] =
    BEGIN
    Append: PROCEDURE [s: LONG STRING, clientData: LONG POINTER] =
      BEGIN String.AppendString[string, s]; END;
    Format.NetworkNumber[Append, net, octal];
    END;

  END.