(* M2StackWord.mod provides a generic stack for WORD sized objects. Copyright (C) 2001-2023 Free Software Foundation, Inc. Contributed by Gaius Mulley . This file is part of GNU Modula-2. GNU Modula-2 is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Modula-2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Modula-2; see the file COPYING3. If not see . *) IMPLEMENTATION MODULE M2StackWord ; FROM Storage IMPORT ALLOCATE, DEALLOCATE ; FROM M2Error IMPORT InternalError ; FROM M2Debug IMPORT Assert ; CONST MaxBucket = 10 ; TYPE StackBucketWord = POINTER TO BucketWord ; BucketWord = RECORD bucket: ARRAY [0..MaxBucket-1] OF WORD ; items : CARDINAL ; last : StackBucketWord ; END ; StackOfWord = POINTER TO StackDescriptor ; StackDescriptor = RECORD tail: StackBucketWord ; END ; (* InitStackWord - creates and returns a new stack. *) PROCEDURE InitStackWord () : StackOfWord ; VAR s: StackOfWord ; BEGIN NEW(s) ; WITH s^ DO tail := NIL END ; RETURN( s ) END InitStackWord ; (* KillBucket - destroys a StackBucketWord and returns, NIL. *) PROCEDURE KillBucket (b: StackBucketWord) : StackBucketWord ; BEGIN IF b#NIL THEN b := KillBucket(b^.last) ; DISPOSE(b) END ; RETURN( NIL ) END KillBucket ; (* KillStackWord - destroys a stack, returning NIL. *) PROCEDURE KillStackWord (s: StackOfWord) : StackOfWord ; BEGIN IF s#NIL THEN s^.tail := KillBucket(s^.tail) ; DISPOSE(s) END ; RETURN( NIL ) END KillStackWord ; (* InitBucket - returns an empty StackBucketWord. *) PROCEDURE InitBucket (l: StackBucketWord) : StackBucketWord ; VAR b: StackBucketWord ; BEGIN NEW(b) ; WITH b^ DO items := 0 ; last := l END ; RETURN( b ) END InitBucket ; (* PushWord - pushes a word, w, onto, s. *) PROCEDURE PushWord (s: StackOfWord; w: WORD) ; BEGIN IF s=NIL THEN InternalError ('stack has not been initialized') ELSE WITH s^ DO IF (tail=NIL) OR (tail^.items=MaxBucket) THEN tail := InitBucket(tail) END ; WITH tail^ DO IF items=1 DO IF b=NIL THEN InternalError ('stack underflow') ELSIF b^.items>=n THEN RETURN( b^.bucket[b^.items-n] ) ELSE Assert(b^.items=n THEN DEC( s^.tail^.items, n) ; RETURN (* all done exit *) ELSE b := s^.tail ; DEC(n, b^.items) ; s^.tail := s^.tail^.last ; DISPOSE(b) END END END END ReduceWord ; (* RemoveTop - throw away the top element of the stack. *) PROCEDURE RemoveTop (s: StackOfWord) ; BEGIN ReduceWord (s, 1) END RemoveTop ; (* NoOfItemsInStackWord - returns the number of items held in the stack, s. *) PROCEDURE NoOfItemsInStackWord (s: StackOfWord) : CARDINAL ; VAR b: StackBucketWord ; n: CARDINAL ; BEGIN IF IsEmptyWord(s) THEN RETURN( 0 ) ELSE n := 0 ; b := s^.tail ; WHILE b#NIL DO INC(n, b^.items) ; b := b^.last END ; RETURN( n ) END END NoOfItemsInStackWord ; END M2StackWord.