-- Copyright (C) 1983, 1985  by Xerox Corporation. All rights reserved. 
-- TimeServersParmNoDisk.mesa, HGM, 15-Jun-85 15:52:31

DIRECTORY
  Ascii USING [CR],
  CmFile USING [Handle, TableError],
  Inline USING [LowHalf],
  Put USING [Text],
  String USING [AppendChar, AppendDecimal, AppendString, AppendLongDecimal],
  StringLookUp USING [noMatch, TableDesc],
  System USING [GetLocalTimeParameters, LocalTimeParameters, WestEast],
  TemporarySetGMT USING [adjustableClockRate, SetClockRate],
  Time USING [AppendCurrent],
  Token USING [Boolean, Decimal, LongDecimal],
  TimeServerOps USING [SetClockDrift, SetClockWobble, Start, Stop],
  
  Indirect USING [Close, NextValue, OpenSection],
  PupTimeServer USING [PupTimeServerOn],
  PupTimeServerOps USING [parmsOk, correction];

TimeServersParmNoDisk: PROGRAM
  IMPORTS
    CmFile, Inline, Put, String, System, TemporarySetGMT, Time, Token,
    TimeServerOps,
    Indirect, PupTimeServer, PupTimeServerOps =
  BEGIN

  FindParameters: PROCEDURE =
    BEGIN
    ok: BOOLEAN ← TRUE;
    flakey, disableNSTimeServer: BOOLEAN ← FALSE;
    dstSpecified, zoneSpecified: BOOLEAN ← FALSE;
    driftSpecified, wobbleSpecified, correctionSpecified: BOOLEAN ← FALSE;
    parms: System.LocalTimeParameters ← System.GetLocalTimeParameters[];
    cmFile: CmFile.Handle;
    Option: TYPE = MACHINE DEPENDENT{
      correction(0), drift, wobble, dst, zone, disableNSTimeServer,
      noMatch(StringLookUp.noMatch)};
    DefinedOption: TYPE = Option [correction..disableNSTimeServer];
    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 ← [
      correction: "Correction"L, drift: "Drift"L, wobble: "Wobble"L,
      dst: "DST"L, zone: "Zone"L,
      disableNSTimeServer: "Disable NS Time Server"L];
    PupTimeServerOps.parmsOk ← FALSE;
    cmFile ← Indirect.OpenSection["TimeServer"L];
    IF cmFile = NIL THEN
      BEGIN
      Message["Can't find [TimeServer] section in parameter file"L];
      RETURN;
      END;
    DO
      text: STRING = [200];
      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;
        correction =>
          BEGIN
          correction: LONG INTEGER ← Token.LongDecimal[cmFile];
          String.AppendLongDecimal[text, correction];
          Message["The crystal correction is "L, text, " milliseconds per day"L];
          SetCorrection[correction];
          PupTimeServerOps.correction ← Inline.LowHalf[correction/1000];
          correctionSpecified ← TRUE;
          END;
        drift =>
          BEGIN
          drift: CARDINAL ← Token.Decimal[cmFile];
          String.AppendLongDecimal[text, drift];
          Message["The clock drift is "L, text, " milliseconds per day"L];
	  TimeServerOps.SetClockDrift[86400, drift];
          driftSpecified ← TRUE;
          END;
        wobble =>
          BEGIN
          wobble: CARDINAL ← Token.Decimal[cmFile];
          String.AppendLongDecimal[text, wobble];
          Message["The clock wobble is "L, text, " milliseconds per quarter day"L];
	  TimeServerOps.SetClockWobble[86400/4, wobble];
          wobbleSpecified ← TRUE;
          END;
	dst =>  -- <begin day> <end day>
          BEGIN
          first: CARDINAL ← Token.Decimal[cmFile];
          last: CARDINAL ← Token.Decimal[cmFile];
          IF first # parms.beginDST OR last # parms.endDST THEN
            BEGIN Message["The DST info on this disk is wrong"L]; ok ← FALSE; END;
          String.AppendString[text, "DST: begin="L];
          String.AppendDecimal[text, first];
          String.AppendString[text, ", last="L];
          String.AppendDecimal[text, last];
          Message[text];
          dstSpecified ← TRUE;
          END;
        zone =>  -- <sign> <hours>:<minutes>
          BEGIN
          hours: INTEGER ← Token.Decimal[cmFile];
          minutes: CARDINAL ← Token.Decimal[cmFile];
          westEast: System.WestEast ← IF hours < 0 THEN east ELSE west;
          hours ← ABS[hours];
          IF westEast # parms.direction OR hours # parms.zone
            OR minutes # parms.zoneMinutes THEN
            BEGIN
            Message["The time zone info on this disk is wrong"L];
            ok ← FALSE;
            END;
          String.AppendString[text, "ZONE: hours="L];
          String.AppendDecimal[text, hours];
          String.AppendString[
            text, IF westEast = west THEN "(west)"L ELSE "(east)"L];
          String.AppendString[text, ", minutes="L];
          String.AppendDecimal[text, minutes];
          Message[text];
          zoneSpecified ← TRUE;
          END;
        disableNSTimeServer =>
          BEGIN
          IF Token.Boolean[cmFile] THEN
            BEGIN
            Message["Turning OFF the NS Time Server"L];
	    disableNSTimeServer ← TRUE;
            END
          ELSE Message["Didn't turn OFF the NS Time Server"L];
          END;
        ENDCASE => ERROR;
      ENDLOOP;
    Indirect.Close[cmFile];
    ok ← ok AND dstSpecified AND zoneSpecified AND correctionSpecified
      AND driftSpecified AND wobbleSpecified;
    PupTimeServerOps.parmsOk ← ok AND ~flakey;
    IF ok AND ~disableNSTimeServer THEN
      TimeServerOps.Start[]
      ELSE TimeServerOps.Stop[];  -- Created and Started by START Trap
    END;

  SetCorrection: PROCEDURE [arg: LONG INTEGER] =
    BEGIN
    IF arg # 0 THEN
      BEGIN
      secondsPerDay: LONG CARDINAL = 86400;
      delta: LONG INTEGER ← arg;
      bottom: LONG CARDINAL ← 1000*secondsPerDay;
      IF ~TemporarySetGMT.adjustableClockRate THEN
        BEGIN
        Message["The clock on this machine is not adjustable"L];
	RETURN;
	END;
-- Yetch, what a pile of crap
-- 640 works on D0s (or at least some of them)
-- Dicentra needs 274
      UNTIL ABS[delta] < 274 DO  -- Avoid overflow
        delta ← delta/2;
	bottom ← bottom/2;
	ENDLOOP;
      TemporarySetGMT.SetClockRate[bottom, bottom + delta];   
      END;
    END;
  
  Message: PROCEDURE [one, two, three: LONG STRING ← NIL] =
    BEGIN
    text: STRING = [100];
    Time.AppendCurrent[text];
    String.AppendString[text, "  TimeServer: "L];
    String.AppendString[text, one];
    IF two # NIL THEN String.AppendString[text, two];
    IF three # NIL THEN String.AppendString[text, three];
    LogString[text];
    END;
  
  LogString: PROCEDURE [text: LONG STRING] =
    BEGIN
    String.AppendChar[text, '.];
    String.AppendChar[text, Ascii.CR];
    Put.Text[NIL, text];
    END;

  FindParameters[];
  PupTimeServer.PupTimeServerOn[];
  END.