cpp_macromap.hpp
字号:
/*============================================================================= Boost.Wave: A Standard compliant C++ preprocessor library Macro expansion engine 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(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; // expects a token sequence as its parameters template <typename IteratorT> bool is_defined(IteratorT const &begin, IteratorT const &end) const; // expects an arbitrary string as its parameter bool is_defined(string_type const &str) const;// 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) const; // Remove a macro name from the given macro scope bool remove_macro(string_type const &name, position_type const& pos, bool even_predefined = false); template <typename IteratorT, typename ContainerT> token_type const &expand_tokensequence(IteratorT &first, IteratorT const &last, ContainerT &pending, ContainerT &expanded, bool& seen_newline, 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; }// interface for macro name introspection typedef typename defined_macros_type::name_iterator name_iterator; typedef typename defined_macros_type::const_name_iterator const_name_iterator; name_iterator begin() { return defined_macros_type::make_iterator(current_macros->begin()); } name_iterator end() { return defined_macros_type::make_iterator(current_macros->end()); } const_name_iterator begin() const { return defined_macros_type::make_iterator(current_macros->begin()); } const_name_iterator end() const { return defined_macros_type::make_iterator(current_macros->end()); } 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& seen_newline, bool expand_operator_defined);// Collect all arguments supplied to a macro invocation#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0 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, bool& seen_newline);#else 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 &endparen, IteratorT const &end, SizeT const ¶meter_count, bool& seen_newline);#endif// 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& seen_newline, 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, bool& seen_newline);// Handle the concatenation operator '##' template <typename ContainerT> bool 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 != 0public: 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 { using namespace boost::serialization; ar & make_nvp("defined_macros", defined_macros); } template<typename Archive> void load(Archive &ar, const unsigned int loaded_version) { using namespace boost::serialization; if (version != (loaded_version & ~version_mask)) { BOOST_WAVE_THROW(preprocess_exception, incompatible_config, "cpp_context state version", get_main_pos()); } ar & make_nvp("defined_macros", defined_macros); current_macros = defined_macros.get(); } BOOST_SERIALIZATION_SPLIT_MEMBER()#endifprivate: 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; predefined_macros predef; // predefined macro support};//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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_CTX(ctx, macro_handling_exception, illegal_redefinition, name.get_value().c_str(), main_pos, name.get_value().c_str()); return false; } 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_CTX(ctx, macro_handling_exception, bad_define_statement_va_args, name.get_value().c_str(), main_pos, name.get_value().c_str()); return false; } if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) { // exclude special operator names BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception, illegal_operator_redefinition, name.get_value().c_str(), main_pos, name.get_value().c_str()); return false; } // try to define the new macrodefined_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 macro_definition_type* macrodef = (*it).second.get(); if (macrodef->is_functionlike != has_parameters || !impl::parameters_equal(macrodef->macroparameters, parameters) || !impl::definition_equals(macrodef->macrodefinition, definition)) { BOOST_WAVE_THROW_NAME_CTX(ctx, 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()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -