language-Modula2-0.1: examples/Modula-2_Libraries/C.-Lins_Modula-2_Software_Component_Library/Vol1/STACKS/STKSBUI.MOD
IMPLEMENTATION MODULE StkSBUI;
(*==========================================================
Version : 1.00 29 Apr 1989 C. Lins
Compiler : TopSpeed Modula-2
Code Size: R- bytes
Component: Monolithic Structures - Stack (Opaque)
Sequential Bounded Managed Iterator
REVISION HISTORY
v1.00 29 Apr 1989 C. Lins
Initial implementation from StackSBMI module.
==========================================================*)
FROM JPIStorage IMPORT
(*--Proc*) Allocate, Deallocate;
FROM Items IMPORT
(*--Cons*) NullItem,
(*--Type*) Item, AccessProc, ChangeProc,
LoopAccessProc, LoopChangeProc;
FROM ErrorHandling IMPORT
(*--Type*) HandlerProc,
(*--Proc*) NullHandler, ExitOnError, Raise;
FROM StackEnum IMPORT
(*--Type*) Exceptions, Operations, ComponentID;
(*-----------------------*)
TYPE ItemsArray = ARRAY SizeRange OF Item;
TYPE BoundedStack = RECORD
size : SizeRange; (*-- Maximum # of items on this stack *)
top : CARDINAL; (*-- Current stack top := 0 *)
items : ItemsArray; (*-- Dynamic array [1..size] of item *)
END (*-- BoundedStack *);
TYPE Stack = POINTER TO BoundedStack;
(*-----------------------*)
VAR stackError : Exceptions;
VAR handlers : ARRAY Exceptions OF HandlerProc;
(*-----------------------*)
PROCEDURE StackError () : Exceptions (*-- out *);
BEGIN
RETURN stackError;
END StackError;
(*----------------------------*)
PROCEDURE GetHandler ( theError : Exceptions (*-- in *))
: HandlerProc (*-- out *);
BEGIN
RETURN handlers[theError];
END GetHandler;
(*----------------------------*)
PROCEDURE SetHandler ( theError : Exceptions (*-- in *);
theHandler : HandlerProc (*-- in *));
BEGIN
handlers[theError] := theHandler;
END SetHandler;
(*----------------------------*)
PROCEDURE RaiseErrIn ( theRoutine : Operations (*-- in *);
theError : Exceptions (*-- in *));
BEGIN
stackError := theError;
Raise(ComponentID + ModuleID, theRoutine, theError, handlers[theError]);
END RaiseErrIn;
(*----------------------------*)
(*-----------------------*)
PROCEDURE Create ( theSize : SizeRange (*-- in *))
: Stack (*-- out *);
CONST minStackSize = SIZE(BoundedStack) - SIZE(ItemsArray);
VAR newStack : Stack;
BEGIN
stackError := noerr;
Allocate(newStack, minStackSize + SIZE(Item) * theSize);
IF (newStack # NIL) THEN
WITH newStack^ DO
size := theSize;
top := 0;
END (*--with*);
RETURN newStack;
END (*--if*);
RaiseErrIn(create, overflow);
RETURN NullStack;
END Create;
(*----------------------------*)
PROCEDURE Destroy (VAR theStack : Stack (*-- inout *));
CONST minStackSize = SIZE(BoundedStack) - SIZE(ItemsArray);
BEGIN
Clear(theStack);
IF (stackError = noerr) THEN
Deallocate(theStack, minStackSize + SIZE(Item) * theStack^.size);
END (*--if*);
END Destroy;
(*----------------------------*)
PROCEDURE Clear (VAR theStack : Stack (*-- inout *));
VAR itemIndex : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
top := 0;
END (*--with*);
ELSE
RaiseErrIn(clear, undefined);
END (*--if*);
END Clear;
(*----------------------------*)
PROCEDURE Assign ( theStack : Stack (*-- in *);
VAR toStack : Stack (*-- inout *));
VAR itemIndex : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
IF (toStack # NIL) THEN
IF (theStack^.top <= toStack^.size) THEN
Clear(toStack);
ELSE
RaiseErrIn(assign, overflow);
END (*--if*);
ELSE
WITH theStack^ DO
toStack := Create(size);
END (*--with*);
END (*--if*);
IF (stackError # noerr) THEN
RETURN;
END (*--if*);
WITH theStack^ DO
FOR itemIndex := MIN(SizeRange) TO top DO
toStack^.items[itemIndex] := items[itemIndex];
END (*--for*);
toStack^.top := top;
END (*--with*);
ELSE
RaiseErrIn(assign, undefined);
END (*--if*);
END Assign;
(*----------------------------*)
PROCEDURE Push (VAR toStack : Stack (*-- inout *);
theItem : Item (*-- in *));
BEGIN
stackError := noerr;
IF (toStack # NIL) THEN
WITH toStack^ DO
IF (top < size) THEN
INC(top);
items[top] := theItem;
ELSE
RaiseErrIn(push, overflow);
END (*--if*);
END (*--with*);
ELSE
RaiseErrIn(push, undefined);
END (*--if*);
END Push;
(*----------------------------*)
PROCEDURE Pop (VAR theStack : Stack (*-- inout *));
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
IF (top # 0) THEN
DEC(top);
ELSE
RaiseErrIn(pop, underflow);
END (*--if*);
END (*--with*);
ELSE
RaiseErrIn(pop, undefined);
END (*--if*);
END Pop;
(*----------------------------*)
PROCEDURE PopTopOf (VAR theStack : Stack (*-- inout *))
: Item (*-- out *);
VAR theItem : Item; (*-- item to be returned *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
IF (top # 0) THEN
theItem := items[top];
DEC(top);
RETURN theItem;
END (*--if*);
END (*--with*);
RaiseErrIn(poptopof, underflow);
ELSE
RaiseErrIn(poptopof, undefined);
END (*--if*);
(*-- Return the empty item if an exception occurred. *)
RETURN NullItem;
END PopTopOf;
(*----------------------------*)
PROCEDURE IsDefined ( theStack : Stack (*-- in *))
: BOOLEAN (*-- out *);
BEGIN
RETURN (theStack # NIL);
END IsDefined;
(*----------------------------*)
PROCEDURE IsEmpty ( theStack : Stack (*-- in *))
: BOOLEAN (*-- out *);
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
RETURN theStack^.top = 0;
END (*--if*);
RaiseErrIn(isempty, undefined);
RETURN TRUE;
END IsEmpty;
(*----------------------------*)
PROCEDURE IsEqual ( left : Stack (*-- in *);
right : Stack (*-- in *))
: BOOLEAN (*-- out *);
VAR index : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (left # NIL) & (right # NIL) THEN
IF (left^.top = right^.top) THEN
FOR index := MIN(SizeRange) TO left^.top DO
IF (left^.items[index] # right^.items[index]) THEN
RETURN FALSE;
END (*--if*);
END (*--for*);
RETURN TRUE;
END (*--if*);
ELSE
RaiseErrIn(isequal, undefined);
END (*--if*);
RETURN FALSE;
END IsEqual;
(*----------------------------*)
PROCEDURE SizeOf ( theStack : Stack (*-- in *))
: CARDINAL (*-- out *);
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
RETURN theStack^.size;
END (*--if*);
RaiseErrIn(sizeof, undefined);
RETURN 0;
END SizeOf;
(*----------------------------*)
PROCEDURE DepthOf ( theStack : Stack (*-- in *))
: CARDINAL (*-- out *);
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
RETURN theStack^.top;
END (*--if*);
RaiseErrIn(depthof, undefined);
RETURN 0;
END DepthOf;
(*----------------------------*)
PROCEDURE TopOf ( theStack : Stack (*-- in *))
: Item (*-- out *);
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
IF (top # 0) THEN
RETURN items[top];
END (*--if*);
END (*--with*);
RaiseErrIn(topof, underflow);
ELSE
RaiseErrIn(topof, undefined);
END (*--if*);
(*-- Return the empty item if an exception occurred *)
RETURN NullItem;
END TopOf;
(*----------------------------*)
PROCEDURE LoopOver ( theStack : Stack (*-- in *);
theProcess: LoopAccessProc (*-- in *));
VAR index : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
FOR index := top TO MIN(SizeRange) BY -1 DO
IF ~theProcess(items[index]) THEN
RETURN;
END (*--if*);
END (*--for*);
END (*--with*);
ELSE
RaiseErrIn(loopover, undefined);
END (*--if*);
END LoopOver;
(*----------------------------*)
PROCEDURE LoopChange ( theStack : Stack (*-- in *);
theProcess: LoopChangeProc (*-- in *));
VAR index : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
FOR index := top TO MIN(SizeRange) BY -1 DO
IF ~theProcess(items[index]) THEN
RETURN;
END (*--if*);
END (*--for*);
END (*--with*);
ELSE
RaiseErrIn(loopchange, undefined);
END (*--if*);
END LoopChange;
(*----------------------------*)
PROCEDURE Traverse ( theStack : Stack (*-- in *);
theProcess: AccessProc (*-- in *));
VAR index : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
FOR index := top TO MIN(SizeRange) BY -1 DO
theProcess(items[index]);
END (*--for*);
END (*--with*);
ELSE
RaiseErrIn(traverse, undefined);
END (*--if*);
END Traverse;
(*----------------------------*)
PROCEDURE TravChange ( theStack : Stack (*-- in *);
theProcess: ChangeProc (*-- in *));
VAR index : CARDINAL; (*-- loop index over items *)
BEGIN
stackError := noerr;
IF (theStack # NIL) THEN
WITH theStack^ DO
FOR index := top TO MIN(SizeRange) BY -1 DO
theProcess(items[index]);
END (*--for*);
END (*--with*);
ELSE
RaiseErrIn(traverse, undefined);
END (*--if*);
END TravChange;
(*----------------------------*)
BEGIN
FOR stackError := initfailed TO MAX(Exceptions) DO
SetHandler(stackError, ExitOnError);
END (*--for*);
SetHandler(noerr, NullHandler);
stackError := noerr;
END StkSBUI.