cpp_macromap.hpp
字号:
// handle concatenation operators if (found && !concat_tokensequence(replacement_list)) return false; ++first; // skip macro name } }// rescan the replacement listContainerT expanded_list;#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0 ctx.get_hooks().expanded_macro(replacement_list);#else ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);#endif rescan_replacement_list(curr_token, macro_def, replacement_list, expanded_list, expand_operator_defined, first, last); #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0 ctx.get_hooks().rescanned_macro(expanded_list); #else ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list); #endif expanded.splice(expanded.end(), expanded_list); return true; // rescan is required}/////////////////////////////////////////////////////////////////////////////////// If the token under inspection points to a certain predefined macro it will // be expanded, otherwise false is returned.// (only __FILE__, __LINE__ and __INCLUDE_LEVEL__ macros are expanded here)/////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename ContainerT>inline bool macromap<ContextT>::expand_predefined_macro(token_type const &curr_token, ContainerT &expanded){ using namespace boost::wave; string_type const &value = curr_token.get_value(); if (value.size() < 8 || '_' != value[0] || '_' != value[1]) return false; // quick check failed if (value == "__LINE__") { // expand the __LINE__ macro char buffer[22]; // 21 bytes holds all NUL-terminated unsigned 64-bit numbers using namespace std; // for some systems sprintf is in namespace std sprintf(buffer, "%d", main_pos.get_line()); expanded.push_back(token_type(T_INTLIT, buffer, curr_token.get_position())); return true; } else if (value == "__FILE__") { // expand the __FILE__ macro namespace fs = boost::filesystem; std::string file("\""); fs::path filename(main_pos.get_file().c_str(), fs::native); using boost::wave::util::impl::escape_lit; file += escape_lit(filename.native_file_string()) + "\""; expanded.push_back(token_type(T_STRINGLIT, file.c_str(), curr_token.get_position())); return true; } else if (value == "__INCLUDE_LEVEL__") { // expand the __INCLUDE_LEVEL__ macro char buffer[22]; // 21 bytes holds all NUL-terminated unsigned 64-bit numbers using namespace std; // for some systems sprintf is in namespace std sprintf(buffer, "%d", (int)ctx.get_iteration_depth()); expanded.push_back(token_type(T_INTLIT, buffer, curr_token.get_position())); return true; } return false; // no predefined token}/////////////////////////////////////////////////////////////////////////////////// resolve_defined(): resolve the operator defined() and replace it with the // correct T_INTLIT token/////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename IteratorT, typename ContainerT>inline typename ContextT::token_type const ¯omap<ContextT>::resolve_defined(IteratorT &first, IteratorT const &last, ContainerT &pending) { using namespace boost::wave; using namespace boost::wave::grammars;ContainerT result;IteratorT start = first;boost::spirit::classic::parse_info<IteratorT> hit = defined_grammar_gen<typename ContextT::lexer_type>:: parse_operator_defined(start, last, result); if (!hit.hit) { string_type msg ("defined(): "); msg = msg + util::impl::as_string<string_type>(first, last); BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression, msg.c_str(), main_pos); // insert a dummy token pending.push_back(token_type(T_INTLIT, "0", main_pos)); } else { impl::assign_iterator<IteratorT>::do_(first, hit.stop); // insert a token, which reflects the outcome pending.push_back(token_type(T_INTLIT, is_defined(result.begin(), result.end()) ? "1" : "0", main_pos)); } on_exit::pop_front<definition_container_type> pop_front_token(pending); return act_token = pending.front();}/////////////////////////////////////////////////////////////////////////////////// resolve_operator_pragma(): resolve the operator _Pragma() and dispatch to// the associated action//// This function returns true, if the pragma was correctly interpreted. // The iterator 'first' is positioned behind the closing ')'.// This function returns false, if the _Pragma was not known, the // preprocessed token sequence is pushed back to the 'pending' sequence./////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename IteratorT, typename ContainerT>inline boolmacromap<ContextT>::resolve_operator_pragma(IteratorT &first, IteratorT const &last, ContainerT &pending, bool& seen_newline) {// isolate the parameter of the operator _Pragma token_type pragma_token = *first; if (!impl::skip_to_token(first, last, T_LEFTPAREN, seen_newline)) { // illformed operator _Pragma BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression, "operator _Pragma()", pragma_token.get_position()); return false; } std::vector<ContainerT> arguments;#if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0 typename std::vector<ContainerT>::size_type count_args = collect_arguments (pragma_token, arguments, first, last, 1, seen_newline);#else IteratorT endparen = first; typename std::vector<ContainerT>::size_type count_args = collect_arguments (pragma_token, arguments, first, endparen, last, 1, seen_newline);#endif// verify the parameter count if (pragma_token.get_position().get_file().empty()) pragma_token.set_position(act_token.get_position()); if (count_args < 1 || arguments.size() < 1) { // too few macro arguments BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_few_macroarguments, pragma_token.get_value().c_str(), pragma_token.get_position()); return false; } if (count_args > 1 || arguments.size() > 1) { // too many macro arguments BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_many_macroarguments, pragma_token.get_value().c_str(), pragma_token.get_position()); return false; }// preprocess the pragma token body typedef typename std::vector<ContainerT>::value_type::iterator argument_iterator_type; ContainerT expanded; argument_iterator_type begin_it = arguments[0].begin(); argument_iterator_type end_it = arguments[0].end(); expand_whole_tokensequence(expanded, begin_it, end_it, false);// un-escape the parameter of the operator _Pragma typedef typename token_type::string_type string_type; string_type pragma_cmd; typename ContainerT::const_iterator end_exp = expanded.end(); for (typename ContainerT::const_iterator it_exp = expanded.begin(); it_exp != end_exp; ++it_exp) { if (T_EOF == token_id(*it_exp)) break; if (IS_CATEGORY(*it_exp, WhiteSpaceTokenType)) continue; if (T_STRINGLIT != token_id(*it_exp)) { // ill formed operator _Pragma BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_pragma_option, "_Pragma", pragma_token.get_position()); return false; } if (pragma_cmd.size() > 0) { // there should be exactly one string literal (string literals are to // be concatenated at translation phase 6, but _Pragma operators are // to be executed at translation phase 4) BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_pragma_option, "_Pragma", pragma_token.get_position()); return false; } // remove the '\"' and concat all given string literal-values string_type token_str = (*it_exp).get_value(); pragma_cmd += token_str.substr(1, token_str.size() - 2); } string_type pragma_cmd_unesc = impl::unescape_lit(pragma_cmd);// tokenize the pragma body typedef typename ContextT::lexer_type lexer_type; ContainerT pragma; std::string pragma_cmd_str(pragma_cmd_unesc.c_str()); lexer_type it = lexer_type(pragma_cmd_str.begin(), pragma_cmd_str.end(), pragma_token.get_position(), ctx.get_language()); lexer_type end = lexer_type(); for (/**/; it != end; ++it) pragma.push_back(*it);// analyze the preprocessed token sequence and eventually dispatch to the // associated action if (interpret_pragma(ctx, pragma_token, pragma.begin(), pragma.end(), pending)) { return true; // successfully recognized a wave specific pragma } // unknown pragma token sequence, push it back and return to the caller pending.push_front(token_type(T_SPACE, " ", pragma_token.get_position())); pending.push_front(token_type(T_RIGHTPAREN, ")", pragma_token.get_position())); pending.push_front(token_type(T_STRINGLIT, string_type("\"") + pragma_cmd + "\"", pragma_token.get_position())); pending.push_front(token_type(T_LEFTPAREN, "(", pragma_token.get_position())); pending.push_front(pragma_token); return false;}/////////////////////////////////////////////////////////////////////////////////// Test, whether the result of a concat operator is well formed or not. //// This is done by re-scanning (re-tokenizing) the resulting token sequence, // which should give back exactly one token./////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename ContainerT>inline boolmacromap<ContextT>::is_valid_concat(string_type new_value, position_type const &pos, ContainerT &rescanned){// re-tokenize the newly generated string typedef typename ContextT::lexer_type lexer_type; std::string value_to_test(new_value.c_str()); boost::wave::language_support lang = boost::wave::enable_prefer_pp_numbers(ctx.get_language()); lang = boost::wave::enable_single_line(lang); lexer_type it = lexer_type(value_to_test.begin(), value_to_test.end(), pos, lang); lexer_type end = lexer_type(); for (/**/; it != end && T_EOF != token_id(*it); ++it) rescanned.push_back(*it);#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 if (boost::wave::need_variadics(ctx.get_language())) return true; // in variadics mode token pasting is well defined#endif // test if the newly generated token sequence contains more than 1 token// the second one is the T_EOF token// BOOST_ASSERT(T_EOF == token_id(rescanned.back())); return 1 == rescanned.size();}/////////////////////////////////////////////////////////////////////////////////// Handle all occurrences of the concatenation operator '##' inside the given// token sequence./////////////////////////////////////////////////////////////////////////////////template <typename ContextT>template <typename ContainerT>inline bool macromap<ContextT>::concat_tokensequence(ContainerT &expanded){ using namespace boost::wave; typedef typename ContainerT::iterator iterator_type; iterator_type end = expanded.end(); iterator_type prev = end; for (iterator_type it = expanded.begin(); it != end; /**/) { if (T_POUND_POUND == BASE_TOKEN(token_id(*it))) { iterator_type next = it; ++next; if (prev == end || next == end) { // error, '##' should be in between two tokens BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator, "concat ('##')", main_pos); return false; } // replace prev##next with the concatenated value, skip whitespace // before and after the '##' operator while (IS_CATEGORY(*next, WhiteSpaceTokenType)) { ++next; if (next == end) { // error, '##' should be in between two tokens BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator, "concat ('##')", main_pos);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -