cpp_macromap.hpp
字号:
// duplicate parameter name BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception, duplicate_parameter_name, (*pit).c_str(), main_pos, name.get_value().c_str()); return false; } 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_CTX(ctx, macro_handling_exception, macro_insertion_error, name.get_value().c_str(), main_pos, name.get_value().c_str()); return false; }// 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#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0 ctx.get_hooks().defined_macro(name, has_parameters, (*p.first).second->macroparameters, (*p.first).second->macrodefinition, is_predefined);#else ctx.get_hooks().defined_macro(ctx.derived(), name, has_parameters, (*p.first).second->macroparameters, (*p.first).second->macrodefinition, is_predefined);#endif 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, defined_macros_type *scope) const{ if (0 == scope) scope = current_macros; if ((it = scope->find(name)) != scope->end()) return true; // found in symbol table// quick pre-check if (name.size() < 8 || '_' != name[0] || '_' != name[1]) return false; // quick check failed return name == "__LINE__" || name == "__FILE__" || name == "__INCLUDE_LEVEL__";}template <typename ContextT>template <typename IteratorT>inline bool macromap<ContextT>::is_defined(IteratorT const &begin, IteratorT const &end) const{// in normal mode the name under inspection should consist of an identifier// onlytoken_id id = token_id(*begin); if (T_IDENTIFIER != id && !IS_CATEGORY(id, KeywordTokenType) && !IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) && !IS_CATEGORY(id, BoolLiteralTokenType)) { BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname, impl::get_full_name(begin, end).c_str(), main_pos); return false; }IteratorT it = begin;string_type name ((*it).get_value());typename defined_macros_type::iterator cit; if (++it != end) { // there should be only one token as the inspected name BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname, impl::get_full_name(begin, end).c_str(), main_pos); return false; } return is_defined(name, cit, 0);}///////////////////////////////////////////////////////////////////////////////// same as above, only takes an arbitrary string type as its parametertemplate <typename ContextT>inline bool macromap<ContextT>::is_defined(string_type const &str) const{ typename defined_macros_type::iterator cit; return is_defined(str, cit, 0); }///////////////////////////////////////////////////////////////////////////////// // Get the macro definition for the given macro scope/////////////////////////////////////////////////////////////////////////////////template <typename ContextT>inline bool macromap<ContextT>::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) const{ typename defined_macros_type::iterator it; if (!is_defined(name, it, scope)) return false; macro_definition_type ¯o_def = *(*it).second.get(); has_parameters = macro_def.is_functionlike; is_predefined = macro_def.is_predefined; pos = macro_def.macroname.get_position(); parameters = macro_def.macroparameters; definition = macro_def.macrodefinition; return true;}///////////////////////////////////////////////////////////////////////////////// // remove_macro(): remove a macro from the macromap/////////////////////////////////////////////////////////////////////////////////template <typename ContextT>inline bool macromap<ContextT>::remove_macro(string_type const &name, position_type const& pos, bool even_predefined){ typename defined_macros_type::iterator it = current_macros->find(name); if (it != current_macros->end()) { if ((*it).second->is_predefined) { if (!even_predefined || impl::is_special_macroname(name)) { BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_undefine_statement, name.c_str(), main_pos); return false; } } current_macros->erase(it); // call the context supplied preprocessing hook function token_type tok(T_IDENTIFIER, name, pos);#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0 ctx.get_hooks().undefined_macro(tok);#else ctx.get_hooks().undefined_macro(ctx.derived(), tok);#endif return true; } else if (impl::is_special_macroname(name)) { BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_undefine_statement, name.c_str(), pos); } return false; // macro was not defined}///////////////////////////////////////////////////////////////////////////////// // expand_tokensequence//// This function is a helper function which wraps the given iterator // range into corresponding unput_iterator's and calls the main workhorse// of the macro expansion engine (the function expand_tokensequence_worker)//// This is the top level macro expansion function called from the // preprocessing iterator component only./////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename IteratorT, typename ContainerT>inline typename ContextT::token_type const ¯omap<ContextT>::expand_tokensequence(IteratorT &first, IteratorT const &last, ContainerT &pending, ContainerT &expanded, bool& seen_newline, bool expand_operator_defined){ typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT> gen_type; typedef typename gen_type::return_type iterator_type; iterator_type first_it = gen_type::generate(expanded, first); iterator_type last_it = gen_type::generate(last);on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it); return expand_tokensequence_worker(pending, first_it, last_it, seen_newline, expand_operator_defined);}/////////////////////////////////////////////////////////////////////////////////// expand_tokensequence_worker//// This function is the main workhorse of the macro expansion engine. It// expands as much tokens as needed to identify the next preprocessed // token to return to the caller. // It returns the next preprocessed token.//// The iterator 'first' is adjusted accordingly./////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename IteratorT, typename ContainerT>inline typename ContextT::token_type const ¯omap<ContextT>::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){// if there exist pending tokens (tokens, which are already preprocessed), then// return the next one from there if (!pending.empty()) { on_exit::pop_front<definition_container_type> pop_front_token(pending); return act_token = pending.front(); }// analyze the next element of the given sequence, if it is an // T_IDENTIFIER token, try to replace this as a macro etc. using namespace boost::wave; typedef unput_queue_iterator<IteratorT, token_type, ContainerT> iterator_type; if (first != last) { token_id id = token_id(*first); // ignore placeholder tokens if (T_PLACEHOLDER == id) { token_type placeholder = *first; ++first; if (first == last) return act_token = placeholder; id = token_id(*first); } if (T_IDENTIFIER == id || IS_CATEGORY(id, KeywordTokenType) || IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) || IS_CATEGORY(id, BoolLiteralTokenType)) { // try to replace this identifier as a macro if (expand_operator_defined && (*first).get_value() == "defined") { // resolve operator defined() return resolve_defined(first, last, pending); } else if (boost::wave::need_variadics(ctx.get_language()) && (*first).get_value() == "_Pragma") { // in C99 mode only: resolve the operator _Pragma token_type curr_token = *first; if (!resolve_operator_pragma(first, last, pending, seen_newline) || pending.size() > 0) { // unknown to us pragma or supplied replacement, return the // next token on_exit::pop_front<definition_container_type> pop_token(pending); return act_token = pending.front(); } // the operator _Pragma() was eaten completely, continue return act_token = token_type(T_PLACEHOLDER, "_", curr_token.get_position()); } token_type name_token (*first); typename defined_macros_type::iterator it; if (is_defined(name_token.get_value(), it)) { // the current token contains an identifier, which is currently // defined as a macro if (expand_macro(pending, name_token, it, first, last, seen_newline, expand_operator_defined)) { // the tokens returned by expand_macro should be rescanned // beginning at the last token of the returned replacement list if (first != last) { // splice the last token back into the input queue typename ContainerT::reverse_iterator rit = pending.rbegin(); first.get_unput_queue().splice( first.get_unput_queue().begin(), pending, (++rit).base(), pending.end()); } // fall through ... } else if (!pending.empty()) { // return the first token from the pending queue on_exit::pop_front<definition_container_type> pop_queue (pending); return act_token = pending.front(); } else { // macro expansion reached the eoi return act_token = token_type(); } // return the next preprocessed token return expand_tokensequence_worker(pending, first, last, seen_newline, expand_operator_defined); }// else if (expand_operator_defined) {// // in preprocessing conditionals undefined identifiers and keywords // // are to be replaced with '0' (see. C++ standard 16.1.4, [cpp.cond])// return act_token = // token_type(T_INTLIT, "0", (*first++).get_position());// } else { act_token = name_token; ++first; return act_token; } } else if (expand_operator_defined && IS_CATEGORY(*first, BoolLiteralTokenType)) { // expanding a constant expression inside #if/#elif, special handling
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -