-- Transport mechanism: FSP implementation of R-Lists

-- [Juniper]<dms>ms>FSPRList.mesa

-- Andrew Birrell  15-Oct-80 15:26:14

DIRECTORY
  BodyDefs USING [maxRNameLength, RName, RNameSize],
  ProtocolDefs USING [Handle, ReceiveCount, ReceiveRName],
  RListDefs USING [],
  Storage USING [Free, FreeString, Node, String],
  String USING [AppendString];

FSPRList: PROGRAM
IMPORTS BodyDefs, ProtocolDefs, String, Storage
EXPORTS RListDefs =

BEGIN

RListHandle: PUBLIC TYPE = POINTER TO RListItem;

RListItem: TYPE = RECORD[next: RListHandle, name: BodyDefs.RName];

noList: RListHandle = NIL;

Receive: PUBLIC PROC[str: ProtocolDefs.Handle]
             RETURNS[list: RListHandle] =
   BEGIN
   buffer: BodyDefs.RName = [BodyDefs.maxRNameLength];
   count: CARDINAL ← ProtocolDefs.ReceiveCount[str];
   tail: POINTER TO RListHandle ← @list;
   list ← noList;
   WHILE count > 0
   DO ENABLE UNWIND => Close[list];
      ProtocolDefs.ReceiveRName[str, buffer];
      count ← count - BodyDefs.RNameSize[buffer];
      BEGIN
         new: RListHandle = Storage.Node[SIZE[RListItem]];
         new↑ ← [name: Storage.String[buffer.length],
                 next: noList];
         String.AppendString[new.name, buffer];
         tail↑ ← new; tail ← @(new.next);
      END;
   ENDLOOP;
   END;

Enumerate: PUBLIC PROC[list: RListHandle,
                       work: PROC[BodyDefs.RName]RETURNS[done:BOOLEAN] ] =
   BEGIN
   FOR list ← list, list.next UNTIL list = noList OR work[list.name]
   DO NULL ENDLOOP;
   END;

Close: PUBLIC PROC[list: RListHandle] =
   BEGIN
   WHILE list # noList
   DO next: RListHandle = list.next;
      Storage.FreeString[list.name];
      Storage.Free[list];
      list ← next;
   ENDLOOP;
   END;

END.