cpp_macromap.hpp
来自「support vector clustering for vc++」· HPP 代码 · 共 683 行 · 第 1/2 页
HPP
683 行
/*=============================================================================
Boost.Wave: A Standard compliant C++ preprocessor library
Macro expansion engine
http://www.boost.org/
Copyright (c) 2001-2007 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(CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)
#define CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <list>
#include <map>
#include <set>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/assert.hpp>
#include <boost/wave/wave_config.hpp>
#if BOOST_WAVE_SERIALIZATION != 0
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/shared_ptr.hpp>
#endif
#include <boost/filesystem/path.hpp>
#include <boost/wave/util/time_conversion_helper.hpp>
#include <boost/wave/util/unput_queue_iterator.hpp>
#include <boost/wave/util/macro_helpers.hpp>
#include <boost/wave/util/macro_definition.hpp>
#include <boost/wave/util/symbol_table.hpp>
#include <boost/wave/util/cpp_macromap_utils.hpp>
#include <boost/wave/util/cpp_macromap_predef.hpp>
#include <boost/wave/grammars/cpp_defined_grammar_gen.hpp>
#include <boost/wave/wave_version.hpp>
#include <boost/wave/cpp_exceptions.hpp>
#include <boost/wave/language_support.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 {
///////////////////////////////////////////////////////////////////////////////
//
// macromap
//
// This class holds all currently defined macros and on demand expands
// those macro definitions
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
class macromap {
typedef macromap<ContextT> self_type;
typedef typename ContextT::token_type token_type;
typedef typename token_type::string_type string_type;
typedef typename token_type::position_type position_type;
typedef typename ContextT::token_sequence_type definition_container_type;
typedef std::vector<token_type> parameter_container_type;
typedef macro_definition<token_type, definition_container_type>
macro_definition_type;
typedef symbol_table<string_type, macro_definition_type>
defined_macros_type;
typedef typename defined_macros_type::value_type::second_type
macro_ref_type;
public:
macromap(ContextT &ctx_)
: current_macros(0), defined_macros(new defined_macros_type(1)),
main_pos("", 0), ctx(ctx_), macro_uid(1)
{
current_macros = defined_macros.get();
}
~macromap() {}
// Add a new macro to the given macro scope
bool add_macro(token_type const &name, bool has_parameters,
parameter_container_type ¶meters,
definition_container_type &definition, bool is_predefined = false,
defined_macros_type *scope = 0);
// Tests, whether the given macro name is defined in the given macro scope
bool is_defined(string_type const &name,
typename defined_macros_type::iterator &it,
defined_macros_type *scope = 0) const;
template <typename IteratorT>
bool is_defined(IteratorT const &begin, IteratorT const &end);
// Get the macro definition for the given macro scope
bool get_macro(string_type const &name, bool &has_parameters,
bool &is_predefined, position_type &pos, parameter_container_type ¶meters,
definition_container_type &definition, defined_macros_type *scope = 0);
// Remove a macro name from the given macro scope
bool remove_macro(token_type const &token, bool even_predefined = false);
template <typename IteratorT, typename ContainerT>
token_type const &expand_tokensequence(IteratorT &first,
IteratorT const &last, ContainerT &pending, ContainerT &expanded,
bool expand_operator_defined);
// Expand all macros inside the given token sequence
template <typename IteratorT, typename ContainerT>
void expand_whole_tokensequence(ContainerT &expanded,
IteratorT &first, IteratorT const &last,
bool expand_operator_defined);
// Init the predefined macros (add them to the given scope)
void init_predefined_macros(char const *fname = "<Unknown>",
defined_macros_type *scope = 0, bool at_global_scope = true);
void predefine_macro(defined_macros_type *scope, string_type const &name,
token_type const &t);
// Init the internal macro symbol namespace
void reset_macromap();
position_type &get_main_pos() { return main_pos; }
protected:
// Helper functions for expanding all macros in token sequences
template <typename IteratorT, typename ContainerT>
token_type const &expand_tokensequence_worker(ContainerT &pending,
unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
bool expand_operator_defined);
// Collect all arguments supplied to a macro invocation
template <typename IteratorT, typename ContainerT, typename SizeT>
typename std::vector<ContainerT>::size_type collect_arguments (
token_type const curr_token, std::vector<ContainerT> &arguments,
IteratorT &next, IteratorT const &end, SizeT const ¶meter_count);
// Expand a single macro name
template <typename IteratorT, typename ContainerT>
bool expand_macro(ContainerT &pending, token_type const &name,
typename defined_macros_type::iterator it,
IteratorT &first, IteratorT const &last, bool expand_operator_defined,
defined_macros_type *scope = 0, ContainerT *queue_symbol = 0);
// Expand a predefined macro (__LINE__, __FILE__ and __INCLUDE_LEVEL__)
template <typename ContainerT>
bool expand_predefined_macro(token_type const &curr_token,
ContainerT &expanded);
// Expand a single macro argument
template <typename ContainerT>
void expand_argument (typename std::vector<ContainerT>::size_type arg,
std::vector<ContainerT> &arguments,
std::vector<ContainerT> &expanded_args, bool expand_operator_defined,
std::vector<bool> &has_expanded_args);
// Expand the replacement list (replaces parameters with arguments)
template <typename ContainerT>
void expand_replacement_list(
macro_definition_type const ¯odefinition,
std::vector<ContainerT> &arguments,
bool expand_operator_defined, ContainerT &expanded);
// Rescans the replacement list for macro expansion
template <typename IteratorT, typename ContainerT>
void rescan_replacement_list(token_type const &curr_token,
macro_definition_type ¯odef, ContainerT &replacement_list,
ContainerT &expanded, bool expand_operator_defined,
IteratorT &nfirst, IteratorT const &nlast);
// Resolves the operator defined() and replces the token with "0" or "1"
template <typename IteratorT, typename ContainerT>
token_type const &resolve_defined(IteratorT &first, IteratorT const &last,
ContainerT &expanded);
// Resolve operator _Pragma or the #pragma directive
template <typename IteratorT, typename ContainerT>
bool resolve_operator_pragma(IteratorT &first,
IteratorT const &last, ContainerT &expanded);
// Handle the concatenation operator '##'
template <typename ContainerT>
void concat_tokensequence(ContainerT &expanded);
template <typename ContainerT>
bool is_valid_concat(string_type new_value,
position_type const &pos, ContainerT &rescanned);
#if BOOST_WAVE_SERIALIZATION != 0
public:
BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
private:
friend class boost::serialization::access;
template<typename Archive>
void save(Archive &ar, const unsigned int version) const
{
ar & defined_macros;
}
template<typename Archive>
void load(Archive &ar, const unsigned int loaded_version)
{
if (version != (loaded_version & ~version_mask)) {
BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
"cpp_context state version", get_main_pos());
}
ar & defined_macros;
current_macros = defined_macros.get();
}
BOOST_SERIALIZATION_SPLIT_MEMBER()
#endif
private:
defined_macros_type *current_macros; // current symbol table
boost::shared_ptr<defined_macros_type> defined_macros; // global symbol table
token_type act_token; // current token
position_type main_pos; // last token position in the pp_iterator
string_type base_name; // the name to be expanded by __BASE_FILE__
ContextT &ctx; // context object associated with the macromap
long macro_uid;
};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// add_macro(): adds a new macro to the macromap
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
parameter_container_type ¶meters, definition_container_type &definition,
bool is_predefined, defined_macros_type *scope)
{
if (!is_predefined && impl::is_special_macroname (name.get_value())) {
// exclude special macro names
BOOST_WAVE_THROW_NAME(macro_handling_exception, illegal_redefinition,
name.get_value().c_str(), main_pos, name.get_value().c_str());
}
if (boost::wave::need_variadics(ctx.get_language()) &&
"__VA_ARGS__" == name.get_value())
{
// can't use __VA_ARGS__ as a macro name
BOOST_WAVE_THROW_NAME(macro_handling_exception, bad_define_statement_va_args,
name.get_value().c_str(), main_pos, name.get_value().c_str());
}
if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
// exclude special operator names
BOOST_WAVE_THROW_NAME(macro_handling_exception,
illegal_operator_redefinition, name.get_value().c_str(), main_pos,
name.get_value().c_str());
}
// try to define the new macro
defined_macros_type *current_scope = scope ? scope : current_macros;
typename defined_macros_type::iterator it = current_scope->find(name.get_value());
if (it != current_scope->end()) {
// redefinition, should not be different
if ((*it).second->is_functionlike != has_parameters ||
!impl::parameters_equal((*it).second->macroparameters, parameters) ||
!impl::definition_equals((*it).second->macrodefinition, definition))
{
BOOST_WAVE_THROW_NAME(macro_handling_exception, macro_redefinition,
name.get_value().c_str(), main_pos, name.get_value().c_str());
}
return false;
}
// test the validity of the parameter names
if (has_parameters) {
std::set<typename token_type::string_type> names;
typedef typename parameter_container_type::iterator
parameter_iterator_type;
typedef typename std::set<typename token_type::string_type>::iterator
name_iterator_type;
parameter_iterator_type end = parameters.end();
for (parameter_iterator_type itp = parameters.begin(); itp != end; ++itp)
{
name_iterator_type pit = names.find((*itp).get_value());
if (pit != names.end()) {
// duplicate parameter name
BOOST_WAVE_THROW_NAME(macro_handling_exception,
duplicate_parameter_name, (*pit).c_str(), main_pos,
name.get_value().c_str());
}
names.insert((*itp).get_value());
}
}
// insert a new macro node
std::pair<typename defined_macros_type::iterator, bool> p =
current_scope->insert(
typename defined_macros_type::value_type(
name.get_value(),
macro_ref_type(new macro_definition_type(name,
has_parameters, is_predefined, ++macro_uid)
)
)
);
if (!p.second) {
BOOST_WAVE_THROW_NAME(macro_handling_exception, macro_insertion_error,
name.get_value().c_str(), main_pos, name.get_value().c_str());
}
// add the parameters and the definition
std::swap((*p.first).second->macroparameters, parameters);
std::swap((*p.first).second->macrodefinition, definition);
// call the context supplied preprocessing hook
ctx.get_hooks().defined_macro(name, has_parameters,
(*p.first).second->macroparameters,
(*p.first).second->macrodefinition, is_predefined);
return true;
}
///////////////////////////////////////////////////////////////////////////////
//
// is_defined(): returns, whether a given macro is already defined
//
///////////////////////////////////////////////////////////////////////////////
template <typename ContextT>
inline bool
macromap<ContextT>::is_defined(typename token_type::string_type const &name,
typename defined_macros_type::iterator &it,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?