(*********************************************************************
 *                                                                   *
 *  :Program.    Queue.mod                                           *
 *  :Author.     Michael Frieß                                       *
 *  :Address.    Kernerstr. 22a                                      *
 *  :shortcut.   [MiF]                                               *
 *  :Version.    1.0                                                 *
 *  :Date.       14.09.88                                            *
 *  :Copyright.  PD                                                  *
 *  :Language.   Modula-II                                           *
 *  :Translator. M2Amiga                                             *
 *  :Imports.    MemSystem (at least V1.0 --> Amok#5)                *
 *  :Contents.   Generic data type: Queue                            *
 *                                                                   *
 *********************************************************************)

IMPLEMENTATION MODULE Queue;
(* MODULE Queue: (C) Copyright 1988 by Michael Frieß *)

FROM SYSTEM    IMPORT BYTE, ADR, ADDRESS;
FROM MemSystem IMPORT Allocate, Deallocate;
FROM Exec      IMPORT CopyMem;

CONST copyright = "MODULE Queue: (C) Copyright 1988 by Michael Frieß";

TYPE queue      = POINTER TO queuebody;
     elementptr = POINTER TO element;
     element    = RECORD
                   Data : ADDRESS;
                   Next : elementptr;
                  END;
      queuebody = RECORD
                   Top, Bottom : elementptr;
                  END;

PROCEDURE Init (VAR q:queue);
 BEGIN
  Allocate (q, SIZE(queuebody));
  IF q = NIL THEN HALT END;
  q^.Top := NIL;
  q^.Bottom := NIL;
 END Init;

PROCEDURE Write  (q:queue; Data : ARRAY OF BYTE);
 BEGIN
  IF q^.Bottom = NIL THEN
    Allocate (q^.Bottom, SIZE(element));
    IF q^.Bottom = NIL THEN HALT END;
    q^.Bottom^.Next := NIL;
    q^.Top :=  q^.Bottom
  ELSE
    Allocate (q^.Bottom^.Next, SIZE(element));
    IF q^.Bottom^.Next = NIL THEN HALT END;
    q^.Bottom := q^.Bottom^.Next
  END;
  Allocate (q^.Bottom^.Data, HIGH(Data)+1);
  IF q^.Bottom^.Data = NIL THEN HALT END;
  CopyMem (ADR(Data), q^.Bottom^.Data, HIGH(Data)+1);
 END Write;

PROCEDURE Read (q:queue; VAR Data : ARRAY OF BYTE);
 VAR p : elementptr;
 BEGIN
  IF q^.Top # NIL THEN
   CopyMem (q^.Top^.Data, ADR(Data), HIGH(Data)+1);
   IF q^.Top = q^.Bottom THEN
    q^.Bottom := NIL;
   END;
   p := q^.Top^.Next;
   Deallocate (q^.Top^.Data);
   Deallocate (q^.Top);
   q^.Top := p
  END
 END Read;

PROCEDURE Empty (q:queue) : BOOLEAN;
 BEGIN
  RETURN q^.Top = NIL
 END Empty;

PROCEDURE Discard (VAR q:queue);
 BEGIN
  WHILE q^.Top # NIL DO
   q^.Bottom := q^.Top^.Next;
   Deallocate (q^.Top^.Data);
   Deallocate (q^.Top);
   q^.Top := q^.Bottom
  END;
  Deallocate (q);
 END Discard;

END Queue.
