欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

cpp_macromap.hpp

Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
HPP
第 1 页 / 共 5 页
字号:
        // 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 &macromap<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 + -