os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacExit.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacExit.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,333 @@
     1.4 +/* 
     1.5 + * tclMacExit.c --
     1.6 + *
     1.7 + *	This file contains routines that deal with cleaning up various state
     1.8 + *	when Tcl/Tk applications quit.  Unfortunantly, not all state is cleaned
     1.9 + *	up by the process when an application quites or crashes.  Also you
    1.10 + *	need to do different things depending on wether you are running as
    1.11 + *	68k code, PowerPC, or a code resource.  The Exit handler code was 
    1.12 + *	adapted from code posted on alt.sources.mac by Dave Nebinger.
    1.13 + *
    1.14 + * Copyright (c) 1995 Dave Nebinger.
    1.15 + * Copyright (c) 1995-1996 Sun Microsystems, Inc.
    1.16 + *
    1.17 + * See the file "license.terms" for information on usage and redistribution
    1.18 + * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    1.19 + *
    1.20 + * RCS: @(#) $Id: tclMacExit.c,v 1.4 1999/04/16 00:47:19 stanton Exp $
    1.21 + */
    1.22 +
    1.23 +#include "tclInt.h"
    1.24 +#include "tclMacInt.h"
    1.25 +#include <SegLoad.h>
    1.26 +#include <Traps.h>
    1.27 +#include <Processes.h>
    1.28 +
    1.29 +/*
    1.30 + * Various typedefs and defines needed to patch ExitToShell.
    1.31 + */
    1.32 + 
    1.33 +enum {
    1.34 +        uppExitToShellProcInfo = kPascalStackBased
    1.35 +};
    1.36 +
    1.37 +#if GENERATINGCFM
    1.38 +typedef UniversalProcPtr ExitToShellUPP;
    1.39 +
    1.40 +#define CallExitToShellProc(userRoutine)        \
    1.41 +        CallUniversalProc((UniversalProcPtr)(userRoutine),uppExitToShellProcInfo)
    1.42 +#define NewExitToShellProc(userRoutine) \
    1.43 +        (ExitToShellUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), \
    1.44 +		uppExitToShellProcInfo, GetCurrentArchitecture())
    1.45 +
    1.46 +#else
    1.47 +typedef ExitToShellProcPtr ExitToShellUPP;
    1.48 +
    1.49 +#define CallExitToShellProc(userRoutine)        \
    1.50 +        (*(userRoutine))()
    1.51 +#define NewExitToShellProc(userRoutine) \
    1.52 +        (ExitToShellUPP)(userRoutine)
    1.53 +#endif
    1.54 +
    1.55 +#define DisposeExitToShellProc(userRoutine) \
    1.56 +        DisposeRoutineDescriptor(userRoutine)
    1.57 +
    1.58 +#if defined(powerc)||defined(__powerc)
    1.59 +#pragma options align=mac68k
    1.60 +#endif
    1.61 +struct ExitToShellUPPList{
    1.62 +        struct ExitToShellUPPList* nextProc;
    1.63 +        ExitToShellUPP userProc;
    1.64 +};
    1.65 +#if defined(powerc)||defined(__powerc)
    1.66 +#pragma options align=reset
    1.67 +#endif
    1.68 +
    1.69 +typedef struct ExitToShellDataStruct ExitToShellDataRec,* ExitToShellDataPtr,** ExitToShellDataHdl;
    1.70 +
    1.71 +typedef struct ExitToShellUPPList ExitToShellUPPList,* ExitToShellUPPListPtr,** ExitToShellUPPHdl;
    1.72 +
    1.73 +#if defined(powerc)||defined(__powerc)
    1.74 +#pragma options align=mac68k
    1.75 +#endif
    1.76 +struct ExitToShellDataStruct{
    1.77 +    unsigned long a5;
    1.78 +    ExitToShellUPPList* userProcs;
    1.79 +    ExitToShellUPP oldProc;
    1.80 +};
    1.81 +#if defined(powerc)||defined(__powerc)
    1.82 +#pragma options align=reset
    1.83 +#endif
    1.84 +
    1.85 +/*
    1.86 + * Static globals used within this file.
    1.87 + */
    1.88 +static ExitToShellDataPtr gExitToShellData = (ExitToShellDataPtr) NULL;
    1.89 +
    1.90 +
    1.91 +/*
    1.92 + *----------------------------------------------------------------------
    1.93 + *
    1.94 + * TclPlatformExit --
    1.95 + *
    1.96 + *	This procedure implements the Macintosh specific exit routine.
    1.97 + *	We explicitly callthe ExitHandler function to do various clean
    1.98 + *	up.  
    1.99 + *
   1.100 + * Results:
   1.101 + *	None.
   1.102 + *
   1.103 + * Side effects:
   1.104 + *	We exit the process.
   1.105 + *
   1.106 + *----------------------------------------------------------------------
   1.107 + */
   1.108 +
   1.109 +void
   1.110 +TclpExit(
   1.111 +    int status)		/* Ignored. */
   1.112 +{
   1.113 +    TclMacExitHandler();
   1.114 +
   1.115 +/* 
   1.116 + * If we are using the Metrowerks Standard Library, then we will call its exit so that it
   1.117 + * will get a chance to clean up temp files, and so forth.  It always calls the standard 
   1.118 + * ExitToShell, so the Tcl handlers will also get called.
   1.119 + *   
   1.120 + * If you have another exit, make sure that it does not patch ExitToShell, and does
   1.121 + * call it.  If so, it will probably work as well.
   1.122 + *
   1.123 + */
   1.124 + 
   1.125 +#ifdef __MSL__    
   1.126 +    exit(status);
   1.127 +#else
   1.128 +    ExitToShell();
   1.129 +#endif
   1.130 +
   1.131 +}
   1.132 +
   1.133 +/*
   1.134 + *----------------------------------------------------------------------
   1.135 + *
   1.136 + * TclMacExitHandler --
   1.137 + *
   1.138 + *	This procedure is invoked after Tcl at the last possible moment
   1.139 + *	to clean up any state Tcl has left around that may cause other
   1.140 + *	applications to crash.  For example, this function can be used
   1.141 + *	as the termination routine for CFM applications.
   1.142 + *
   1.143 + * Results:
   1.144 + *	None.
   1.145 + *
   1.146 + * Side effects:
   1.147 + *	Various cleanup occurs.
   1.148 + *
   1.149 + *----------------------------------------------------------------------
   1.150 + */
   1.151 +
   1.152 +void
   1.153 +TclMacExitHandler()
   1.154 +{
   1.155 +    ExitToShellUPPListPtr curProc;
   1.156 +
   1.157 +    /*
   1.158 +     * Loop through all installed Exit handlers
   1.159 +     * and call them.  Always make sure we are in
   1.160 +     * a clean state in case we are recursivly called.
   1.161 +     */
   1.162 +    if ((gExitToShellData) != NULL && (gExitToShellData->userProcs != NULL)){
   1.163 +    
   1.164 +	/*
   1.165 +	 * Call the installed exit to shell routines.
   1.166 +	 */
   1.167 +	curProc = gExitToShellData->userProcs;
   1.168 +	do {
   1.169 +	    gExitToShellData->userProcs = curProc->nextProc;
   1.170 +	    CallExitToShellProc(curProc->userProc);
   1.171 +	    DisposeExitToShellProc(curProc->userProc);
   1.172 +	    DisposePtr((Ptr) curProc);
   1.173 +	    curProc = gExitToShellData->userProcs;
   1.174 +	} while (curProc != (ExitToShellUPPListPtr) NULL);
   1.175 +    }
   1.176 +
   1.177 +    return;
   1.178 +}
   1.179 +
   1.180 +/*
   1.181 + *----------------------------------------------------------------------
   1.182 + *
   1.183 + * TclMacInstallExitToShellPatch --
   1.184 + *
   1.185 + *	This procedure installs a way to clean up state at the latest
   1.186 + *	possible moment before we exit.  These are things that must
   1.187 + *	be cleaned up or the system will crash.  The exact way in which
   1.188 + *	this is implemented depends on the architecture in which we are
   1.189 + *	running.  For 68k applications we patch the ExitToShell call.
   1.190 + *	For PowerPC applications we just create a list of procs to call.
   1.191 + *	The function ExitHandler should be installed in the Code 
   1.192 + *	Fragments terminiation routine.
   1.193 + *
   1.194 + * Results:
   1.195 + *	None.
   1.196 + *
   1.197 + * Side effects:
   1.198 + *	Installs the new routine.
   1.199 + *
   1.200 + *----------------------------------------------------------------------
   1.201 + */
   1.202 +
   1.203 +OSErr 
   1.204 +TclMacInstallExitToShellPatch(
   1.205 +    ExitToShellProcPtr newProc)		/* Function pointer. */
   1.206 +{
   1.207 +    ExitToShellUPP exitHandler;
   1.208 +    ExitToShellUPPListPtr listPtr;
   1.209 +
   1.210 +    if (gExitToShellData == (ExitToShellDataPtr) NULL){
   1.211 +	TclMacInitExitToShell(true);
   1.212 +    }
   1.213 +
   1.214 +    /*
   1.215 +     * Add the passed in function pointer to the list of functions
   1.216 +     * to be called when ExitToShell is called.
   1.217 +     */
   1.218 +    exitHandler = NewExitToShellProc(newProc);
   1.219 +    listPtr = (ExitToShellUPPListPtr) NewPtrClear(sizeof(ExitToShellUPPList));
   1.220 +    listPtr->userProc = exitHandler;
   1.221 +    listPtr->nextProc = gExitToShellData->userProcs;
   1.222 +    gExitToShellData->userProcs = listPtr;
   1.223 +
   1.224 +    return noErr;
   1.225 +}
   1.226 +
   1.227 +/*
   1.228 + *----------------------------------------------------------------------
   1.229 + *
   1.230 + * ExitToShellPatchRoutine --
   1.231 + *
   1.232 + *	This procedure is invoked when someone calls ExitToShell for
   1.233 + *	this application.  This function performs some last miniute
   1.234 + *	clean up and then calls the real ExitToShell routine.
   1.235 + *
   1.236 + * Results:
   1.237 + *	None.
   1.238 + *
   1.239 + * Side effects:
   1.240 + *	Various cleanup occurs.
   1.241 + *
   1.242 + *----------------------------------------------------------------------
   1.243 + */
   1.244 +
   1.245 +static pascal void
   1.246 +ExitToShellPatchRoutine()
   1.247 +{
   1.248 +    ExitToShellUPP oldETS;
   1.249 +    long oldA5;
   1.250 +
   1.251 +    /*
   1.252 +     * Set up our A5 world.  This allows us to have
   1.253 +     * access to our global variables in the 68k world.
   1.254 +     */
   1.255 +    oldA5 = SetCurrentA5();
   1.256 +    SetA5(gExitToShellData->a5);
   1.257 +
   1.258 +    /*
   1.259 +     * Call the function that invokes all
   1.260 +     * of the handlers.
   1.261 +     */
   1.262 +    TclMacExitHandler();
   1.263 +
   1.264 +    /*
   1.265 +     * Call the origional ExitToShell routine.
   1.266 +     */
   1.267 +    oldETS = gExitToShellData->oldProc;
   1.268 +    DisposePtr((Ptr) gExitToShellData);
   1.269 +    SetA5(oldA5);
   1.270 +    CallExitToShellProc(oldETS);
   1.271 +    return;
   1.272 +}
   1.273 +
   1.274 +/*
   1.275 + *----------------------------------------------------------------------
   1.276 + *
   1.277 + * TclMacInitExitToShell --
   1.278 + *
   1.279 + *	This procedure initializes the ExitToShell clean up machanism.
   1.280 + *	Generally, this is handled automatically when users make a call
   1.281 + *	to InstallExitToShellPatch.  However, it can be called 
   1.282 + *	explicitly at startup time to turn off the patching mechanism.
   1.283 + *	This can be used by code resources which could be removed from
   1.284 + *	the application before ExitToShell is called.
   1.285 + *
   1.286 + *	Note, if we are running from CFM code we never install the
   1.287 + *	patch.  Instead, the function ExitHandler should be installed
   1.288 + *	as the terminiation routine for the code fragment.
   1.289 + *
   1.290 + * Results:
   1.291 + *	None.
   1.292 + *
   1.293 + * Side effects:
   1.294 + *	Creates global state.
   1.295 + *
   1.296 + *----------------------------------------------------------------------
   1.297 + */
   1.298 +
   1.299 +void 
   1.300 +TclMacInitExitToShell(
   1.301 +    int usePatch)	/* True if on 68k. */
   1.302 +{
   1.303 +    if (gExitToShellData == (ExitToShellDataPtr) NULL){
   1.304 +#if GENERATINGCFM
   1.305 +	gExitToShellData = (ExitToShellDataPtr)
   1.306 +	  NewPtr(sizeof(ExitToShellDataRec));
   1.307 +	gExitToShellData->a5 = SetCurrentA5();
   1.308 +	gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
   1.309 +#else
   1.310 +	ExitToShellUPP oldExitToShell, newExitToShellPatch;
   1.311 +	short exitToShellTrap;
   1.312 +	
   1.313 +	/*
   1.314 +	 * Initialize patch mechanism.
   1.315 +	 */
   1.316 +	 
   1.317 +	gExitToShellData = (ExitToShellDataPtr) NewPtr(sizeof(ExitToShellDataRec));
   1.318 +	gExitToShellData->a5 = SetCurrentA5();
   1.319 +	gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
   1.320 +
   1.321 +	/*
   1.322 +	 * Save state needed to call origional ExitToShell routine.  Install
   1.323 +	 * the new ExitToShell code in it's place.
   1.324 +	 */
   1.325 +	if (usePatch) {
   1.326 +	    exitToShellTrap = _ExitToShell & 0x3ff;
   1.327 +	    newExitToShellPatch = NewExitToShellProc(ExitToShellPatchRoutine);
   1.328 +	    oldExitToShell = (ExitToShellUPP)
   1.329 +	      NGetTrapAddress(exitToShellTrap, ToolTrap);
   1.330 +	    NSetTrapAddress((UniversalProcPtr) newExitToShellPatch,
   1.331 +		    exitToShellTrap, ToolTrap);
   1.332 +	    gExitToShellData->oldProc = oldExitToShell;
   1.333 +	}
   1.334 +#endif
   1.335 +    }
   1.336 +}