#ifndef FUNPTR_H
#define FUNPTR_H

/*** <Pointer to function> Types: ***/
/**
   (see the NOTES file about the FUNPTR() macro)

   included is a parameter (which will generally be an integer or pointer
   to a larger structure), that shall be the function's first parameter
   (even if not important).
   
**/

#define NAMEDFUNPTR(TypeName,RetType,ParamType,ParamList) \
   struct TypeName { \
     RetType (*fun) ParamList ; \
     ParamType param ; \
   }

#define FUNPTR(RetType,ParamType,ParamList) \
   struct { \
     RetType (*fun) ParamList ; \
     ParamType param ; \
   }

#define TYPEDEF_FUNPTR(TypeName,RetType,ParamType,ParamList) \
   typedef NAMEDFUNPTR(TypeName,RetType,ParamType,ParamList) TypeName

#define CALLFUN(FUN,ParamList)  ( (FUN).fun ParamList )

/************ Functions with up to 5 explicit parameters ************/

/*** Absolute function ***/
#define NamedFunPtr_(TypeName,RetType)		NAMEDFUNPTR(TypeName, \
							RetType,void*,(void))
#define TypeDefFunPtr_(TypeName,RetType)	TYPEDEF_FUNPTR(TypeName, \
							RetType,void*,(void))
#define FunPtr_(RetType)			FUNPTR(RetType,void*,(void))
#define Call_(FUN)				( (FUN).fun () )

/*** Implicit parameter only ***/
#define NamedFunPtr0(TypeName,RetType,ParamType) \
	NAMEDFUNPTR(TypeName, RetType,ParamType, (ParamType))
#define TypeDefFunPtr0(TypeName,RetType,ParamType) \
	TYPEDEF_FUNPTR(TypeName, RetType,ParamType, (ParamType))
#define FunPtr0(RetType,ParamType) \
	FUNPTR(RetType, ParamType, (ParamType))
#define Call0(FUN)		( (FUN).fun ((FUN).param) )

/*** one explicit parameter ***/
#define NamedFunPtr1(TypeName,RetType,ParamType,A) \
	NAMEDFUNPTR(TypeName, RetType,ParamType, (ParamType,A))
#define TypeDefFunPtr1(TypeName,RetType,ParamType,A) \
	TYPEDEF_FUNPTR(TypeName, RetType,ParamType, (ParamType,A))
#define FunPtr1(RetType,ParamType,A) \
	FUNPTR(RetType, ParamType, (ParamType,A))
#define Call1(FUN,a)		( (FUN).fun ((FUN).param,a) )

/*** Two explicit parameters ***/
#define NamedFunPtr2(TypeName,RetType,ParamType,A,B) \
	NAMEDFUNPTR(TypeName, RetType,ParamType, (ParamType,A,B))
#define TypeDefFunPtr2(TypeName,RetType,ParamType,A,B) \
	TYPEDEF_FUNPTR(TypeName, RetType,ParamType, (ParamType,A,B))
#define FunPtr2(RetType,ParamType,A,B) \
	FUNPTR(RetType, ParamType, (ParamType,A,B))
#define Call2(FUN,a,b)		( (FUN).fun ((FUN).param,a,b) )

/*** Three explicit parameters ***/
#define NamedFunPtr3(TypeName,RetType,ParamType,A,B,C) \
	NAMEDFUNPTR(TypeName, RetType,ParamType, (ParamType,A,B,C))
#define TypeDefFunPtr3(TypeName,RetType,ParamType,A,B,C) \
	TYPEDEF_FUNPTR(TypeName, RetType,ParamType, (ParamType,A,B,C))
#define FunPtr3(RetType,ParamType,A,B,C) \
	FUNPTR(RetType, ParamType, (ParamType,A,B,C)) 
#define Call3(FUN,a,b,c)		( (FUN).fun ((FUN).param,a,b,c) )

/*** Four explicit parameters ***/
#define NamedFunPtr4(TypeName,RetType,ParamType,A,B,C,D) \
	NAMEDFUNPTR(TypeName, RetType,ParamType, (ParamType,A,B,C,D))
#define TypeDefFunPtr4(TypeName,RetType,ParamType,A,B,C,D) \
	TYPEDEF_FUNPTR(TypeName, RetType,ParamType, (ParamType,A,B,C,D))
#define FunPtr4(RetType,ParamType,A,B,C,D) \
	FUNPTR(RetType, ParamType, (ParamType,A,B,C,D))
#define Call4(FUN,a,b,c,d)		( (FUN).fun ((FUN).param,a,b,c,d) )

/*** Five explicit parameters ***/
#define NamedFunPtr5(TypeName,RetType,ParamType,A,B,C,D,E) \
	NAMEDFUNPTR(TypeName, RetType,ParamType, (ParamType,A,B,C,D,E))
#define TypeDefFunPtr5(TypeName,RetType,ParamType,A,B,C,D,E) \
	TYPEDEF_FUNPTR(TypeName, RetType,ParamType, (ParamType,A,B,C,D,E))
#define FunPtr5(RetType,ParamType,A,B,C,D,E) \
	FUNPTR(RetType, ParamType, (ParamType,A,B,C,D,E))
#define Call5(FUN,a,b,c,d,e)		( (FUN).fun ((FUN).param,a,b,c,d,e) )

#endif /* funptr.h */
