
/*	Copyright  (c)	GŸnter Woigk  1999
  					mailto:kio@little-bat.de

	This file is free software

 	This program is distributed in the hope that it will be useful,
 	but WITHOUT ANY WARRANTY; without even the implied warranty of
 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

 	Permission to use, copy, modify, distribute, and sell this software and
 	its documentation for any purpose is hereby granted without fee, provided
 	that the above copyright notice appear in all copies and that both that
 	copyright notice and this permission notice appear in supporting
 	documentation, and that the name of the copyright holder not be used
 	in advertising or publicity pertaining to distribution of the software
 	without specific, written prior permission.  The copyright holder makes no
 	representations about the suitability of this software for any purpose.
 	It is provided "as is" without express or implied warranty.

 	THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 	INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 	EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 	CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 	DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 	TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 	PERFORMANCE OF THIS SOFTWARE.

 
	atexit() and _atexit()

	this file is ment to increase portability of C/C++ code for the macintosh.

	MetroWerks C/C++ compiler provides only atexit() which shedules a function
	to be executed on normal application termination only; not _atexit() which
	shedules a function to be executed on normal exit and error abort.

	this file implements _atexit() and re-implements atexit(). 
	the latter is neccessary to assure that functions registered by any of
	these routines are called in the correct sequence, that is in exact reverse
	order than they were sheduled.

	17.sep.1999	kio	started work
*/


#if macintosh

#define	SAFE	1
#define	LOG		0

#include	"kio.h"



/* ----	local variables ------------------------------------------------------
*/
static UniversalProcPtr	OldExitToShell;	// MacOS procedure pointer to old ExitToShell()
static void(*proc[32])();				// addresses of registered functions
static uint	procs   = 0;
static long	always  = 0x00000000;		// registered for any exit (else only proper)
static bool	proper = false;				// is it a proper shutdown ?
static int  xxxFlag = 1;


/* ----	detect proper exit ------------------------------------------------
*/
static void isproper ( void )
{
	proper = true;
}


/* ----	Run all registered jobs ----------------------------------------------
*/
static void DoAtExit()
{
	SetCurrentA5(); 					// required for 68k only ?

// call registered procs in reverse order
	while (procs)
	{
		procs--;
		if (proper||(always&1)) { if(XXXLOG) SysBeep(20); proc[procs](); }
		always >>= 1;
	}

// remove patch and exit via old ExitToShell()
	SetToolTrapAddress(OldExitToShell,_ExitToShell);
	ExitToShell();
}


/* ----	Register a job for execution ----------------------------------------
*/
int AT_EXIT ( void(*fu)(void), bool flag )
{
	XXXTRAP(xxxFlag!=1);
	XXLog("AT_EXIT(proc,%s)",flag?"always":"when proper");

	if (procs>=NELEM(proc)) return error;
	
	proc[procs] = fu;
	procs++;
	always += always +flag;

	if (procs==1)
	{
		OldExitToShell = GetToolTrapAddress(_ExitToShell);
		SetToolTrapAddress ( NewRoutineDescriptor((ProcPtr)DoAtExit,kPascalStackBased,GetCurrentISA()), _ExitToShell );

		#undef atexit
		#undef _atexit

		atexit ( isproper );
	}
	
	return ok;
}



#endif	// macintosh

