text: /*=============================================================================
      Boost.Wave: A Standard compliant C++ preprocessor library
  
      http://www.boost.org/
  
      Copyright (c) 2001-2008 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)
  