os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacExit.c
Update contrib.
4 * This file contains routines that deal with cleaning up various state
5 * when Tcl/Tk applications quit. Unfortunantly, not all state is cleaned
6 * up by the process when an application quites or crashes. Also you
7 * need to do different things depending on wether you are running as
8 * 68k code, PowerPC, or a code resource. The Exit handler code was
9 * adapted from code posted on alt.sources.mac by Dave Nebinger.
11 * Copyright (c) 1995 Dave Nebinger.
12 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
14 * See the file "license.terms" for information on usage and redistribution
15 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17 * RCS: @(#) $Id: tclMacExit.c,v 1.4 1999/04/16 00:47:19 stanton Exp $
21 #include "tclMacInt.h"
24 #include <Processes.h>
27 * Various typedefs and defines needed to patch ExitToShell.
31 uppExitToShellProcInfo = kPascalStackBased
35 typedef UniversalProcPtr ExitToShellUPP;
37 #define CallExitToShellProc(userRoutine) \
38 CallUniversalProc((UniversalProcPtr)(userRoutine),uppExitToShellProcInfo)
39 #define NewExitToShellProc(userRoutine) \
40 (ExitToShellUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), \
41 uppExitToShellProcInfo, GetCurrentArchitecture())
44 typedef ExitToShellProcPtr ExitToShellUPP;
46 #define CallExitToShellProc(userRoutine) \
48 #define NewExitToShellProc(userRoutine) \
49 (ExitToShellUPP)(userRoutine)
52 #define DisposeExitToShellProc(userRoutine) \
53 DisposeRoutineDescriptor(userRoutine)
55 #if defined(powerc)||defined(__powerc)
56 #pragma options align=mac68k
58 struct ExitToShellUPPList{
59 struct ExitToShellUPPList* nextProc;
60 ExitToShellUPP userProc;
62 #if defined(powerc)||defined(__powerc)
63 #pragma options align=reset
66 typedef struct ExitToShellDataStruct ExitToShellDataRec,* ExitToShellDataPtr,** ExitToShellDataHdl;
68 typedef struct ExitToShellUPPList ExitToShellUPPList,* ExitToShellUPPListPtr,** ExitToShellUPPHdl;
70 #if defined(powerc)||defined(__powerc)
71 #pragma options align=mac68k
73 struct ExitToShellDataStruct{
75 ExitToShellUPPList* userProcs;
76 ExitToShellUPP oldProc;
78 #if defined(powerc)||defined(__powerc)
79 #pragma options align=reset
83 * Static globals used within this file.
85 static ExitToShellDataPtr gExitToShellData = (ExitToShellDataPtr) NULL;
89 *----------------------------------------------------------------------
93 * This procedure implements the Macintosh specific exit routine.
94 * We explicitly callthe ExitHandler function to do various clean
101 * We exit the process.
103 *----------------------------------------------------------------------
108 int status) /* Ignored. */
113 * If we are using the Metrowerks Standard Library, then we will call its exit so that it
114 * will get a chance to clean up temp files, and so forth. It always calls the standard
115 * ExitToShell, so the Tcl handlers will also get called.
117 * If you have another exit, make sure that it does not patch ExitToShell, and does
118 * call it. If so, it will probably work as well.
131 *----------------------------------------------------------------------
133 * TclMacExitHandler --
135 * This procedure is invoked after Tcl at the last possible moment
136 * to clean up any state Tcl has left around that may cause other
137 * applications to crash. For example, this function can be used
138 * as the termination routine for CFM applications.
144 * Various cleanup occurs.
146 *----------------------------------------------------------------------
152 ExitToShellUPPListPtr curProc;
155 * Loop through all installed Exit handlers
156 * and call them. Always make sure we are in
157 * a clean state in case we are recursivly called.
159 if ((gExitToShellData) != NULL && (gExitToShellData->userProcs != NULL)){
162 * Call the installed exit to shell routines.
164 curProc = gExitToShellData->userProcs;
166 gExitToShellData->userProcs = curProc->nextProc;
167 CallExitToShellProc(curProc->userProc);
168 DisposeExitToShellProc(curProc->userProc);
169 DisposePtr((Ptr) curProc);
170 curProc = gExitToShellData->userProcs;
171 } while (curProc != (ExitToShellUPPListPtr) NULL);
178 *----------------------------------------------------------------------
180 * TclMacInstallExitToShellPatch --
182 * This procedure installs a way to clean up state at the latest
183 * possible moment before we exit. These are things that must
184 * be cleaned up or the system will crash. The exact way in which
185 * this is implemented depends on the architecture in which we are
186 * running. For 68k applications we patch the ExitToShell call.
187 * For PowerPC applications we just create a list of procs to call.
188 * The function ExitHandler should be installed in the Code
189 * Fragments terminiation routine.
195 * Installs the new routine.
197 *----------------------------------------------------------------------
201 TclMacInstallExitToShellPatch(
202 ExitToShellProcPtr newProc) /* Function pointer. */
204 ExitToShellUPP exitHandler;
205 ExitToShellUPPListPtr listPtr;
207 if (gExitToShellData == (ExitToShellDataPtr) NULL){
208 TclMacInitExitToShell(true);
212 * Add the passed in function pointer to the list of functions
213 * to be called when ExitToShell is called.
215 exitHandler = NewExitToShellProc(newProc);
216 listPtr = (ExitToShellUPPListPtr) NewPtrClear(sizeof(ExitToShellUPPList));
217 listPtr->userProc = exitHandler;
218 listPtr->nextProc = gExitToShellData->userProcs;
219 gExitToShellData->userProcs = listPtr;
225 *----------------------------------------------------------------------
227 * ExitToShellPatchRoutine --
229 * This procedure is invoked when someone calls ExitToShell for
230 * this application. This function performs some last miniute
231 * clean up and then calls the real ExitToShell routine.
237 * Various cleanup occurs.
239 *----------------------------------------------------------------------
243 ExitToShellPatchRoutine()
245 ExitToShellUPP oldETS;
249 * Set up our A5 world. This allows us to have
250 * access to our global variables in the 68k world.
252 oldA5 = SetCurrentA5();
253 SetA5(gExitToShellData->a5);
256 * Call the function that invokes all
262 * Call the origional ExitToShell routine.
264 oldETS = gExitToShellData->oldProc;
265 DisposePtr((Ptr) gExitToShellData);
267 CallExitToShellProc(oldETS);
272 *----------------------------------------------------------------------
274 * TclMacInitExitToShell --
276 * This procedure initializes the ExitToShell clean up machanism.
277 * Generally, this is handled automatically when users make a call
278 * to InstallExitToShellPatch. However, it can be called
279 * explicitly at startup time to turn off the patching mechanism.
280 * This can be used by code resources which could be removed from
281 * the application before ExitToShell is called.
283 * Note, if we are running from CFM code we never install the
284 * patch. Instead, the function ExitHandler should be installed
285 * as the terminiation routine for the code fragment.
291 * Creates global state.
293 *----------------------------------------------------------------------
297 TclMacInitExitToShell(
298 int usePatch) /* True if on 68k. */
300 if (gExitToShellData == (ExitToShellDataPtr) NULL){
302 gExitToShellData = (ExitToShellDataPtr)
303 NewPtr(sizeof(ExitToShellDataRec));
304 gExitToShellData->a5 = SetCurrentA5();
305 gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
307 ExitToShellUPP oldExitToShell, newExitToShellPatch;
308 short exitToShellTrap;
311 * Initialize patch mechanism.
314 gExitToShellData = (ExitToShellDataPtr) NewPtr(sizeof(ExitToShellDataRec));
315 gExitToShellData->a5 = SetCurrentA5();
316 gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
319 * Save state needed to call origional ExitToShell routine. Install
320 * the new ExitToShell code in it's place.
323 exitToShellTrap = _ExitToShell & 0x3ff;
324 newExitToShellPatch = NewExitToShellProc(ExitToShellPatchRoutine);
325 oldExitToShell = (ExitToShellUPP)
326 NGetTrapAddress(exitToShellTrap, ToolTrap);
327 NSetTrapAddress((UniversalProcPtr) newExitToShellPatch,
328 exitToShellTrap, ToolTrap);
329 gExitToShellData->oldProc = oldExitToShell;