{ > If you want, I can post a few good and simple examples of OOP > concepts to get you started. { -- A simple stack object with the nice flexibility that only OOP can provide. Data structures StackItem: node for a doubly linked list containing an untyped pointer to hold data. It is the responsibility of descendant types to type this pointer. (override push and pop) StackTop :pointer to available stack item StackBottom :pointer to the bottom (end/root) of the stack StackHt :number of items on stack StackST :status variable Methods Init - initializes the stack object, StackHt = 0, all pointers = nil *** YOU MUST CALL THIS BEFORE ACCESSING STACK *** done - destructor deallocates the stack by doing successive pops until the stack is empty. *** YOU MUST OVERRIDE THIS METHOD WHEN YOU OVERRIDE *** *** PUSH AND POP. ITEMS POPPED ARE NOT DEALLOCATED *** Push - Pushes an item onto the stack by: 1) Allocating a new StackItem (if StackHt>0) 2) Assigning pointer dta to data field 3) Incrementing StackHt Pop - Pops by reversing push method: 1) Recovering dta pointer from data field 2) Deallocating "top" StackItem (if StackHt>1) 3) Decrementing StackHt Most decendant types will override push and pop to type the data field, and call STACK.push or STACK.pop to do the "basic" operations. IsError - shows if an error condition exists MemoryOK - internally used function to check available heap. } Unit OSTACK; INTERFACE CONST MAX_STACK = 100; MIN_MEMORY = 4096; StatusOK = 0; StatusOFlow = 1; StatusEmpty = 2; StatHeapErr = 3; TYPE ItemPtr = ^StackItem; StackItem = RECORD data :pointer; prev, next :ItemPtr; END; { StackItem } STACK = OBJECT StackTop, StackBottom :ItemPtr; StackST :integer; StackHt :byte; constructor init; destructor done; virtual; procedure push(var d); virtual; procedure pop(var d); virtual; function IsError:boolean; private function MemoryOK:boolean; END; { STACK } IMPLEMENTATION constructor STACK.init; BEGIN New(StackBottom); StackTop := StackBottom; StackBottom^.prev := NIL; StackBottom^.next := NIL; StackBottom^.data := NIL; StackHt := 0; StackST := StatusOK; END; destructor STACK.done; VAR val :pointer; BEGIN if StackHt>0 then repeat pop(val); until val = nil; Dispose(StackBottom); END; procedure STACK.push(var d); VAR TemPtr :ItemPtr; dta :pointer ABSOLUTE d; BEGIN if not MemoryOK then EXIT; if (StackHt>=MAX_STACK) then begin StackST := StatusOFlow; EXIT; end; If StackHt>0 then BEGIN New(StackTop^.next); TemPtr := StackTop; StackTop := TemPtr^.next; StackTop^.prev := TemPtr; StackTop^.next := NIL; END; StackTop^.data := dta; Inc(StackHt); END; procedure STACK.pop(var d); VAR dta :pointer ABSOLUTE d; BEGIN if StackHt>1 then BEGIN dta := StackTop^.data; StackTop := StackTop^.prev; Dispose(StackTop^.next); StackTop^.next := NIL; Dec(StackHt); if StackST = StatusOFlow then StackST := StatusOK; END ELSE BEGIN if StackHt = 1 then BEGIN dta := StackBottom^.data; StackBottom^.data := nil; Dec(StackHt); END ELSE begin dta := StackBottom^.data; StackST := StatusEmpty; end; END; END; function STACK.IsError:boolean; begin if StackST = StatusOK then IsError := FALSE else IsError := TRUE; end; function STACK.MemoryOK:boolean; begin if MaxAvail0 then repeat pop(tmp); until tmp = NOREG; end; procedure RegisterStack.push(var d); var tmp :pOpRec; dta :OpRec ABSOLUTE d; begin New(tmp); tmp^ := dta; inherited push(tmp); end; procedure RegisterStack.pop(var d); var tmp :pOpRec; dta :OpRec ABSOLUTE d; begin inherited pop(tmp); if StackST = StatusEmpty then begin dta := NOREG; EXIT; end else if tmp<>nil then begin dta := tmp^; Dispose(tmp); end else dta := NOREG; end;