home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Carousel Volume 2 #1
/
carousel.iso
/
mactosh
/
lang
/
thinkc30.sit
/
onexit.c
< prev
next >
Wrap
Text File
|
1989-01-25
|
4KB
|
267 lines
/*
* onexit.c - Copyright (C) 1989 by Symantec Corp. All rights reserved.
*
* Shutdown routines installed with "onexit" are called only on NORMAL
* termination, i.e. calling "exit" or returning from "main".
*
* Shutdown routines installed with "_onexit" are called on "ExitToShell"
* as well as on normal termination.
*
* When initiating any other form of termination (e.g. "Launch"), the
* user can call "_exiting" to force shutdown routines to be called.
*
*/
#ifndef _MacTypes_
#include <MacHeaders>
#endif
extern long ATrapHandler : 0x28;
typedef void (*Proc)();
Proc onexit(Proc);
Proc _onexit(Proc);
void _exiting(int);
void exit(int);
void nop(void);
void abort(void);
#define NPROCS 32
static struct proc { Proc proc; int always; } procs[NPROCS];
static int next = 0;
static Proc oldexit, oldES;
static char *ptrES;
static void normal_exit(void), newES(void);
/*
* exit - normal program termination
*
* The exit status is ignored.
*
*/
void
exit(i)
{
asm {
movea.l 0x6C(a5),a0
jsr (a0) ; call onexit vector
_ExitToShell
}
}
/*
* onexit - install user shutdown routine
*
*/
Proc
onexit(proc)
Proc proc;
{
register struct proc *p;
if (next == NPROCS)
return(0);
/* install proc in table */
p = &procs[next++];
p->proc = proc;
/* p->always = 0; */
if (!oldexit) {
proc = normal_exit;
/* install onexit vector */
asm {
move.l 0x6C(a5),oldexit
move.l proc,0x6C(a5)
}
}
return(p->proc);
}
/*
* normal_exit - onexit vector
*
*/
static void
normal_exit()
{
_exiting(1);
}
/*
* _onexit - install a critical shutdown routine
*
* Routines installed with "_onexit" are called even if the program does
* not terminate normally, provided only that "ExitToShell" is called.
*
*/
Proc
_onexit(proc)
Proc proc;
{
register struct proc *p;
if (next == NPROCS)
return(0);
/* install proc in table */
p = &procs[next++];
p->proc = proc;
p->always = 1;
if (!oldES) {
proc = newES;
/* save original ExitToShell */
asm {
move.w #0xA9F4,d0 ; _ExitToShell
_GetTrapAddress
move.l a0,oldES
}
/* (64K ROM only) allocate intercept in sysheap */
asm {
movea.l proc,a0
tst.w ROM85
bpl.s @1
moveq #6,d0
_NewPtr SYS
move.l a0,ptrES
move.w #0x4EF9,(a0) ; JMP abs.L
move.l proc,2(a0)
@1 }
/* install ExitToShell intercept */
asm {
move.w #0xA9F4,d0 ; _ExitToShell
_SetTrapAddress
}
}
return(p->proc);
}
/*
* newES - ExitToShell intercept
*
*/
static void
newES()
{
_exiting(0);
ExitToShell();
}
/*
* _exiting - perform shutdown activity
*
* The argument controls which shutdown routines should be called:
*
* _exiting(1) call all installed shutdown routines
* _exiting(0) call only routines installed with "_onexit"
*
*/
void
_exiting(normally)
{
register struct proc *p;
Proc proc;
int i;
SetUpA5();
p = &procs[NPROCS];
for (i = NPROCS; i--; ) {
if (proc = (--p)->proc) {
p->proc = 0;
if (normally || p->always)
(*proc)();
}
}
/* deallocate ExitToShell intercept */
asm {
move.l ptrES,d0
beq.s @1
movea.l d0,a0
_DisposPtr
clr.l ptrES
@1 }
/* remove ExitToShell intercept */
asm {
move.l oldES,d0
beq.s @2
movea.l d0,a0
move.w #0xA9F4,d0
_SetTrapAddress
clr.l oldES
@2 }
/* call original exit proc */
asm {
movea.l 0x6C(a5),a0
move.l oldexit,d0
beq.s @3
movea.l d0,a0
@3 jsr (a0)
}
oldexit = nop;
RestoreA5();
}
/*
* nop - do nothing
*
*/
static void
nop()
{
}
/*
* abort - abort execution
*
* A debugger trap is issued if it looks like a debugger is installed.
*
*/
void
abort()
{
if (GetTrapAddress(0xA055) == GetTrapAddress(0xA89F)) {
if ((ATrapHandler & Lo3Bytes) < ((long) ROMBase & Lo3Bytes))
Debugger();
}
else {
if (StripAddress(ATrapHandler) < StripAddress(ROMBase))
Debugger();
}
ExitToShell();
}