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

cpp_macromap.hpp

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