home *** CD-ROM | disk | FTP | other *** search
- {
- ════════════════════════════════════════════════════════════════════════════
-
- Visionix ExitProc Unit (VPROC)
- Version 0.4
- Copyright 1991,92,93 Visionix
- ALL RIGHTS RESERVED
-
- Manages an ExitProc Stack for easing the halting of a program.
-
- ────────────────────────────────────────────────────────────────────────────
-
- Revision history in reverse chronological order:
-
- Initials Date Comment
-
- ──────── ──────── ────────────────────────────────────────────────────────
-
- lpg 03/16/93 Added Source Documentation
-
- mep 02/11/93 Updated code for release - new names for functions.
- Cleaned up code for beta release
-
- jrt 02/08/93 Sync with beta 0.12 release
-
- mep 01/24/93 Initialized.
-
- ────────────────────────────────────────────────────────────────────────────
- }
-
- (*-
-
- [TEXT]
-
- <Overview>
-
- This procedure implements an "exit procedure stack" which manages a list
- of procedures which should be called when a Turbo Pascal application
- terminates. It provides functions to dynamically add and remove
- procedures to/from the exit stack.
-
- <Interface>
-
- -*)
-
- Unit VxProcu;
-
- Interface
-
- Type
-
- {---------------------------------}
- { Generic types for PROCEDURE and }
- { Pointer to procedure; used by }
- { isolation routines. }
- {---------------------------------}
-
- PProcCall = ^TProcCall;
- TProcCall = PROCEDURE;
-
- {----------------------------------}
- { Procedure stack types, used for }
- { the exit procedure stack at }
- { system shutdown }
- {----------------------------------}
-
- PProcStack = ^TProcStack;
- TProcStack = RECORD
-
- Proc : PProcCall;
- Next : PProcStack;
-
- END;
-
- Var
-
- ProcStack : PProcStack;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- Procedure VProcPush( Proc : PProcCall );
-
- Procedure VProcPop( Proc : PProcCall );
-
- Function VProcPopNext : PProcCall;
-
- Procedure VProcRemove( Proc : PProcCall );
-
- Procedure VProcRemoveAll;
-
- Procedure VProcDoExit;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- IMPLEMENTATION
-
- Var
-
- SaveExitProc : POINTER;
- SaveMaxAvail : LONGINT;
- SaveMemAvail : LONGINT;
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VProcPush( Proc : PProcCall );
-
- [PARAMETERS]
-
- Proc Pointer to a procedure-type.
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- This procedure pushs a far procedure onto the exit stack, which will be
- automatically called upon a program halt.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VProcPush( Proc : PProcCall );
-
- Var
-
- NewNode : PProcStack;
- TempNode : PProcStack;
-
- BEGIN
-
- {-----------------------------------}
- { !! check if enuf mem for node???? }
- {-----------------------------------}
-
- If MaxAvail < SizeOf(TProcStack) Then
- Exit;
-
- {-----------------------}
- { Allocate the new node }
- {-----------------------}
-
- New( NewNode );
-
- {----------------------}
- { Fill in the new node }
- {----------------------}
-
- NewNode^.Proc := Proc;
- NewNode^.Next := NIL;
-
- {--------------------------------}
- { find out where on the stack to }
- { put the new node, and put it }
- { on the stack }
- {--------------------------------}
-
- If ProcStack = NIL Then
- BEGIN
-
- ProcStack := NewNode;
-
- END { If ProcStack } { if stack empty }
-
- Else
- BEGIN
-
- TempNode := ProcStack;
-
- While (TempNode^.Next <> NIL) DO
- TempNode := TempNode^.Next;
-
- TempNode^.Next := NewNode;
-
- END; { If ProcStack / Else } { if stack empty / ELSE }
-
- END; { VProcPush }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VProcPop( Proc : PProcCall );
-
- [PARAMETERS]
-
- Proc Pointer to a procedure-type.
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Prematurely pops (calls then removes) a far procedure from the exitproc
- stack.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VProcPop( Proc : PProcCall );
-
- Var
-
- TempNode : PProcStack;
-
- BEGIN
-
- {-----------------------------------}
- { Make sure there is a stack at all }
- {-----------------------------------}
-
- If ( (ProcStack <> NIL) AND (Proc <> NIL) ) Then
- BEGIN
-
- {-------------------------------------}
- { Search for the node containing Proc }
- {-------------------------------------}
-
- TempNode := ProcStack;
-
- While (TempNode^.Next <> NIL) AND
- (TempNode^.Proc <> Proc) Do
- TempNode := TempNode^.Next;
-
- {-------------}
- { Found Node? }
- {-------------}
-
- If (TempNode^.Proc = Proc) Then
- BEGIN
-
- TProcCall( Proc );
- VProcRemove( Proc );
-
- END; { If TempNode^.Proc }
-
- END; { If ProcStack }
-
- END; { VProcPop }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Function VProcPopNext : PProcCall;
-
- [PARAMETERS]
-
- (None)
-
- [RETURNS]
-
- Next procdure pointer
-
- [DESCRIPTION]
-
- Returns next procedure call pointer to use during internal pops (or removes).
- This is in the interface for unit completeness - you should never need to
- use this directly.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Function VProcPopNext : PProcCall;
-
- Var
-
- TempNode : PProcStack;
- PrevNode : PProcStack;
-
- BEGIN
-
- {-----------------------------------}
- { Make sure there is a stack at all }
- {-----------------------------------}
-
- If (ProcStack <> NIL) Then
- BEGIN
-
- {-----------------------------}
- { Search for the End of Stack }
- {-----------------------------}
-
- TempNode := ProcStack;
- PrevNode := NIL;
-
- While (TempNode^.Next <> NIL) Do
-
- BEGIN
-
- PrevNode := TempNode;
- TempNode := TempNode^.Next;
-
- END; { While TempNode^.Next }
-
- VProcPopNext := TempNode^.Proc;
-
- If (PrevNode = NIL) Then
- ProcStack := PrevNode
- Else
- PrevNode^.Next := TempNode^.Next;
-
- Dispose( TempNode );
-
- END { If ProcStack }
-
- Else
- VProcPopNext := NIL;
-
- END; { VProcPopNext }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VProcRemove( Proc : PProcCall );
-
- [PARAMETERS]
-
- Proc Pointer to a procedure-type.
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Removes a valid procedure from the procedure stack. This function will not
- call that procedure - use with disgression.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VProcRemove( Proc : PProcCall );
-
- Var
-
- TempNode : PProcStack;
- PrevNode : PProcStack;
-
- BEGIN
-
- {-----------------------------------}
- { Make sure there is a stack at all }
- {-----------------------------------}
-
- If ( (ProcStack <> NIL) AND (Proc <> NIL) ) Then
- BEGIN
-
- {-------------------------------------}
- { Search for the node containing Proc }
- {-------------------------------------}
-
- TempNode := ProcStack;
- PrevNode := NIL;
-
- While (TempNode^.Next <> NIL) AND
- (TempNode^.Proc <> Proc) Do
-
- BEGIN
-
- PrevNode := TempNode;
- TempNode := TempNode^.Next;
-
- END; { While TempNode^.Next }
-
- {-------------}
- { Found Node? }
- {-------------}
-
- If (TempNode^.Proc = Proc) Then
- BEGIN
-
- If (TempNode = ProcStack) Then
- ProcStack := TempNode^.Next;
-
- PrevNode^.Next := TempNode^.Next;
- Dispose( TempNode );
- TempNode := NIL;
-
- END; { If TempNode^.Proc }
-
- END; { If ProcStack }
-
- END; { VProcRemove }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VProcRemoveAll;
-
- [PARAMETERS]
-
- (None)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Purges the exitproc stack. No calls to the procedures in the stack will be
- made during this procedure.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VProcRemoveAll;
-
- Var
-
- Junk : PProcCall;
-
- BEGIN
-
- Repeat
-
- Junk := VProcPopNext;
-
- Until (Junk = NIL);
-
- { go through and call each critical procedure on the stack }
-
- END; { VProcRemoveAll }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure VProcDoExit;
-
- [PARAMETERS]
-
- (None)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- Call then remove all of the exit procedure on the current stack. The stack
- will be removed during its use.
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure VProcDoExit;
-
- Var
-
- ProcToCall : PProcCall;
-
- BEGIN
-
- Repeat
-
- ProcToCall := VProcPopNext;
-
- If (ProcToCall <> NIL) Then
- TProcCall( ProcToCall );
-
- Until (ProcToCall = NIL);
-
- END; { VProcDoExit }
-
- {────────────────────────────────────────────────────────────────────────────}
-
- (*-
-
- [FUNCTION]
-
- Procedure MyExitProc;
-
- [PARAMETERS]
-
- (None)
-
- [RETURNS]
-
- (None)
-
- [DESCRIPTION]
-
- The procedure begins the execution of the exit procedure stack.
- It also fixes for any other units that might do their own exit stack.
- In addition, if a breakpoint is set on the "ExitProc := SaveExitProc;"
- line, then you can Add a Watch of "SaveMaxAvail - MaxAvail" to see
- if any memory has not been deallocated - a bonus (only within source code).
-
- [SEE-ALSO]
-
- [EXAMPLE]
-
- -*)
-
- Procedure MyExitProc; Far;
-
- BEGIN
-
- VProcDoExit;
-
- {--------------------------------------------------------------------}
- { Set breakpoint on next line in order to find un-deallocated memory }
- { Then make a watch of "SaveMaxAvail - MaxAvail". WOW, magic! }
- {--------------------------------------------------------------------}
-
- ExitProc := SaveExitProc;
-
- END; { MyExitProc }
-
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
- {────────────────────────────────────────────────────────────────────────────}
-
- BEGIN
-
- ProcStack := NIL;
- SaveExitProc := ExitProc;
- ExitProc := @MyExitProc;
- SaveMaxAvail := MaxAvail;
- SaveMemAvail := MemAvail;
-
- END.