00001 #if !BOOST_PP_IS_ITERATING
00002 #ifndef CALLING_CONVENTION_H
00003 #define CALLING_CONVENTION_H
00004
00005 #include "traits.h"
00006 #include "angelscript.h"
00007 #include <sstream>
00008 #include <boost/type_traits.hpp>
00009
00010 #include <boost/preprocessor/cat.hpp>
00011 #include <boost/preprocessor/arithmetic/sub.hpp>
00012 #include <boost/preprocessor/comparison/not_equal.hpp>
00013 #include <boost/preprocessor/control/if.hpp>
00014 #include <boost/preprocessor/iteration/iterate.hpp>
00015 #include <boost/preprocessor/repetition/enum_params.hpp>
00016 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
00017 #include <boost/preprocessor/repetition/repeat.hpp>
00018
00019 class Undefined;
00020 void AS_TypeDoesntSeemToBeAFunction(Undefined &);
00021 void AS_AngelScriptDoesntSupportFastCall(Undefined &);
00022
00023 template <typename T>
00024 struct CallingConvention {
00025 CallingConvention() {
00026 AS_TypeDoesntSeemToBeAFunction(T());
00027 }
00028 };
00029
00030 template <typename T>
00031 struct Type2Type {};
00032 template <typename T>
00033 void add_const(std::ostream &, T) {}
00034 template <typename T>
00035 void add_const(std::ostream & sstr, Type2Type<const T *>) {
00036 sstr << " const";
00037 }
00038 template <typename T>
00039 void add_const(std::ostream & sstr, Type2Type<const T &>) {
00040 sstr << " const";
00041 }
00042
00043 #define MAX_ARGS 5
00044 #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, MAX_ARGS, "calling_convention.h"))
00045 #include BOOST_PP_ITERATE()
00046
00047 template <typename Fn>
00048 asDWORD calling_convention(Fn) {
00049 return CallingConvention<Fn>();
00050 }
00051
00052 #endif
00053 #elif BOOST_PP_ITERATION_DEPTH() == 1
00054 #define EMPTY
00055 #define NUM_ARGS BOOST_PP_FRAME_ITERATION(1)
00056
00057 #define AND_ARG(z, n, param) && ASArg<A##n>::value
00058 #define AND_ARG_NOT_FIRST(z, n, param) \
00059 BOOST_PP_IF(BOOST_PP_NOT_EQUAL(0, n), AND_ARG(z, n, param), EMPTY)
00060 #define AND_ARG_NOT_LAST(z, n, param) \
00061 BOOST_PP_IF(BOOST_PP_NOT_EQUAL(BOOST_PP_SUB(NUM_ARGS, 1), n), AND_ARG(z, n, param), EMPTY)
00062
00063 #define INSERT_COMMA << ", "
00064 #define INSERT_COMMA_IF(cond) BOOST_PP_IF(cond, INSERT_COMMA, EMPTY)
00065 #define INSERT_ARG(z, n, param) \
00066 INSERT_COMMA_IF(BOOST_PP_NOT_EQUAL(0, n)) << ASArg<A##n>::arg_type()
00067 #define INSERT_ARG1(z, n, param) \
00068 INSERT_COMMA_IF(BOOST_PP_NOT_EQUAL(1, n)) << ASArg<A##n>::arg_type()
00069 #define INSERT_ARG_NOT_FIRST(z, n, param) \
00070 BOOST_PP_IF(BOOST_PP_NOT_EQUAL(0, n), INSERT_ARG1(z, n, param), EMPTY)
00071 #define INSERT_ARG_NOT_LAST(z, n, param) \
00072 BOOST_PP_IF(BOOST_PP_NOT_EQUAL(BOOST_PP_SUB(NUM_ARGS, 1), n), INSERT_ARG(z, n, param), EMPTY)
00073
00074 #define FIRST_TYPE BOOST_PP_IF(BOOST_PP_NOT_EQUAL(0, NUM_ARGS), A0, void)
00075 #define LAST_TYPE BOOST_PP_IF(BOOST_PP_NOT_EQUAL(0, NUM_ARGS), BOOST_PP_CAT(A, BOOST_PP_SUB(NUM_ARGS, 1)), void)
00076
00077 template <typename R BOOST_PP_ENUM_TRAILING_PARAMS(NUM_ARGS, typename A)>
00078 struct CallingConvention<R (__cdecl *)(BOOST_PP_ENUM_PARAMS(NUM_ARGS, A))>
00079 : boost::integral_constant<asDWORD, asCALL_CDECL> {
00080
00081 typedef FIRST_TYPE FirstType;
00082 static const bool is_valid_firstcall_method
00083 = ASReturn<R>::value
00084 BOOST_PP_REPEAT(NUM_ARGS, AND_ARG_NOT_FIRST, ~)
00085 ;
00086 static std::string firstcall_signature(const std::string & name) {
00087 std::stringstream sstr;
00088 sstr << ASReturn<R>::return_type()
00089 << " " << name << "("
00090 BOOST_PP_REPEAT(NUM_ARGS, INSERT_ARG_NOT_FIRST, ~)
00091 << ")";
00092 add_const(sstr, Type2Type<FirstType>());
00093 return sstr.str();
00094 }
00095
00096 typedef LAST_TYPE LastType;
00097 static const bool is_valid_lastcall_method
00098 = ASReturn<R>::value
00099 BOOST_PP_REPEAT(NUM_ARGS, AND_ARG_NOT_LAST, ~)
00100 ;
00101 static std::string lastcall_signature(const std::string & name) {
00102 std::stringstream sstr;
00103 sstr << ASReturn<R>::return_type()
00104 << " " << name << "("
00105 BOOST_PP_REPEAT(NUM_ARGS, INSERT_ARG_NOT_LAST, ~)
00106 << ")";
00107 add_const(sstr, Type2Type<LastType>());
00108 return sstr.str();
00109 }
00110
00111 static const bool valid_global_function
00112 = ASReturn<R>::value
00113 BOOST_PP_REPEAT(NUM_ARGS, AND_ARG, ~)
00114 ;
00115 static std::string global_function_signature(const std::string & name) {
00116 std::stringstream sstr;
00117 sstr << ASReturn<R>::return_type()
00118 << " " << name << "("
00119 BOOST_PP_REPEAT(NUM_ARGS, INSERT_ARG, ~)
00120 << ")";
00121 return sstr.str();
00122 }
00123 };
00124 template <typename R BOOST_PP_ENUM_TRAILING_PARAMS(NUM_ARGS, typename A)>
00125 struct CallingConvention<R (__stdcall *)(BOOST_PP_ENUM_PARAMS(NUM_ARGS, A))>
00126 : boost::integral_constant<asDWORD, asCALL_STDCALL> {
00127
00128 static const bool valid_global_function
00129 = ASReturn<R>::value
00130 BOOST_PP_REPEAT(NUM_ARGS, AND_ARG, ~)
00131 ;
00132 static std::string global_function_signature(const std::string & name) {
00133 std::stringstream sstr;
00134 sstr << ASReturn<R>::return_type()
00135 << " " << name << "("
00136 BOOST_PP_REPEAT(NUM_ARGS, INSERT_ARG, ~)
00137 << ")";
00138 return sstr.str();
00139 }
00140 };
00141 template <typename T, typename R BOOST_PP_ENUM_TRAILING_PARAMS(NUM_ARGS, typename A)>
00142 struct CallingConvention<R (T::*)(BOOST_PP_ENUM_PARAMS(NUM_ARGS, A))>
00143 : boost::integral_constant<asDWORD, asCALL_THISCALL> {
00144
00145 typedef T ObjectType;
00146
00147 static const bool valid_object_method
00148 = ASReturn<R>::value
00149 BOOST_PP_REPEAT(NUM_ARGS, AND_ARG, ~)
00150 ;
00151 static std::string object_method_signature(const std::string & name) {
00152 std::stringstream sstr;
00153 sstr << ASReturn<R>::return_type()
00154 << " " << name << "("
00155 BOOST_PP_REPEAT(NUM_ARGS, INSERT_ARG, ~)
00156 << ")";
00157 return sstr.str();
00158 }
00159 };
00160 template <typename T, typename R BOOST_PP_ENUM_TRAILING_PARAMS(NUM_ARGS, typename A)>
00161 struct CallingConvention<R (T::*)(BOOST_PP_ENUM_PARAMS(NUM_ARGS, A)) const>
00162 : boost::integral_constant<asDWORD, asCALL_THISCALL> {
00163
00164 typedef T ObjectType;
00165
00166 static const bool valid_object_method
00167 = ASReturn<R>::value
00168 BOOST_PP_REPEAT(NUM_ARGS, AND_ARG, ~)
00169 ;
00170 static std::string object_method_signature(const std::string & name) {
00171 std::stringstream sstr;
00172 sstr << ASReturn<R>::return_type()
00173 << " " << name << "("
00174 BOOST_PP_REPEAT(NUM_ARGS, INSERT_ARG, ~)
00175 << ") const";
00176 return sstr.str();
00177 }
00178 };
00179
00180 template <typename R BOOST_PP_ENUM_TRAILING_PARAMS(NUM_ARGS, typename A)>
00181 struct CallingConvention<R (__fastcall *)(BOOST_PP_ENUM_PARAMS(NUM_ARGS, A))> {
00182 CallingConvention() {
00183 AS_AngelScriptDoesntSupportFastCall( (R (__fastcall *)(BOOST_PP_ENUM_PARAMS(NUM_ARGS, A)))0 );
00184 }
00185 operator asDWORD() const;
00186 };
00187 #endif