-- File: AMCUCool.mesa,  Last Edit:
  -- MAS  Apr 18, 1980 4:30 PM
  -- HGM  July 19, 1979  8:15 PM

-- Copyright  Xerox Corporation 1979, 1980

DIRECTORY
  ControlDefs: FROM "ControlDefs" USING [FrameHandle, GlobalFrameHandle],
  FrameDefs: FROM "FrameDefs" USING [GlobalFrame, UnNew],
  FrameOps: FROM "FrameOps" USING [SetReturnLink, GetReturnFrame, Free],
  InlineDefs: FROM "InlineDefs" USING [COPY],
  Mopcodes: FROM "Mopcodes" USING [zPOP],
  ProcessDefs: FROM "ProcessDefs" USING [
    Ticks, Detach, Yield, MsecToTicks,
    SetTimeout, DisableTimeout, InitializeCondition, InitializeMonitor],
  ProcessOps: FROM "ProcessOps" USING [TimerGrain],
  StringDefs: FROM "StringDefs" USING [
    StringBoundsFault, WordsForString, AppendLongNumber],
  SystemDefs: FROM "SystemDefs" USING [AllocateHeapNode, FreeHeapNode],
  CommUtilDefs: FROM "CommUtilDefs" USING [GetTicks, msPerTick],
  DriverDefs: FROM "DriverDefs" USING [doStats],
  PupStream: FROM "PupStream",  -- EXPORTs
  PupDefs: FROM "PupDefs" USING [Tocks];

AMCUCool: PROGRAM
  IMPORTS
    FrameDefs, FrameOps, InlineDefs, ProcessDefs,
    StringDefs, SystemDefs, CommUtilDefs
  EXPORTS CommUtilDefs, PupStream, PupDefs
  SHARES StringDefs =
BEGIN

doStats: BOOLEAN = DriverDefs.doStats;


-- vanilla process things
Ticks: TYPE = ProcessDefs.Ticks;


Detach: PUBLIC PROCEDURE [foo: UNSPECIFIED] =
  BEGIN
  ProcessDefs.Detach[foo];
  END;

Yield: PUBLIC PROCEDURE =
  BEGIN
  ProcessDefs.Yield[];
  END;

MsecToTicks: PUBLIC PROCEDURE [foo: CARDINAL] RETURNS [Ticks] =
  BEGIN
  RETURN[ProcessDefs.MsecToTicks[foo]];
  END;

Shorten: PROCEDURE [LONG POINTER] RETURNS [POINTER] =
  MACHINE CODE BEGIN
  Mopcodes.zPOP;
  END;

SetTimeout: PUBLIC PROCEDURE [c: LONG POINTER TO CONDITION, t: Ticks] =
  BEGIN
  ProcessDefs.SetTimeout[Shorten[c],t];
  END;

DisableTimeout: PUBLIC PROCEDURE [c: LONG POINTER TO CONDITION] =
  BEGIN
  ProcessDefs.DisableTimeout[Shorten[c]];
  END;

InitializeCondition: PUBLIC PROCEDURE [c: LONG POINTER TO CONDITION, t: Ticks] =
  BEGIN
  ProcessDefs.InitializeCondition[Shorten[c],t];
  END;

InitializeMonitor: PUBLIC PROCEDURE [m: LONG POINTER TO MONITORLOCK] =
  BEGIN
  ProcessDefs.InitializeMonitor[Shorten[m]];
  END;

-- Heap nodes

AllocateLockedNode: PUBLIC PROCEDURE [CARDINAL] RETURNS [POINTER] = AllocateHeapNode;
AllocateHeapNode: PUBLIC PROCEDURE [nwords: CARDINAL] RETURNS [p: POINTER] =
  BEGIN
  p ← SystemDefs.AllocateHeapNode[nwords];
  END;

FreeHeapNode: PUBLIC PROCEDURE [p: POINTER] =
  BEGIN
  SystemDefs.FreeHeapNode[p];
  END;


-- Heap STRINGs

AllocateHeapString: PUBLIC PROCEDURE [nchar: CARDINAL] RETURNS [STRING] =
  BEGIN
  p: POINTER TO MACHINE DEPENDENT RECORD [ -- fake STRING header
    length: CARDINAL,
    maxlength: CARDINAL ];
  p ← AllocateHeapNode[StringDefs.WordsForString[nchar]];
  p.length ← 0;
  p.maxlength ← nchar;
  RETURN[LOOPHOLE[p]];
  END;

FreeHeapString: PUBLIC PROCEDURE [s: STRING] = FreeHeapNode;




-- New and UnNew things
GlobalFrameHandle: TYPE = ControlDefs.GlobalFrameHandle;

GlobalFrame: PUBLIC PROCEDURE [link: UNSPECIFIED] RETURNS [gf: GlobalFrameHandle] = 
  BEGIN
  gf ← FrameDefs.GlobalFrame[link];
  END;

SelfDestruct: PUBLIC PROCEDURE =
  BEGIN
  destructee: ControlDefs.FrameHandle ← FrameOps.GetReturnFrame[];
  FrameOps.SetReturnLink[destructee.returnlink];
  FrameDefs.UnNew[FrameDefs.GlobalFrame[destructee]];
  FrameOps.Free[destructee];
  RETURN
  END;

-- Things from StringDefs.  Copy over to avoid dragging in Strings.bcd

AppendChar: PUBLIC PROCEDURE [s: STRING, c: CHARACTER] =
  BEGIN
  UNTIL s.length<s.maxlength DO
    s ← SIGNAL StringDefs.StringBoundsFault[s];
    ENDLOOP;
  s[s.length] ← c;
  s.length ← s.length+1;
  END;  

AppendString: PUBLIC PROCEDURE [to, from: STRING] =
  BEGIN
  i, j, n: CARDINAL;
  WHILE (from.length+to.length)>to.maxlength DO
    to ← SIGNAL StringDefs.StringBoundsFault[to];
    ENDLOOP;
  n ← MIN[from.length, to.maxlength-to.length];
  i ← to.length;
  j ← 0;
  WHILE j < n
    DO
    to[i] ← from[j];
    i ← i+1; j ← j+1;
    ENDLOOP;
  to.length ← i;
  END;  

AppendLongNumber: PUBLIC PROCEDURE [s: STRING, n: LONG INTEGER, r: CARDINAL] =
  BEGIN
  StringDefs.AppendLongNumber[s,n,r];
  END;  

-- Other goodies
Zero: PUBLIC PROCEDURE [p: POINTER, l: CARDINAL] =
  BEGIN
  IF l=0 THEN RETURN;
  p↑ ← 0;
  InlineDefs.COPY[from: p, to: p+1, nwords: l-1];
  END;



-- Clock
GetClock: PUBLIC PROCEDURE RETURNS [ms: LONG CARDINAL] =
  BEGIN
  ms ← LONG[CommUtilDefs.GetTicks[]]*CommUtilDefs.msPerTick;  -- UGH procedure call
  END;

-- TimeCoversion

TockConversionTroubles: PUBLIC ERROR = CODE;

msPerTock: CARDINAL = ProcessOps.TimerGrain;

SecondsToTocks: PUBLIC PROCEDURE [t: CARDINAL] RETURNS [PupDefs.Tocks] =
  BEGIN
  IF t ~IN [1..(177777B/(1000/msPerTock))) THEN ERROR TockConversionTroubles;
  RETURN[[t*(1000/msPerTock)]];
  END;

MsToTocks: PUBLIC PROCEDURE [t: CARDINAL] RETURNS [PupDefs.Tocks] =
  BEGIN
  IF t=0 THEN ERROR TockConversionTroubles;
  IF (t+msPerTock)>t THEN t←t+(msPerTock-1);  -- roundup if won't overflow
  RETURN[[t/msPerTock]];
  END;

-- initialization
END.  -- AMCUCool