/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.

** 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.  See the
** GNU General Public License for more details.

** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- December 1997
 */

/*
 * dll_loader.h --- code to load dynamic code
 */

#ifndef DLLLOADER_H
#define DLLLOADER_H

#ifdef TARGET_OS_MAC
#	include <CodeFragments.h>
	typedef CFragConnectionID CompatConnectID;
#elif defined(WIN32)
	typedef HINSTANCE CompatConnectID;
#else /* !TARGET_OS_MAC && !WIN32 */
#	include <dlfcn.h>
	typedef void *CompatConnectID;
#endif /* !TARGET_OS_MAC && !WIN32 */

#ifdef __cplusplus
extern "C" {
#endif

int CompatLoadLibrary(CompatConnectID * connID, const char *name_dll);
	// return false if failed
	// mac : name_dll is the fragment name of the shared library
	// others : name_dll is the filename of the library

int CompatCloseLibrary(CompatConnectID * connID);
	// unload the shared library, connID should not
	// be used anymore after this call

// CompatCallLibrary(CompatConnectID ID, <atype> result, macFuncDescInfo idf,
//     const char *nf, <atype> tf, <arguments...>
//
// Call a function named "nf", prototype "tf", macDescInfo idf (0 if not mac)
// with the arguments "a1", "a2"... and put the result in "res"

#if defined(TARGET_OS_MAC) && !TARGET_API_MAC_CARBON
	extern UniversalProcPtr sCompatProc;
#	define CompatCallLibrary1(ID, res, idf, nf, tf, a1) \
		( \
			sCompatProc = _CompatCallLibrary(ID, idf, nf), \
			res = sCompatProc != NULL ? \
				CallUniversalProc(sCompatProc, idf, a1) : res, \
			sCompatProc != NULL ? (DisposeRoutineDescriptor(sCompatProc), true) : false \
		)
#	define CompatCallLibrary2(ID, res, idf, nf, tf, a1, a2) \
		( \
			sCompatProc = _CompatCallLibrary(ID, idf, nf), \
			res = sCompatProc != NULL ? \
				CallUniversalProc(sCompatProc, idf, a1, a2) : res, \
			sCompatProc != NULL ? (DisposeRoutineDescriptor(sCompatProc), true) : false \
		)
#	define CompatCallLibrary3(ID, res, idf, nf, tf, a1, a2, a3) \
		( \
			sCompatProc = _CompatCallLibrary(ID, idf, nf), \
			res = sCompatProc != NULL ? \
				CallUniversalProc(sCompatProc, idf, a1, a2, a3) : res, \
			sCompatProc != NULL ? (DisposeRoutineDescriptor(sCompatProc), true) : false \
		)
	UniversalProcPtr _CompatCallLibrary(CompatConnectID connID, long id_func, const char *name_func);
#else /* !TARGET_OS_MAC || TARGET_API_MAC_CARBON */
	extern void *sCompatProc;
#	define CompatCallLibrary1(ID, res, idf, nf, tf, a1) \
		( \
			sCompatProc = _CompatCallLibrary(ID, nf), \
			res = sCompatProc != NULL ? \
				((tf)sCompatProc)(a1) : res, \
			sCompatProc != NULL \
		)
#	define CompatCallLibrary2(ID, res, idf, nf, tf, a1, a2) \
		( \
			sCompatProc = _CompatCallLibrary(ID, nf), \
			res = sCompatProc != NULL ? \
				((tf)sCompatProc)(a1, a2) : res, \
			sCompatProc != NULL \
		)
#	define CompatCallLibrary3(ID, res, idf, nf, tf, a1, a2, a3) \
		( \
			sCompatProc = _CompatCallLibrary(ID, nf), \
			res = sCompatProc != NULL ? \
				((tf)sCompatProc)(a1, a2, a3) : res, \
			sCompatProc != NULL \
		)
	void *_CompatCallLibrary(CompatConnectID connID, const char *name_func);
#endif /* !TARGET_OS_MAC || TARGET_API_MAC_CARBON */

// used with CompatCallLibrary when you want to give a function
// as an argument : for mac funcInfo is the desc. of the function
// arguments, if not 0

#if defined(TARGET_OS_MAC) && !TARGET_API_MAC_CARBON
#	define CompatFuncArg(funcInfo, func) \
		NewRoutineDescriptor((ProcPtr)func, funcInfo, kPowerPCISA)
#else /* !TARGET_OS_MAC || TARGET_API_MAC_CARBON */
#	define CompatFuncArg(funcInfo, func) func
#endif /* TARGET_OS_MAC || TARGET_API_MAC_CARBON */

#ifdef __cplusplus
}
#endif

#endif /* DLLLOADER_H */
