OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [tcl/] [mac/] [tclMacExit.c] - Blame information for rev 1767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tclMacExit.c --
3
 *
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.
10
 *
11
 * Copyright (c) 1995 Dave Nebinger.
12
 * Copyright (c) 1995-1996 Sun Microsystems, Inc.
13
 *
14
 * See the file "license.terms" for information on usage and redistribution
15
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16
 *
17
 * RCS: @(#) $Id: tclMacExit.c,v 1.1.1.1 2002-01-16 10:25:30 markom Exp $
18
 */
19
 
20
#include "tclInt.h"
21
#include "tclMacInt.h"
22
#include <SegLoad.h>
23
#include <Traps.h>
24
#include <Processes.h>
25
 
26
/*
27
 * Various typedefs and defines needed to patch ExitToShell.
28
 */
29
 
30
enum {
31
        uppExitToShellProcInfo = kPascalStackBased
32
};
33
 
34
#if GENERATINGCFM
35
typedef UniversalProcPtr ExitToShellUPP;
36
 
37
#define CallExitToShellProc(userRoutine)        \
38
        CallUniversalProc((UniversalProcPtr)(userRoutine),uppExitToShellProcInfo)
39
#define NewExitToShellProc(userRoutine) \
40
        (ExitToShellUPP)NewRoutineDescriptor((ProcPtr)(userRoutine), \
41
                uppExitToShellProcInfo, GetCurrentArchitecture())
42
 
43
#else
44
typedef ExitToShellProcPtr ExitToShellUPP;
45
 
46
#define CallExitToShellProc(userRoutine)        \
47
        (*(userRoutine))()
48
#define NewExitToShellProc(userRoutine) \
49
        (ExitToShellUPP)(userRoutine)
50
#endif
51
 
52
#define DisposeExitToShellProc(userRoutine) \
53
        DisposeRoutineDescriptor(userRoutine)
54
 
55
#if defined(powerc)||defined(__powerc)
56
#pragma options align=mac68k
57
#endif
58
struct ExitToShellUPPList{
59
        struct ExitToShellUPPList* nextProc;
60
        ExitToShellUPP userProc;
61
};
62
#if defined(powerc)||defined(__powerc)
63
#pragma options align=reset
64
#endif
65
 
66
typedef struct ExitToShellDataStruct ExitToShellDataRec,* ExitToShellDataPtr,** ExitToShellDataHdl;
67
 
68
typedef struct ExitToShellUPPList ExitToShellUPPList,* ExitToShellUPPListPtr,** ExitToShellUPPHdl;
69
 
70
#if defined(powerc)||defined(__powerc)
71
#pragma options align=mac68k
72
#endif
73
struct ExitToShellDataStruct{
74
    unsigned long a5;
75
    ExitToShellUPPList* userProcs;
76
    ExitToShellUPP oldProc;
77
};
78
#if defined(powerc)||defined(__powerc)
79
#pragma options align=reset
80
#endif
81
 
82
/*
83
 * Static globals used within this file.
84
 */
85
static ExitToShellDataPtr gExitToShellData = (ExitToShellDataPtr) NULL;
86
 
87
 
88
/*
89
 *----------------------------------------------------------------------
90
 *
91
 * TclPlatformExit --
92
 *
93
 *      This procedure implements the Macintosh specific exit routine.
94
 *      We explicitly callthe ExitHandler function to do various clean
95
 *      up.
96
 *
97
 * Results:
98
 *      None.
99
 *
100
 * Side effects:
101
 *      We exit the process.
102
 *
103
 *----------------------------------------------------------------------
104
 */
105
 
106
void
107
TclPlatformExit(
108
    int status)         /* Ignored. */
109
{
110
    TclMacExitHandler();
111
 
112
/*
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.
116
 *
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.
119
 *
120
 */
121
 
122
#ifdef __MSL__    
123
    exit(status);
124
#else
125
    ExitToShell();
126
#endif
127
 
128
}
129
 
130
/*
131
 *----------------------------------------------------------------------
132
 *
133
 * TclMacExitHandler --
134
 *
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.
139
 *
140
 * Results:
141
 *      None.
142
 *
143
 * Side effects:
144
 *      Various cleanup occurs.
145
 *
146
 *----------------------------------------------------------------------
147
 */
148
 
149
void
150
TclMacExitHandler()
151
{
152
    ExitToShellUPPListPtr curProc;
153
 
154
    /*
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.
158
     */
159
    if ((gExitToShellData) != NULL && (gExitToShellData->userProcs != NULL)){
160
 
161
        /*
162
         * Call the installed exit to shell routines.
163
         */
164
        curProc = gExitToShellData->userProcs;
165
        do {
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);
172
    }
173
 
174
    return;
175
}
176
 
177
/*
178
 *----------------------------------------------------------------------
179
 *
180
 * TclMacInstallExitToShellPatch --
181
 *
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.
190
 *
191
 * Results:
192
 *      None.
193
 *
194
 * Side effects:
195
 *      Installs the new routine.
196
 *
197
 *----------------------------------------------------------------------
198
 */
199
 
200
OSErr
201
TclMacInstallExitToShellPatch(
202
    ExitToShellProcPtr newProc)         /* Function pointer. */
203
{
204
    ExitToShellUPP exitHandler;
205
    ExitToShellUPPListPtr listPtr;
206
 
207
    if (gExitToShellData == (ExitToShellDataPtr) NULL){
208
        TclMacInitExitToShell(true);
209
    }
210
 
211
    /*
212
     * Add the passed in function pointer to the list of functions
213
     * to be called when ExitToShell is called.
214
     */
215
    exitHandler = NewExitToShellProc(newProc);
216
    listPtr = (ExitToShellUPPListPtr) NewPtrClear(sizeof(ExitToShellUPPList));
217
    listPtr->userProc = exitHandler;
218
    listPtr->nextProc = gExitToShellData->userProcs;
219
    gExitToShellData->userProcs = listPtr;
220
 
221
    return noErr;
222
}
223
 
224
/*
225
 *----------------------------------------------------------------------
226
 *
227
 * ExitToShellPatchRoutine --
228
 *
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.
232
 *
233
 * Results:
234
 *      None.
235
 *
236
 * Side effects:
237
 *      Various cleanup occurs.
238
 *
239
 *----------------------------------------------------------------------
240
 */
241
 
242
static pascal void
243
ExitToShellPatchRoutine()
244
{
245
    ExitToShellUPP oldETS;
246
    long oldA5;
247
 
248
    /*
249
     * Set up our A5 world.  This allows us to have
250
     * access to our global variables in the 68k world.
251
     */
252
    oldA5 = SetCurrentA5();
253
    SetA5(gExitToShellData->a5);
254
 
255
    /*
256
     * Call the function that invokes all
257
     * of the handlers.
258
     */
259
    TclMacExitHandler();
260
 
261
    /*
262
     * Call the origional ExitToShell routine.
263
     */
264
    oldETS = gExitToShellData->oldProc;
265
    DisposePtr((Ptr) gExitToShellData);
266
    SetA5(oldA5);
267
    CallExitToShellProc(oldETS);
268
    return;
269
}
270
 
271
/*
272
 *----------------------------------------------------------------------
273
 *
274
 * TclMacInitExitToShell --
275
 *
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.
282
 *
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.
286
 *
287
 * Results:
288
 *      None.
289
 *
290
 * Side effects:
291
 *      Creates global state.
292
 *
293
 *----------------------------------------------------------------------
294
 */
295
 
296
void
297
TclMacInitExitToShell(
298
    int usePatch)       /* True if on 68k. */
299
{
300
    if (gExitToShellData == (ExitToShellDataPtr) NULL){
301
#if GENERATINGCFM
302
        gExitToShellData = (ExitToShellDataPtr)
303
          NewPtr(sizeof(ExitToShellDataRec));
304
        gExitToShellData->a5 = SetCurrentA5();
305
        gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
306
#else
307
        ExitToShellUPP oldExitToShell, newExitToShellPatch;
308
        short exitToShellTrap;
309
 
310
        /*
311
         * Initialize patch mechanism.
312
         */
313
 
314
        gExitToShellData = (ExitToShellDataPtr) NewPtr(sizeof(ExitToShellDataRec));
315
        gExitToShellData->a5 = SetCurrentA5();
316
        gExitToShellData->userProcs = (ExitToShellUPPList*) NULL;
317
 
318
        /*
319
         * Save state needed to call origional ExitToShell routine.  Install
320
         * the new ExitToShell code in it's place.
321
         */
322
        if (usePatch) {
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;
330
        }
331
#endif
332
    }
333
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.