-- PhoneNetworkImpl.mesa (last edited by: Garlick on: August 5, 1980  5:44 PM) --
DIRECTORY
  PhoneNetwork USING [AccessAddress],
  Heap USING [CreateMDS, MakeMDSNode, FreeMDSNode, MakeMDSString, FreeMDSString],
  RS232CManager USING [CommParamHandle, CommParamObject],
  SpecialSystem USING [HostNumber];

PhoneNetworkImpl: MONITOR IMPORTS Heap EXPORTS PhoneNetwork =
  BEGIN
  -- types
  PathList: TYPE = RECORD [head, tail: PathElemHandle];
  PathElemHandle: TYPE = POINTER TO PathListElem;
  PathListElem: TYPE = RECORD [
    previous: PathElemHandle,
    next: PathElemHandle,
    systemElemID: SpecialSystem.HostNumber,
    lineParams: RS232CManager.CommParamHandle,
    phoneNo: PhoneNetwork.AccessAddress];
  -- writeable data
  myHeap: MDSZone;
  -- data structure for keeping path info
  phoneBook: PathList ← [NIL, NIL];
  -- constants
  heapPages: CARDINAL = 1;
  heapThreshold: CARDINAL = 4; -- min block size
  heapPageIncrement: CARDINAL = 1;
  -- errors and signals
  UnknownPath: PUBLIC ERROR = CODE;
  -- ********Phone Network Path Definition********
  FindPhonePath: PUBLIC ENTRY PROCEDURE [
    OISUniqueAddress: SpecialSystem.HostNumber]
    RETURNS [RS232CManager.CommParamHandle, PhoneNetwork.AccessAddress] =
    -- search path table
    BEGIN
    ENABLE UNWIND => NULL; -- release monitor
    -- local
    pathElem: PathElemHandle;
    -- start at head
    pathElem ← phoneBook.head;
    UNTIL pathElem = NIL DO
      IF pathElem.systemElemID = OISUniqueAddress THEN
	RETURN[pathElem.lineParams, pathElem.phoneNo];
      pathElem ← pathElem.next;
      ENDLOOP;
    ERROR UnknownPath;
    END; -- disable UNWIND

  KnowAboutPhonePath: PUBLIC ENTRY PROCEDURE [
    OISUniqueAddress: SpecialSystem.HostNumber,
    commParamHandle: RS232CManager.CommParamHandle,
    phoneNumber: PhoneNetwork.AccessAddress] =
    -- add to path table
    BEGIN
    -- locals
    lineParams: RS232CManager.CommParamHandle;
    accessString: STRING;
    pathElem: PathElemHandle;
    BEGIN
    ENABLE UNWIND => NULL; -- release monitor
    -- allocate, copy  CommParamObject, AccessAddress
    lineParams ← Heap.MakeMDSNode[myHeap, SIZE[RS232CManager.CommParamObject]];
    lineParams↑ ← commParamHandle↑;
    accessString ← Heap.MakeMDSString[myHeap, phoneNumber.length];
    accessString↑ ← [length: 0, maxlength: phoneNumber.length, text:];
    AppendString[accessString, phoneNumber];
    -- allocate table entry
    pathElem ← Heap.MakeMDSNode[myHeap, SIZE[PathListElem]];
    END; -- disable UNWIND
    pathElem↑ ← PathListElem[
      previous: NIL, next: phoneBook.head, systemElemID: OISUniqueAddress,
      lineParams: lineParams, phoneNo: accessString];
    -- Add to  head of phone list
    IF phoneBook.head # NIL THEN phoneBook.head.previous ← pathElem;
    phoneBook.head ← pathElem;
    IF phoneBook.tail = NIL THEN phoneBook.tail ← pathElem;
    END;

  ForgetAboutPhonePath: PUBLIC ENTRY PROCEDURE [
    OISUniqueAddress: SpecialSystem.HostNumber] =
    -- delete the path from path table
    BEGIN
    ENABLE UNWIND => NULL; -- release monitor
    -- local
    pathElem: PathElemHandle;
    -- if active, what will happen? Nothing, transporter will handle it
    pathElem ← phoneBook.head;
    UNTIL pathElem = NIL DO
      -- we only look at the processor ID of the networkAddress
      IF pathElem.systemElemID = OISUniqueAddress THEN
	BEGIN -- delete it
	IF pathElem = phoneBook.head THEN phoneBook.head ← pathElem.next
	ELSE pathElem.previous.next ← pathElem.next;
	IF pathElem = phoneBook.tail THEN phoneBook.tail ← pathElem.previous
	ELSE pathElem.next.previous ← pathElem.previous;
	-- free everything
	Heap.FreeMDSNode[myHeap, pathElem.lineParams];
	Heap.FreeMDSString[myHeap, pathElem.phoneNo];
	Heap.FreeMDSNode[myHeap, pathElem];
	RETURN;
	END;
      pathElem ← pathElem.next;
      ENDLOOP;
    ERROR UnknownPath;
    END; -- disable UNWIND
  -- ********String Support********

  AppendString: PROCEDURE [to: STRING, from: STRING] =
    BEGIN -- assumes to string has room!!
    i, j, n: CARDINAL;
    IF to = NIL OR from = NIL THEN RETURN;
    n ← MIN[from.length, LOOPHOLE[to.maxlength - to.length, CARDINAL]];
    i ← to.length;
    j ← 0;
    WHILE j < n DO to[i] ← from[j]; i ← i + 1; j ← j + 1; ENDLOOP;
    to.length ← i;
    RETURN
    END;
  -- MAIN PROGRAM --
  -- create a heap

  myHeap ← Heap.CreateMDS[
    initial: heapPages, increment: heapPageIncrement, threshold: heapThreshold];
  END.
LOG
Time: January 30, 1980  3:58 PM	By: Garlick	Action: Created file from subset of RS232CManagerImpl.
Time: July 3, 1980  9:33 AM	By: Garlick	Action: Stopped using RS232CHeap.  Started using Heap.
Time: January 30, 1980  3:58 PM	By: Garlick	Action: Stopped using RS232CHeap.  Started using Heap.
Time: July 21, 1980  12:26 PM	By: McJones	Action: Heap.Create+GetMDSHandle=>CreateMDS
Time: August 5, 1980  5:43 PM	By: Garlick	Action: Changed all SpecialSystem.ProcessorIDs to HostNumber so we could accept broadcastHostNumber.