/*============================================================================= Boost.Wave: A Standard compliant C++ preprocessor library http://www.boost.org/ Copyright (c) 2001-2012 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 #include #include #include #include #include // 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 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 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 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 inline typename ContainerT::value_type::string_type as_stringlit (std::vector const &arguments, typename std::vector::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 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 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(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 void replace_ellipsis (std::vector 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 inline boost::wave::token_id skip_whitespace(IteratorT &first, IteratorT const &last) { token_id id = util::impl::next_token::peek(first, last, false); if (IS_CATEGORY(id, WhiteSpaceTokenType)) { do { ++first; id = util::impl::next_token::peek(first, last, false); } while (IS_CATEGORY(id, WhiteSpaceTokenType)); } ++first; return id; } template 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::peek(first, last, false); if (IS_CATEGORY(id, WhiteSpaceTokenType)) { do { queue.push_back(*++first); // queue up the next whitespace id = util::impl::next_token::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)