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