calling_convention.h

Go to the documentation of this file.
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

Generated on Mon Jan 11 12:03:41 2010 for Werewolf by  doxygen 1.6.1