Chris@16: /*============================================================================= Chris@16: Boost.Wave: A Standard compliant C++ preprocessor library Chris@16: Chris@16: http://www.boost.org/ Chris@16: Chris@16: Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost Chris@16: Software License, Version 1.0. (See accompanying file Chris@16: LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: =============================================================================*/ Chris@16: Chris@16: #if !defined(MACRO_DEFINITION_HPP_D68A639E_2DA5_4E9C_8ACD_CFE6B903831E_INCLUDED) Chris@16: #define MACRO_DEFINITION_HPP_D68A639E_2DA5_4E9C_8ACD_CFE6B903831E_INCLUDED Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: #include Chris@16: #if BOOST_WAVE_SERIALIZATION != 0 Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #include Chris@16: Chris@16: // this must occur after all of the includes and before any code appears Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_PREFIX Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { Chris@16: namespace wave { Chris@16: namespace util { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // macro_definition Chris@16: // Chris@16: // This class containes all infos for a defined macro. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct macro_definition { Chris@16: Chris@16: typedef std::vector parameter_container_type; Chris@16: typedef ContainerT definition_container_type; Chris@16: Chris@16: typedef typename parameter_container_type::const_iterator Chris@16: const_parameter_iterator_t; Chris@16: typedef typename definition_container_type::const_iterator Chris@16: const_definition_iterator_t; Chris@16: Chris@16: macro_definition(TokenT const &token_, bool has_parameters, Chris@16: bool is_predefined_, long uid_) Chris@16: : macroname(token_), uid(uid_), is_functionlike(has_parameters), Chris@16: replaced_parameters(false), is_available_for_replacement(true), Chris@16: is_predefined(is_predefined_) Chris@16: #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 Chris@16: , has_ellipsis(false) Chris@16: #endif Chris@16: , use_count(0) Chris@16: { Chris@16: } Chris@16: // generated copy constructor Chris@16: // generated destructor Chris@16: // generated assignment operator Chris@16: Chris@16: // Replace all occurrences of the parameters throughout the macrodefinition Chris@16: // with special parameter tokens to simplify later macro replacement. Chris@16: // Additionally mark all occurrences of the macro name itself throughout Chris@16: // the macro definition Chris@16: void replace_parameters() Chris@16: { Chris@16: using namespace boost::wave; Chris@16: Chris@16: if (!replaced_parameters) { Chris@16: typename definition_container_type::iterator end = macrodefinition.end(); Chris@16: typename definition_container_type::iterator it = macrodefinition.begin(); Chris@16: Chris@16: for (/**/; it != end; ++it) { Chris@16: token_id id = *it; Chris@16: Chris@16: if (T_IDENTIFIER == id || Chris@16: IS_CATEGORY(id, KeywordTokenType) || Chris@16: IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) || Chris@16: IS_CATEGORY(id, OperatorTokenType)) Chris@16: { Chris@16: // may be a parameter to replace Chris@16: const_parameter_iterator_t cend = macroparameters.end(); Chris@16: const_parameter_iterator_t cit = macroparameters.begin(); Chris@16: for (typename parameter_container_type::size_type i = 0; Chris@16: cit != cend; ++cit, ++i) Chris@16: { Chris@16: if ((*it).get_value() == (*cit).get_value()) { Chris@16: (*it).set_token_id(token_id(T_PARAMETERBASE+i)); Chris@16: break; Chris@16: } Chris@16: #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 Chris@16: else if (T_ELLIPSIS == token_id(*cit) && Chris@16: "__VA_ARGS__" == (*it).get_value()) Chris@16: { Chris@16: // __VA_ARGS__ requires special handling Chris@16: (*it).set_token_id(token_id(T_EXTPARAMETERBASE+i)); Chris@16: break; Chris@16: } Chris@16: #endif Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 Chris@16: // we need to know, if the last of the formal arguments is an ellipsis Chris@16: if (macroparameters.size() > 0 && Chris@16: T_ELLIPSIS == token_id(macroparameters.back())) Chris@16: { Chris@16: has_ellipsis = true; Chris@16: } Chris@16: #endif Chris@16: replaced_parameters = true; // do it only once Chris@16: } Chris@16: } Chris@16: Chris@16: TokenT macroname; // macro name Chris@16: parameter_container_type macroparameters; // formal parameters Chris@16: definition_container_type macrodefinition; // macro definition token sequence Chris@16: long uid; // unique id of this macro Chris@16: bool is_functionlike; Chris@16: bool replaced_parameters; Chris@16: bool is_available_for_replacement; Chris@16: bool is_predefined; Chris@16: #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 Chris@16: bool has_ellipsis; Chris@16: #endif Chris@16: boost::detail::atomic_count use_count; Chris@16: Chris@16: #if BOOST_WAVE_SERIALIZATION != 0 Chris@16: // default constructor is needed for serialization only Chris@16: macro_definition() Chris@16: : uid(0), is_functionlike(false), replaced_parameters(false), Chris@16: is_available_for_replacement(false), is_predefined(false) Chris@16: #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 Chris@16: , has_ellipsis(false) Chris@16: #endif Chris@16: , use_count(0) Chris@16: {} Chris@16: Chris@16: private: Chris@16: friend class boost::serialization::access; Chris@16: template Chris@16: void serialize(Archive &ar, const unsigned int version) Chris@16: { Chris@16: using namespace boost::serialization; Chris@16: ar & make_nvp("name", macroname); Chris@16: ar & make_nvp("parameters", macroparameters); Chris@16: ar & make_nvp("definition", macrodefinition); Chris@16: ar & make_nvp("uid", uid); Chris@16: ar & make_nvp("is_functionlike", is_functionlike); Chris@16: ar & make_nvp("has_replaced_parameters", replaced_parameters); Chris@16: ar & make_nvp("is_available_for_replacement", is_available_for_replacement); Chris@16: ar & make_nvp("is_predefined", is_predefined); Chris@16: #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 Chris@16: ar & make_nvp("has_ellipsis", has_ellipsis); Chris@16: #endif Chris@16: } Chris@16: #endif Chris@16: }; Chris@16: Chris@16: #if BOOST_WAVE_SERIALIZATION == 0 Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: inline void Chris@16: intrusive_ptr_add_ref(macro_definition* p) Chris@16: { Chris@16: ++p->use_count; Chris@16: } Chris@16: Chris@16: template Chris@16: inline void Chris@16: intrusive_ptr_release(macro_definition* p) Chris@16: { Chris@16: if (--p->use_count == 0) Chris@16: delete p; Chris@16: } Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace util Chris@16: } // namespace wave Chris@16: } // namespace boost Chris@16: Chris@16: // the suffix header occurs after all of the code Chris@16: #ifdef BOOST_HAS_ABI_HEADERS Chris@16: #include BOOST_ABI_SUFFIX Chris@16: #endif Chris@16: Chris@16: #endif // !defined(MACRO_DEFINITION_HPP_D68A639E_2DA5_4E9C_8ACD_CFE6B903831E_INCLUDED)