LCOV - code coverage report
Current view: top level - usr/include/boost/wave/util - cpp_macromap_utils.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 143 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*=============================================================================
       2             :     Boost.Wave: A Standard compliant C++ preprocessor library
       3             : 
       4             :     Token sequence analysis and transformation helper functions
       5             : 
       6             :     http://www.boost.org/
       7             : 
       8             :     Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
       9             :     Software License, Version 1.0. (See accompanying file
      10             :     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
      11             : =============================================================================*/
      12             : 
      13             : #if !defined(CPP_MACROMAP_UTIL_HPP_HK041119)
      14             : #define CPP_MACROMAP_UTIL_HPP_HK041119
      15             : 
      16             : #include <boost/assert.hpp>
      17             : 
      18             : #include <boost/wave/wave_config.hpp>
      19             : #include <boost/wave/token_ids.hpp>
      20             : #include <boost/wave/util/unput_queue_iterator.hpp>
      21             : 
      22             : // this must occur after all of the includes and before any code appears
      23             : #ifdef BOOST_HAS_ABI_HEADERS
      24             : #include BOOST_ABI_PREFIX
      25             : #endif
      26             : 
      27             : ///////////////////////////////////////////////////////////////////////////////
      28             : //
      29             : // This file contains the definition of several token sequence analyze
      30             : // and transformation utility functions needed during macro handling.
      31             : //
      32             : ///////////////////////////////////////////////////////////////////////////////
      33             : 
      34             : ///////////////////////////////////////////////////////////////////////////////
      35             : namespace boost {
      36             : namespace wave {
      37             : namespace util {
      38             : 
      39             : ///////////////////////////////////////////////////////////////////////////////
      40             : namespace on_exit {
      41             : 
      42             :     ///////////////////////////////////////////////////////////////////////////
      43             :     //
      44             :     //  On destruction pop the first element of the list given as the argument
      45             :     //
      46             :     ///////////////////////////////////////////////////////////////////////////
      47             :     template <typename ContainerT>
      48             :     class pop_front {
      49             :     public:
      50           0 :         pop_front(ContainerT &list_) : list(list_) {}
      51           0 :         ~pop_front() { list.pop_front(); }
      52             : 
      53             :     private:
      54             :         ContainerT &list;
      55             :     };
      56             : 
      57             :     ///////////////////////////////////////////////////////////////////////////
      58             :     //
      59             :     //  Append a given list to the list given as argument
      60             :     //  On destruction pop the first element of the list given as argument
      61             :     //
      62             :     ///////////////////////////////////////////////////////////////////////////
      63             :     template <typename ContainerT>
      64             :     class splice_pop_front {
      65             :     public:
      66             :         splice_pop_front(ContainerT &list_, ContainerT &queue)
      67             :         :   list(list_)
      68             :         {
      69             :             list.splice(list.end(), queue);
      70             :         }
      71             :         ~splice_pop_front() { list.pop_front(); }
      72             : 
      73             :     private:
      74             :         ContainerT &list;
      75             :     };
      76             : 
      77             :     ///////////////////////////////////////////////////////////////////////////
      78             :     //
      79             :     //  On destruction reset a referenced value to its initial state
      80             :     //
      81             :     ///////////////////////////////////////////////////////////////////////////
      82             :     template <typename TypeT>
      83             :     class reset {
      84             :     public:
      85           0 :         reset(TypeT &target_value_, TypeT new_value)
      86           0 :         :   target_value(target_value_), old_value(target_value_)
      87             :         {
      88           0 :             target_value_ = new_value;
      89             :         }
      90           0 :         ~reset() { target_value = old_value; }
      91             : 
      92             :     private:
      93             :         TypeT &target_value;
      94             :         TypeT old_value;
      95             :     };
      96             : 
      97             :     ///////////////////////////////////////////////////////////////////////////
      98             :     //
      99             :     //  On destruction assign the given iterator back
     100             :     //
     101             :     ///////////////////////////////////////////////////////////////////////////
     102             :     template <typename IteratorT, typename UnputIteratorT>
     103             :     class assign
     104             :     {
     105             :     public:
     106           0 :         assign(IteratorT &it_, UnputIteratorT const &uit_)
     107           0 :         :   it(it_), uit(uit_) {}
     108           0 :         ~assign() { it = uit.base(); }
     109             : 
     110             :     private:
     111             :         IteratorT &it;
     112             :         UnputIteratorT const &uit;
     113             :     };
     114             : 
     115             :     template <typename IteratorT>
     116             :     class assign<IteratorT, IteratorT> {
     117             :     public:
     118             :         assign(IteratorT &it_, IteratorT const &uit_)
     119             :         :   it(it_), uit(uit_) {}
     120             :         ~assign() { it = uit; }
     121             : 
     122             :     private:
     123             :         IteratorT &it;
     124             :         IteratorT const &uit;
     125             :     };
     126             : 
     127             : ///////////////////////////////////////////////////////////////////////////////
     128             : }   // namespace on_exit
     129             : 
     130             : ///////////////////////////////////////////////////////////////////////////////
     131             : namespace impl {
     132             : 
     133             : ///////////////////////////////////////////////////////////////////////////////
     134             : //
     135             : //  Test, whether a given identifier resolves to a predefined name
     136             : //
     137             : ///////////////////////////////////////////////////////////////////////////////
     138             : template <typename StringT>
     139             : inline bool
     140           0 : is_special_macroname (StringT const &name)
     141             : {
     142           0 :     if (name.size() < 7)
     143             :         return false;
     144             : 
     145           0 :     if ("defined" == name)
     146             :         return true;
     147             : 
     148           0 :     if ('_' == name[0] && '_' == name[1]) {
     149           0 :     StringT str = name.substr(2);
     150             : 
     151           0 :         if (str == "cplusplus"  || str == "STDC__" ||
     152           0 :             str == "TIME__"     || str == "DATE__" ||
     153           0 :             str == "LINE__"     || str == "FILE__" ||
     154           0 :             str == "INCLUDE_LEVEL__")
     155             :         {
     156           0 :             return true;
     157             :         }
     158             :     }
     159             :     return false;
     160             : }
     161             : 
     162             : ///////////////////////////////////////////////////////////////////////////////
     163             : //
     164             : //  Test, whether two tokens are to be considered equal (different sequences
     165             : //  of whitespace are considered to be equal)
     166             : //
     167             : ///////////////////////////////////////////////////////////////////////////////
     168             : template <typename TokenT>
     169             : inline bool
     170           0 : token_equals(TokenT const &left, TokenT const &right)
     171             : {
     172             :     using namespace boost::wave;
     173             : 
     174           0 :     if (IS_CATEGORY(left, ParameterTokenType)) {
     175             :     //  if the existing token is of type T_PARAMETERBASE, then the right token
     176             :     //  must be of type T_IDENTIFIER or a keyword
     177           0 :     token_id id = token_id(right);
     178             : 
     179           0 :         return (T_IDENTIFIER == id ||
     180           0 :                 IS_CATEGORY(id, KeywordTokenType) ||
     181           0 :                 IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||
     182           0 :                 IS_CATEGORY(id, BoolLiteralTokenType)) &&
     183           0 :             left.get_value() == right.get_value();
     184             :     }
     185             : 
     186             :     // if the left token has whitespace, the value is irrelevant
     187           0 :     return token_id(left) == token_id(right) && (
     188           0 :             IS_CATEGORY(left, WhiteSpaceTokenType) ||
     189           0 :             left.get_value() == right.get_value()
     190             :         );
     191             : }
     192             : 
     193             : ///////////////////////////////////////////////////////////////////////////////
     194             : //
     195             : //  Tests, whether two macro definitions are equal
     196             : //
     197             : ///////////////////////////////////////////////////////////////////////////////
     198             : template <typename ContainerT>
     199             : inline bool
     200           0 : definition_equals(ContainerT const &definition,
     201             :     ContainerT const &new_definition)
     202             : {
     203             :     typedef typename ContainerT::const_iterator const_iterator_type;
     204             : 
     205           0 : const_iterator_type first1 = definition.begin();
     206           0 : const_iterator_type last1 = definition.end();
     207           0 : const_iterator_type first2 = new_definition.begin();
     208           0 : const_iterator_type last2 = new_definition.end();
     209             : 
     210           0 :     while (first1 != last1 && first2 != last2 && token_equals(*first1, *first2))
     211             :     {
     212             :     // skip whitespace, if both sequences have a whitespace next
     213           0 :     token_id id1 = next_token<const_iterator_type>::peek(first1, last1, false);
     214           0 :     token_id id2 = next_token<const_iterator_type>::peek(first2, last2, false);
     215             : 
     216           0 :         if (IS_CATEGORY(id1, WhiteSpaceTokenType) &&
     217           0 :             IS_CATEGORY(id2, WhiteSpaceTokenType))
     218             :         {
     219             :         // all consecutive whitespace tokens count as one whitespace
     220             :         // adjust first1 and first2 accordingly
     221           0 :             skip_whitespace(first1, last1);
     222           0 :             skip_whitespace(first2, last2);
     223             :         }
     224           0 :         else if (!IS_CATEGORY(id1, WhiteSpaceTokenType) &&
     225           0 :                  !IS_CATEGORY(id2, WhiteSpaceTokenType))
     226             :         {
     227           0 :             ++first1;
     228           0 :             ++first2;
     229             :         }
     230             :         else {
     231             :         // the sequences differ
     232             :             break;
     233             :         }
     234             :     }
     235           0 :     return (first1 == last1 && first2 == last2) ? true : false;
     236             : }
     237             : 
     238             : ///////////////////////////////////////////////////////////////////////////////
     239             : //
     240             : //  Tests, whether two given sets of macro parameters are equal
     241             : //
     242             : ///////////////////////////////////////////////////////////////////////////////
     243             : template <typename ContainerT>
     244             : inline bool
     245           0 : parameters_equal(ContainerT const &parameters, ContainerT const &new_parameters)
     246             : {
     247           0 :     if (parameters.size() != new_parameters.size())
     248             :         return false;   // different parameter count
     249             : 
     250             :     typedef typename ContainerT::const_iterator const_iterator_type;
     251             : 
     252             : const_iterator_type first1 = parameters.begin();
     253           0 : const_iterator_type last1 = parameters.end();
     254             : const_iterator_type first2 = new_parameters.begin();
     255           0 : const_iterator_type last2 = new_parameters.end();
     256             : 
     257           0 :     while (first1 != last1 && first2 != last2) {
     258             :     // parameters are different, if the corresponding tokens are different
     259             :         using namespace boost::wave;
     260           0 :         if (token_id(*first1) != token_id(*first2) ||
     261           0 :             (*first1).get_value() != (*first2).get_value())
     262             :         {
     263             :             break;
     264             :         }
     265           0 :         ++first1;
     266           0 :         ++first2;
     267             :     }
     268           0 :     return (first1 == last1 && first2 == last2) ? true : false;
     269             : }
     270             : 
     271             : ///////////////////////////////////////////////////////////////////////////////
     272             : //
     273             : //  Strip leading and trailing whitespace from the given token sequence
     274             : //
     275             : ///////////////////////////////////////////////////////////////////////////////
     276             : template <typename ContainerT>
     277             : inline void
     278           0 : trim_replacement_list (ContainerT &replacement_list)
     279             : {
     280             :     using namespace boost::wave;
     281             : 
     282             : // strip leading whitespace
     283           0 :     if (replacement_list.size() > 0) {
     284           0 :     typename ContainerT::iterator end = replacement_list.end();
     285           0 :     typename ContainerT::iterator it = replacement_list.begin();
     286             : 
     287           0 :         while (it != end && IS_CATEGORY(*it, WhiteSpaceTokenType)) {
     288           0 :             token_id id(*it);
     289           0 :             if (T_PLACEHOLDER != id && T_PLACEMARKER != id) {
     290           0 :                 typename ContainerT::iterator next = it;
     291           0 :                 ++next;
     292           0 :                 replacement_list.erase(it);
     293           0 :                 it = next;
     294             :             }
     295             :             else {
     296           0 :                 ++it;
     297             :             }
     298             :         }
     299             :     }
     300             : 
     301             : // strip trailing whitespace
     302           0 :     if (replacement_list.size() > 0) {
     303           0 :     typename ContainerT::reverse_iterator rend = replacement_list.rend();
     304           0 :     typename ContainerT::reverse_iterator rit = replacement_list.rbegin();
     305             : 
     306           0 :         while (rit != rend && IS_CATEGORY(*rit, WhiteSpaceTokenType))
     307           0 :             ++rit;
     308             : 
     309           0 :     typename ContainerT::iterator end = replacement_list.end();
     310             :     typename ContainerT::iterator it = rit.base();
     311             : 
     312           0 :         while (it != end && IS_CATEGORY(*it, WhiteSpaceTokenType)) {
     313           0 :             token_id id(*it);
     314           0 :             if (T_PLACEHOLDER != id && T_PLACEMARKER != id) {
     315           0 :                 typename ContainerT::iterator next = it;
     316           0 :                 ++next;
     317           0 :                 replacement_list.erase(it);
     318           0 :                 it = next;
     319             :             }
     320             :             else {
     321           0 :                 ++it;
     322             :             }
     323             :         }
     324             :     }
     325           0 : }
     326             : 
     327             : ///////////////////////////////////////////////////////////////////////////////
     328             : //
     329             : //  Tests, whether the given token sequence consists out of whitespace only
     330             : //
     331             : ///////////////////////////////////////////////////////////////////////////////
     332             : template <typename ContainerT>
     333             : inline bool
     334           0 : is_whitespace_only (ContainerT const &argument)
     335             : {
     336           0 :     typename ContainerT::const_iterator end = argument.end();
     337           0 :     for (typename ContainerT::const_iterator it = argument.begin();
     338           0 :           it != end; ++it)
     339             :     {
     340           0 :         if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
     341             :             return false;
     342             :     }
     343             :     return true;
     344             : }
     345             : 
     346             : ///////////////////////////////////////////////////////////////////////////////
     347             : //
     348             : //  Remove all placeholder tokens from the given token sequence
     349             : //
     350             : ///////////////////////////////////////////////////////////////////////////////
     351             : template <typename ContainerT>
     352             : inline void
     353           0 : remove_placeholders (ContainerT &replacement_list)
     354             : {
     355             :     using namespace boost::wave;
     356             : 
     357             : // strip leading whitespace
     358           0 :     if (replacement_list.size() > 0) {
     359           0 :     typename ContainerT::iterator end = replacement_list.end();
     360           0 :     typename ContainerT::iterator it = replacement_list.begin();
     361             : 
     362           0 :         while (it != end) {
     363           0 :             token_id id(*it);
     364           0 :             if (T_PLACEHOLDER == id || T_PLACEMARKER == id) {
     365           0 :                 typename ContainerT::iterator next = it;
     366           0 :                 ++next;
     367           0 :                 replacement_list.erase(it);
     368           0 :                 it = next;
     369             :             }
     370             :             else {
     371           0 :                 ++it;
     372             :             }
     373             :         }
     374             : 
     375             :     // remove all 'new' leading and trailing whitespace
     376           0 :         if (is_whitespace_only(replacement_list))
     377           0 :             trim_replacement_list(replacement_list);
     378             :     }
     379           0 : }
     380             : 
     381             : ///////////////////////////////////////////////////////////////////////////////
     382             : //
     383             : //  Remove all whitespace tokens on the left side of the given token sequence
     384             : //
     385             : ///////////////////////////////////////////////////////////////////////////////
     386             : template <typename ContainerT>
     387             : inline void
     388           0 : trim_sequence_left (ContainerT &argument)
     389             : {
     390             :     using namespace boost::wave;
     391             : 
     392             : // strip leading whitespace (should be only one token)
     393           0 :     if (argument.size() > 0 &&
     394           0 :         IS_CATEGORY(argument.front(), WhiteSpaceTokenType))
     395             :     {
     396           0 :         argument.pop_front();
     397             :     }
     398           0 : }
     399             : 
     400             : ///////////////////////////////////////////////////////////////////////////////
     401             : //
     402             : //  Remove all whitespace tokens on the right side of the given token sequence
     403             : //
     404             : ///////////////////////////////////////////////////////////////////////////////
     405             : template <typename ContainerT>
     406             : inline void
     407           0 : trim_sequence_right (ContainerT &argument)
     408             : {
     409             :     using namespace boost::wave;
     410             : 
     411             : // strip trailing whitespace (should be only one token)
     412           0 :     if (argument.size() > 0 &&
     413           0 :         IS_CATEGORY(argument.back(), WhiteSpaceTokenType))
     414             :     {
     415           0 :         argument.pop_back();
     416             :     }
     417           0 : }
     418             : 
     419             : ///////////////////////////////////////////////////////////////////////////////
     420             : //
     421             : //  Remove all whitespace tokens on the left and right sides of the given token
     422             : //  sequence
     423             : //
     424             : ///////////////////////////////////////////////////////////////////////////////
     425             : template <typename ContainerT>
     426             : inline void
     427           0 : trim_sequence (ContainerT &argument)
     428             : {
     429           0 :     trim_sequence_left(argument);
     430           0 :     trim_sequence_right(argument);
     431             : }
     432             : 
     433             : ///////////////////////////////////////////////////////////////////////////////
     434             : // call 'skipped_token' preprocessing hook
     435             : template <typename ContextT>
     436           0 : void call_skipped_token_hook(ContextT& ctx,
     437             :     typename ContextT::token_type const& skipped)
     438             : {
     439             : #if BOOST_WAVE_USE_DEPRECIATED_PREPROCESSING_HOOKS != 0
     440             :     ctx.get_hooks().skipped_token(skipped);
     441             : #else
     442           0 :     ctx.get_hooks().skipped_token(ctx.derived(), skipped);
     443             : #endif
     444           0 : }
     445             : 
     446             : ///////////////////////////////////////////////////////////////////////////////
     447             : //
     448             : //  Skip forward to a given token
     449             : //
     450             : ///////////////////////////////////////////////////////////////////////////////
     451             : template <typename ContextT, typename IteratorT>
     452             : inline bool
     453           0 : skip_to_token(ContextT& ctx, IteratorT &it, IteratorT const &end,
     454             :     token_id id, bool& seen_newline)
     455             : {
     456             :     using namespace boost::wave;
     457           0 :     if (token_id(*it) == id)
     458             :         return true;
     459             : 
     460             : //     call_skipped_token_hook(ctx, *it);
     461           0 :     if (++it == end)
     462             :         return false;
     463             : 
     464           0 :     while (IS_CATEGORY(*it, WhiteSpaceTokenType) ||
     465           0 :            T_NEWLINE == token_id(*it))
     466             :     {
     467           0 :         if (T_NEWLINE == token_id(*it))
     468           0 :             seen_newline = true;
     469             : 
     470             : //         call_skipped_token_hook(ctx, *it);
     471           0 :         if (++it == end)
     472             :             return false;
     473             :     }
     474           0 :     return token_id(*it) == id;
     475             : }
     476             : 
     477             : ///////////////////////////////////////////////////////////////////////////////
     478             : //
     479             : //  Get the full name of a given macro name (concatenate the string
     480             : //  representations of the single tokens).
     481             : //
     482             : ///////////////////////////////////////////////////////////////////////////////
     483             : template <typename IteratorT>
     484             : inline std::string
     485           0 : get_full_name(IteratorT const &begin, IteratorT const &end)
     486             : {
     487           0 :     std::string full_name;
     488           0 :     for (IteratorT err_it = begin; err_it != end; ++err_it)
     489           0 :         full_name += (*err_it).get_value().c_str();
     490             : 
     491           0 :     return full_name;
     492             : }
     493             : 
     494             : ///////////////////////////////////////////////////////////////////////////////
     495             : //
     496             : //  The following predicate is used in conjunction with the remove_copy_if
     497             : //  algorithm to allow the detection of an eventually copied operator ##.
     498             : //  No removal is performed in any case.
     499             : //
     500             : ///////////////////////////////////////////////////////////////////////////////
     501             : class find_concat_operator {
     502             : public:
     503           0 :     find_concat_operator(bool &found_) : found_concat(found_) {}
     504             : 
     505             :     template <typename TokenT>
     506           0 :     bool operator()(TokenT const &tok)
     507             :     {
     508             :         using namespace boost::wave;
     509           0 :         if (T_POUND_POUND == BASE_TOKEN(token_id(tok)))
     510           0 :             found_concat = true;
     511             :         return false;
     512             :     }
     513             : 
     514             : private:
     515             :     bool &found_concat;
     516             : };
     517             : 
     518             : ///////////////////////////////////////////////////////////////////////////////
     519             : //  Convert a string of an arbitrary string compatible type to a internal
     520             : //  string (BOOST_WAVE_STRING)
     521             : template <typename Target, typename Src>
     522             : struct to_string_helper
     523             : {
     524             :     typedef Target type;
     525             : 
     526           0 :     static Target call(Src const& str)
     527             :     {
     528           0 :         return Target(str.c_str());
     529             :     }
     530             : };
     531             : 
     532             : // do nothing if types are equal
     533             : template <typename Src>
     534             : struct to_string_helper<Src, Src>
     535             : {
     536             :     typedef Src const& type;
     537             : 
     538           0 :     static Src const& call(Src const& str)
     539             :     {
     540             :         return str;
     541             :     }
     542             : };
     543             : 
     544             : template <typename Target>
     545             : struct to_string_helper<Target, char const*>
     546             : {
     547             :     typedef Target type;
     548             : 
     549             :     static Target call(char const* str)
     550             :     {
     551             :         return Target(str);
     552             :     }
     553             : };
     554             : 
     555             : ///////////////////////////////////////////////////////////////////////////////
     556             : }   // namespace impl
     557             : 
     558             : template <typename Target, typename Src>
     559             : inline typename impl::to_string_helper<Target, Src>::type
     560           0 : to_string(Src const& src)
     561             : {
     562           0 :     return impl::to_string_helper<Target, Src>::call(src);
     563             : }
     564             : 
     565             : ///////////////////////////////////////////////////////////////////////////////
     566             : }   // namespace util
     567             : }   // namespace wave
     568             : }   // namespace boost
     569             : 
     570             : // the suffix header occurs after all of the code
     571             : #ifdef BOOST_HAS_ABI_HEADERS
     572             : #include BOOST_ABI_SUFFIX
     573             : #endif
     574             : 
     575             : #endif // !defined(CPP_MACROMAP_UTIL_HPP_HK041119)

Generated by: LCOV version 1.14