(**********************************************************************

:Program.    Liste.mod
:Contens.    Ein Biliotheksmodul für Listen. 
:Contens.    Nur für das Programm Rechtschreib zu gebrauchen.
:Author.     Bernd Braun
:Address.    Lippestr. 11, D-3300 Braunschweig
:Phone.      0531/845498
:Copyright.  Public Domain
:Language.   Modula-2
:Translator. M2Amiga A+L V3.32d
:Imports.    DynStr
:History.    V1.0 3.Okt.1990

***********************************************************************)

IMPLEMENTATION MODULE Liste;

   FROM Arts IMPORT
      Assert;
   FROM DynStr IMPORT
      DynString, ForgetDynString, DynStringCompare;
   FROM Storage IMPORT
      Available, ALLOCATE, DEALLOCATE;
   FROM SYSTEM IMPORT
      TSIZE, ADR;

   CONST
      ErrMsg = 'Liste: Liste ist NIL';
      MemMsg = 'Liste: Kein Speicher mehr!';

   (* Initialisiert die Liste L *)
   PROCEDURE InitList ( VAR L  : List );
   BEGIN
      Assert ( Available ( TSIZE ( ListHead ) ),
               ADR ( MemMsg ) );                   (* Speicher vorhanden ? *)
      ALLOCATE ( L, TSIZE ( ListHead ) );        (* Erzeuge den Listenkopf *)
      WITH L ^ DO                           (* Initialisere den Listenkopf *)
         LL    := NIL;                                      (* Leere Liste *)
         last  := NIL;
      END;
   END InitList;

   (* Löscht alle Einträge der Liste L und sie selber. *)
   PROCEDURE ExitList ( VAR L : List );
      VAR
         p, q : LList; (* Hilfszeiger zum Löschen der Liste. *)
   BEGIN
      Assert ( L # NIL , ADR ( ErrMsg ) );
      p := L ^. LL;                        (* p zeigt auf den Listenanfang *)
      WHILE p # NIL DO                          (* Besuche die ganze Liste *)
         q := p;                             (* q = der zu lschende Knoten *)
         p := p ^. next;                                 (* p = Nachfolger *)
         ForgetDynString ( q ^. Item );
         DEALLOCATE ( q, TSIZE ( Node ) )             (* Lösche den Knoten *)
      END;
      DEALLOCATE ( L, TSIZE ( ListHead ) );       (* Lösche den Listenkopf *)
      L := NIL                                              (* Leere Liste *)
   END ExitList;

   (* Fügt einen Dynstring an Ende der Liste L ein. *)
   PROCEDURE InsertList ( VAR L      : List;
                              DynStr : DynString );
      VAR
         p : LList; (* Hilfszeiger *)
   BEGIN
      Assert ( L # NIL , ADR ( ErrMsg ) );
      Assert ( Available ( TSIZE ( Node ) ), ADR ( MemMsg ) );
      ALLOCATE ( p, TSIZE ( Node ) );              (* Erzeuge einen Knoten *)
      WITH p ^ DO                              (* Initialisiere den Knoten *)
         Item := DynStr;
         next := NIL;
      END;
      WITH L ^ DO                        (* Richte den last-Zeiger neu ein *)
         IF LL # NIL THEN                        (* Nicht erstes Element ? *)
            last ^. next := p;            (* Zeiger des Vorgängers auf den *)
                                                 (* neuen Eintrag richten. *)
         ELSE                                            (* Erstes Element *)
            LL := p;
         END;
         last := p;                   (* last-Zeiger zeigt aufs Listenende *)
      END;
   END InsertList;

   (* Sucht einen Dynstring in Liste L. Gibt bei Erfolg TRUE zurück,
      FALSE sonst. *)
   PROCEDURE MemberList ( L      : List;
                          DynStr : DynString ) : BOOLEAN;
      VAR
         p     : LList;
         found : BOOLEAN;
   BEGIN
      Assert ( L # NIL , ADR ( ErrMsg ) );
      found := FALSE;
      p := NIL;                                    (* Noch nichts gefunden *)
      WITH L ^ DO
         p := LL;
         WHILE ( p # NIL ) AND NOT found DO
            IF DynStringCompare ( p ^. Item, DynStr ) = 0 THEN
               found := TRUE;
            END;
            p := p ^. next;
         END;
      END;
      RETURN found;                                  (* Eintrag gefunden ? *)
   END MemberList;

   (* Gibt einen Zeiger auf den ersten Eintrag der Liste L zurück.
      Gibt in DynStr den Eintrag des ersten Elements zurück, falls L
      nicht leer. *)
   PROCEDURE FirstList (     L      : List;
                         VAR DynStr : DynString ) : LList;
   BEGIN
      Assert ( L # NIL , ADR ( ErrMsg ) );
      WITH L ^ DO
         IF LL # NIL THEN                    (* Ist die Liste nicht leer ? *)
            WITH LL ^ DO
               DynStr := Item;
            END;
         END;
         RETURN LL;                          (* Gebe dessen Adresse zurück *)
      END;
   END FirstList;

   (* Gibt einen Zeiger auf den Nachfolger nach dem Eintrag vorg in Liste L 
      zurück. Gibt in DynStr den Eintrag im Nachfolger zurück, fals 
      Nachfolger vorhanden. Gibt es keinen Nachfolger wird NIL 
      als Prozedurresultat zurückgegeben. *)
   PROCEDURE NextList  (     L      : List;
                             vorg   : LList;
                         VAR DynStr : DynString ) : LList;
   BEGIN
      Assert ( vorg # NIL, ADR ( ErrMsg ) );
      WITH vorg ^ DO
         IF next # NIL THEN
            DynStr := next ^. Item;
            RETURN next;
         ELSE
            RETURN NIL;
         END;
      END;
   END NextList;

END Liste.
