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

// Private function prototypes

static OSErr Find_Symbol(
	Ptr* pSymAddr,
	Str255 pSymName,
	ProcInfoType pProcInfo);

static pascal Boolean HaveCFM(void);

static pascal OSErr GetSystemArchitecture(OSType *archType);

/* This code is directly from Technote 1077 */

/*	changed Library name to be hardcoded at the top of the file
	instead in the middle of the code */

// Private functions

static pascal OSErr GetSystemArchitecture(OSType *archType)
{
	static long sSysArchitecture = 0; // static so we only Gestalt once.
	OSErr tOSErr = noErr;

	*archType = kAnyCFragArch;   // assume wild architecture

	// If we don't know the system architecture yet...
	if (sSysArchitecture == 0)
	// ...Ask Gestalt what kind of machine we are running on.
	tOSErr = Gestalt(gestaltSysArchitecture, &sSysArchitecture);

	if (tOSErr == noErr) // if no errors
	{
		if (sSysArchitecture == gestalt68k)   // 68k?
			*archType = kMotorola68KCFragArch;   
		else if (sSysArchitecture == gestaltPowerPC) // PPC?
			*archType = kPowerPCCFragArch;       
		else
			tOSErr = gestaltUnknownErr;  // who knows what might be next?
	}
	return tOSErr;
}

static pascal Boolean HaveCFM(void)
{
	long response;
	return ( (Gestalt (gestaltCFMAttr, &response) == noErr) &&
				(((response >> gestaltCFMPresent) & 1) != 0));
}

static OSErr Find_Symbol(
	Ptr* pSymAddr,
	Str255 pSymName,
	ProcInfoType pProcInfo)
{
	static CFragConnectionID sCID = 0;
	static OSType sArchType = kAnyCFragArch;
	static OSErr sOSErr = noErr;

	Str255 errMessage;
	Ptr mainAddr;
	CFragSymbolClass symClass;
	ISAType tISAType;

	if (sArchType == kAnyCFragArch)  // if architecture is undefined...
	{
		sCID = 0;     // ...force (re)connect to library
		sOSErr = GetSystemArchitecture(&sArchType); // determine architecture
		if (sOSErr != noErr)
		return sOSErr; // OOPS!
	}
	
	if (!HaveCFM()) {
		// If we don't have CFM68K, return a reasonable-looking error.
		sOSErr = cfragLibConnErr;
		return sOSErr;
	}

	if (sArchType == kMotorola68KCFragArch) // ...for CFM68K
		tISAType = kM68kISA | kCFM68kRTA;
	else if (sArchType == kPowerPCCFragArch)  // ...for PPC CFM
		tISAType = kPowerPCISA | kPowerPCRTA;
	else
		sOSErr = gestaltUnknownErr; // who knows what might be next?

	if (sCID == 0) // If we haven't connected to the library yet...
	{
		// NOTE: The library name is hard coded here.
		// I try to isolate the glue code, one file per library.
		// I have had developers pass in the Library name to allow
		// plug-in type support. Additional code has to be added to
		// each entry points glue routine to support multiple or
		// switching connection IDs.
		sOSErr = GetSharedLibrary(kLibraryName, sArchType, kLoadCFrag,
		&sCID, &mainAddr, errMessage);
		if (sOSErr != noErr)
		return sOSErr; // OOPS!
	}

	// If we haven't looked up this symbol yet...
	if ((Ptr) *pSymAddr == (Ptr) kUnresolvedCFragSymbolAddress)    
	{
		// ...look it up now
		sOSErr = FindSymbol(sCID,pSymName,pSymAddr,&symClass);
		if (sOSErr != noErr) // in case of error...
		// ...clear the procedure pointer
		*(Ptr*) &pSymAddr = (Ptr) kUnresolvedCFragSymbolAddress;
#	if !GENERATINGCFM // if this is classic 68k code...
			*pSymAddr = (Ptr)NewRoutineDescriptorTrap((ProcPtr) *pSymAddr,
			pProcInfo, tISAType);  // ...create a routine descriptor...
#	endif
	}
	return sOSErr;
}

/* --------------------------------- */
/* Autogenerated section starts here */
/* --------------------------------- */
