| /*============================================================================= |
| Boost.Wave: A Standard compliant C++ preprocessor library |
| |
| http://www.boost.org/ |
| |
| Copyright (c) 2001-2010 Hartmut Kaiser. Distributed under the Boost |
| Software License, Version 1.0. (See accompanying file |
| LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| =============================================================================*/ |
| |
| #if !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED) |
| #define MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED |
| |
| #include <vector> |
| |
| #include <boost/assert.hpp> |
| #include <boost/wave/wave_config.hpp> |
| #include <boost/wave/token_ids.hpp> |
| #include <boost/wave/cpplexer/validate_universal_char.hpp> |
| #include <boost/wave/util/unput_queue_iterator.hpp> |
| |
| // this must occur after all of the includes and before any code appears |
| #ifdef BOOST_HAS_ABI_HEADERS |
| #include BOOST_ABI_PREFIX |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { |
| namespace wave { |
| namespace util { |
| |
| namespace impl { |
| |
| // escape a string literal (insert '\\' before every '\"', '?' and '\\') |
| template <typename StringT> |
| inline StringT |
| escape_lit(StringT const &value) |
| { |
| StringT result; |
| typename StringT::size_type pos = 0; |
| typename StringT::size_type pos1 = value.find_first_of ("\"\\?", 0); |
| if (StringT::npos != pos1) { |
| do { |
| result += value.substr(pos, pos1-pos) |
| + StringT("\\") |
| + StringT(1, value[pos1]); |
| pos1 = value.find_first_of ("\"\\?", pos = pos1+1); |
| } while (StringT::npos != pos1); |
| result += value.substr(pos); |
| } |
| else { |
| result = value; |
| } |
| return result; |
| } |
| |
| // un-escape a string literal (remove '\\' just before '\\', '\"' or '?') |
| template <typename StringT> |
| inline StringT |
| unescape_lit(StringT const &value) |
| { |
| StringT result; |
| typename StringT::size_type pos = 0; |
| typename StringT::size_type pos1 = value.find_first_of ("\\", 0); |
| if (StringT::npos != pos1) { |
| do { |
| switch (value[pos1+1]) { |
| case '\\': |
| case '\"': |
| case '?': |
| result = result + value.substr(pos, pos1-pos); |
| pos1 = value.find_first_of ("\\", (pos = pos1+1)+1); |
| break; |
| |
| case 'n': |
| result = result + value.substr(pos, pos1-pos) + "\n"; |
| pos1 = value.find_first_of ("\\", pos = pos1+1); |
| ++pos; |
| break; |
| |
| default: |
| result = result + value.substr(pos, pos1-pos+1); |
| pos1 = value.find_first_of ("\\", pos = pos1+1); |
| } |
| |
| } while (pos1 != StringT::npos); |
| result = result + value.substr(pos); |
| } |
| else { |
| // the string doesn't contain any escaped character sequences |
| result = value; |
| } |
| return result; |
| } |
| |
| // return the string representation of a token sequence |
| template <typename ContainerT, typename PositionT> |
| inline typename ContainerT::value_type::string_type |
| as_stringlit (ContainerT const &token_sequence, PositionT const &pos) |
| { |
| using namespace boost::wave; |
| typedef typename ContainerT::value_type::string_type string_type; |
| |
| string_type result("\""); |
| bool was_whitespace = false; |
| typename ContainerT::const_iterator end = token_sequence.end(); |
| for (typename ContainerT::const_iterator it = token_sequence.begin(); |
| it != end; ++it) |
| { |
| token_id id = token_id(*it); |
| |
| if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) { |
| if (!was_whitespace) { |
| // C++ standard 16.3.2.2 [cpp.stringize] |
| // Each occurrence of white space between the argument's |
| // preprocessing tokens becomes a single space character in the |
| // character string literal. |
| result += " "; |
| was_whitespace = true; |
| } |
| } |
| else if (T_STRINGLIT == id || T_CHARLIT == id) { |
| // string literals and character literals have to be escaped |
| result += impl::escape_lit((*it).get_value()); |
| was_whitespace = false; |
| } |
| else |
| #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 |
| if (T_PLACEMARKER != id) |
| #endif |
| { |
| // now append this token to the string |
| result += (*it).get_value(); |
| was_whitespace = false; |
| } |
| } |
| result += "\""; |
| |
| // validate the resulting literal to contain no invalid universal character |
| // value (throws if invalid chars found) |
| boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(), |
| pos.get_column(), pos.get_file()); |
| return result; |
| } |
| |
| #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 |
| // return the string representation of a token sequence |
| template <typename ContainerT, typename PositionT> |
| inline typename ContainerT::value_type::string_type |
| as_stringlit (std::vector<ContainerT> const &arguments, |
| typename std::vector<ContainerT>::size_type i, PositionT const &pos) |
| { |
| using namespace boost::wave; |
| typedef typename ContainerT::value_type::string_type string_type; |
| |
| BOOST_ASSERT(i < arguments.size()); |
| |
| string_type result("\""); |
| bool was_whitespace = false; |
| |
| for (/**/; i < arguments.size(); ++i) { |
| // stringize all remaining arguments |
| typename ContainerT::const_iterator end = arguments[i].end(); |
| for (typename ContainerT::const_iterator it = arguments[i].begin(); |
| it != end; ++it) |
| { |
| token_id id = token_id(*it); |
| |
| if (IS_CATEGORY(*it, WhiteSpaceTokenType) || T_NEWLINE == id) { |
| if (!was_whitespace) { |
| // C++ standard 16.3.2.2 [cpp.stringize] |
| // Each occurrence of white space between the argument's |
| // preprocessing tokens becomes a single space character in the |
| // character string literal. |
| result += " "; |
| was_whitespace = true; |
| } |
| } |
| else if (T_STRINGLIT == id || T_CHARLIT == id) { |
| // string literals and character literals have to be escaped |
| result += impl::escape_lit((*it).get_value()); |
| was_whitespace = false; |
| } |
| else if (T_PLACEMARKER != id) { |
| // now append this token to the string |
| result += (*it).get_value(); |
| was_whitespace = false; |
| } |
| } |
| |
| // append comma, if not last argument |
| if (i < arguments.size()-1) { |
| result += ","; |
| was_whitespace = false; |
| } |
| } |
| result += "\""; |
| |
| // validate the resulting literal to contain no invalid universal character |
| // value (throws if invalid chars found) |
| boost::wave::cpplexer::impl::validate_literal(result, pos.get_line(), |
| pos.get_column(), pos.get_file()); |
| return result; |
| } |
| #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 |
| |
| // return the string representation of a token sequence |
| template <typename StringT, typename IteratorT> |
| inline StringT |
| as_string(IteratorT it, IteratorT const& end) |
| { |
| StringT result; |
| for (/**/; it != end; ++it) |
| { |
| result += (*it).get_value(); |
| } |
| return result; |
| } |
| |
| // return the string representation of a token sequence |
| template <typename ContainerT> |
| inline typename ContainerT::value_type::string_type |
| as_string (ContainerT const &token_sequence) |
| { |
| typedef typename ContainerT::value_type::string_type string_type; |
| return as_string<string_type>(token_sequence.begin(), |
| token_sequence.end()); |
| } |
| |
| #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 |
| /////////////////////////////////////////////////////////////////////////// |
| // |
| // Copies all arguments beginning with the given index to the output |
| // sequence. The arguments are separated by commas. |
| // |
| template <typename ContainerT, typename PositionT> |
| void replace_ellipsis (std::vector<ContainerT> const &arguments, |
| typename ContainerT::size_type index, |
| ContainerT &expanded, PositionT const &pos) |
| { |
| using namespace cpplexer; |
| typedef typename ContainerT::value_type token_type; |
| |
| token_type comma(T_COMMA, ",", pos); |
| for (/**/; index < arguments.size(); ++index) { |
| ContainerT const &arg = arguments[index]; |
| |
| std::copy(arg.begin(), arg.end(), |
| std::inserter(expanded, expanded.end())); |
| |
| if (index < arguments.size()-1) |
| expanded.push_back(comma); |
| } |
| } |
| #endif |
| |
| // Skip all whitespace characters and queue the skipped characters into the |
| // given container |
| template <typename IteratorT> |
| inline boost::wave::token_id |
| skip_whitespace(IteratorT &first, IteratorT const &last) |
| { |
| token_id id = util::impl::next_token<IteratorT>::peek(first, last, false); |
| if (IS_CATEGORY(id, WhiteSpaceTokenType)) { |
| do { |
| ++first; |
| id = util::impl::next_token<IteratorT>::peek(first, last, false); |
| } while (IS_CATEGORY(id, WhiteSpaceTokenType)); |
| } |
| ++first; |
| return id; |
| } |
| |
| template <typename IteratorT, typename ContainerT> |
| inline boost::wave::token_id |
| skip_whitespace(IteratorT &first, IteratorT const &last, ContainerT &queue) |
| { |
| queue.push_back (*first); // queue up the current token |
| |
| token_id id = util::impl::next_token<IteratorT>::peek(first, last, false); |
| if (IS_CATEGORY(id, WhiteSpaceTokenType)) { |
| do { |
| queue.push_back(*++first); // queue up the next whitespace |
| id = util::impl::next_token<IteratorT>::peek(first, last, false); |
| } while (IS_CATEGORY(id, WhiteSpaceTokenType)); |
| } |
| ++first; |
| return id; |
| } |
| |
| } // namespace impl |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| } // namespace util |
| } // namespace wave |
| } // namespace boost |
| |
| // the suffix header occurs after all of the code |
| #ifdef BOOST_HAS_ABI_HEADERS |
| #include BOOST_ABI_SUFFIX |
| #endif |
| |
| #endif // !defined(MACRO_HELPERS_HPP_931BBC99_EBFA_4692_8FBE_B555998C2C39_INCLUDED) |