
/*
 *	Startup.c		-	Default init/startup/termination routines for Metrowerks C++ (PowerPC)
 *
 *	Copyright © 1993-1995 metrowerks inc. All Rights Reserved.
 *
 *
 *	THEORY OF OPERATION
 *
 *	This version of the PPC startup code is intended to be used for stand-alone
 *	applications, shared libraries, and dropins that consist of a single fragment,
 *	with well-defined entry and exit points. It is not to be used for multi-fragment
 *	programs which may throw exceptions across fragment boundaries.
 *
 *	The startup file defines 3 entry-points:
 *
 *		__start			This should be the Main Entry-Point for an Application.
 *						It is not used for Shared Libraries or DropIns.
 *						__start() sets up the exception-handling info, calls all
 *						static initializers, calls main(), and calls exit()
 *						to terminate the program. (Monolithic applications need
 *						not un-register the exception-handling info)
 *
 *		__initialize	This should be the Initialization Entry-Point for a
 *						Shared Library or DropIn. It must not be used for Applications.
 *						__initialize() registers the exception-handling info for
 *						the shared library or dropin, and calls all static initializers.
 *
 *		__terminate		This should be the Termination Entry-Point for a
 *						Shared Library or DropIn. It must not be used for Applications.
 *						__terminate() calls all destructors for static/global objects,
 *						then unregisters the exception-handling info for the
 *						shared library or dropin before the fragment is unloaded.
 *
 *	The new zero-runtime-overhead exception-handling mechanism requires that we
 *	keep track of all loaded fragments and their code/data section ranges--we
 *	cannot use the OS data structures to do this--so we must call routines which
 *	register and unregister the exception-handling info as a fragment is loaded/unloaded.
 *
 */

#include <CodeFragments.h>
#include <MacTypes.h>
#include <Errors.h>

#include <stdlib.h>
#include <NMWException.h>

#include <SIOUX.h>




#define IsFileLocation(where) 	\
	( ((where) == kDataForkCFragLocator)	||  \
	((where) == kResourceCFragLocator)	)


/*
 * MODIFIED: 
 *
 *  New void for loading glut resources.
 *  __glutLoadResources()
 */
static OSErr __glutLoadResources(const CFragInitBlock *theInitBlock)
{
	OSErr				err = noErr;
	short  gmyRefNum;
		
		

	
	
	// Find out where we're at!
	if (IsFileLocation(theInitBlock->fragLocator.where))
	{
		FSSpec resSpec;
		
		resSpec =*theInitBlock->fragLocator.u.onDisk.fileSpec; // This is where we are!!!
		gmyRefNum = FSpOpenResFile(&resSpec, fsRdWrShPerm);
	}

	if (gmyRefNum == -1)
	{
		short resNum;
		
		DebugStr("\pCould not open the glutShdLib resource!");
		return (fnfErr);
	}
	else
	{
		return (noErr);
	}
}


	/*	external data	*/

extern char __code_start__[];				/*	(defined by linker)	*/
extern char	__code_end__[];					/*	(defined by linker)	*/
extern char __data_start__[];				/*	(defined by linker)	*/
extern char __data_end__[];					/*	(defined by linker)	*/
extern char __exception_table_start__[];	/*	(defined by linker)	*/
extern char __exception_table_end__[];		/*	(defined by linker)	*/


	/*	private data	*/

static int fragmentID;						/*	ID given to fragment by exception-handling	*/


	/*	prototypes	*/

#ifdef __cplusplus
extern "C" {
#endif

int main(int argc, char **argv);
void __sinit(void);	/*	(generated by linker)	*/
pascal OSErr __initialize(const CFragInitBlock *theInitBlock);
pascal void __terminate(void);
pascal void __start(void);

#ifdef __cplusplus
}
#endif


/*
 *	clear_stackframe_backlink	-	set 0(SP) to 0
 *
 */

static asm void clear_stackframe_backlink(void)
{
		li		r3,0
		stw		r3,0(SP)
		blr
}


/*
 *	__RTOC	-	return the TOC pointer for our code fragment
 *
 */

static asm char *__RTOC(void)
{
		mr		r3,RTOC
		blr
}


/*
 *	__start	-	Default startup routine for Metrowerks C++ (PowerPC)
 *
 *	This routine should be specified as the PEF main routine in the container
 *	for any monolithic application. The program startup/termination sequence is:
 *
 *	1.	Register the exception-handling info for the application
 *	2.	Call all static initializers
 *	3.	Set up default values for 'argc' and 'argv' and call main()
 *	4.	Call exit() to perform required cleanup and termination, including
 *		destroying all static objects, closing open files, closing console window, etc.
 *
 *	We defer all details of proper program termination to the ANSI exit() routine.
 *
 */

pascal void __start(void)
{
	char *argv = 0;

	//	set the stack frame back-link to 0 to improve debugger stack display
	clear_stackframe_backlink();

	//	register this code fragment with the Exception Handling mechanism
	fragmentID = __register_fragment(__code_start__, __code_end__,
									__data_start__, __data_end__,
									__exception_table_start__, __exception_table_end__,
									__RTOC());
	
	//	call all static initializers
	__sinit();
	
	//	call main(argc, argv)
	main(0, &argv);
	
	//	call exit() to terminate the program properly--will not return
	exit(0);
	
	//	unregister this code fragment with the Exception Handling mechanism
//	__unregister_fragment(fragmentID);
}


/*
 *	__initialize	-	Default initialization routine for Metrowerks C++ (PowerPC)
 *
 *	This routine should be specified as the PEF initialization routine in the container
 *	for any monolithic shared-library or drop-in.
 *
 *	1.	Register the exception-handling info for the shared library or dropin
 *	2.	Call all static initializers
 *
 */

pascal OSErr __initialize(const CFragInitBlock *theInitBlock)
{
	//	register this code fragment with the Exception Handling mechanism
	fragmentID = __register_fragment(__code_start__, __code_end__,
									__data_start__, __data_end__,
									__exception_table_start__, __exception_table_end__,
									__RTOC());
	//******************
	// MODIFIED CODE!! *
	//******************								
	if (__glutLoadResources(theInitBlock) == fnfErr)
	{
	  return (fnfErr);
	}
	
	//	call all static initializers
	__sinit();
	
	
	//	return success to Code Fragment Manager
	return(noErr);
}


/*
 *	__terminate	-	Default termination routine for Metrowerks C++ (PowerPC)
 *
 *	This routine should be specified as the PEF termination routine in the container
 *	for any monolithic shared-library or drop-in.
 *
 *	1.	Destroy all static objects
 *	2.	Un-register the exception-handling info for the shared library or dropin
 *
 */

pascal void __terminate(void)
{
	//	destroy all static objects
	__destroy_global_chain();
	
	//	unregister this code fragment with the Exception Handling mechanism
	__unregister_fragment(fragmentID);
}

