emit_custom_line_directives.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. http://www.boost.org/
  4. Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
  5. Software License, Version 1.0. (See accompanying file
  6. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_WAVE_emit_custom_line_directives_HOOKS_INCLUDED)
  9. #define BOOST_WAVE_emit_custom_line_directives_HOOKS_INCLUDED
  10. #include <cstdio>
  11. #include <ostream>
  12. #include <string>
  13. #include <algorithm>
  14. #include <boost/assert.hpp>
  15. #include <boost/config.hpp>
  16. #include <boost/wave/token_ids.hpp>
  17. #include <boost/wave/util/macro_helpers.hpp>
  18. #include <boost/wave/preprocessing_hooks.hpp>
  19. ///////////////////////////////////////////////////////////////////////////////
  20. //
  21. // The emit_custom_line_directives_hooks policy class is used to register some
  22. // of the more advanced (and probably more rarely used hooks with the Wave
  23. // library.
  24. //
  25. // This policy type is used as a template parameter to the boost::wave::context<>
  26. // object.
  27. //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. class emit_custom_line_directives_hooks
  30. : public boost::wave::context_policies::default_preprocessing_hooks
  31. {
  32. public:
  33. ///////////////////////////////////////////////////////////////////////////
  34. //
  35. // The function 'emit_line_directive' is called whenever a #line directive
  36. // has to be emitted into the generated output.
  37. //
  38. // The parameter 'ctx' is a reference to the context object used for
  39. // instantiating the preprocessing iterators by the user.
  40. //
  41. // The parameter 'pending' may be used to push tokens back into the input
  42. // stream, which are to be used instead of the default output generated
  43. // for the #line directive.
  44. //
  45. // The parameter 'act_token' contains the actual #pragma token, which may
  46. // be used for error output. The line number stored in this token can be
  47. // used as the line number emitted as part of the #line directive.
  48. //
  49. // If the return value is 'false', a default #line directive is emitted
  50. // by the library. A return value of 'true' will inhibit any further
  51. // actions, the tokens contained in 'pending' will be copied verbatim
  52. // to the output.
  53. //
  54. ///////////////////////////////////////////////////////////////////////////
  55. template <typename ContextT, typename ContainerT>
  56. bool
  57. emit_line_directive(ContextT const& ctx, ContainerT &pending,
  58. typename ContextT::token_type const& act_token)
  59. {
  60. // emit a #line directive showing the relative filename instead
  61. typename ContextT::position_type pos = act_token.get_position();
  62. unsigned int column = 1;
  63. typedef typename ContextT::token_type result_type;
  64. using namespace boost::wave;
  65. pos.set_column(column);
  66. pending.push_back(result_type(T_POUND, "#", pos));
  67. pos.set_column(++column); // account for '#'
  68. pending.push_back(result_type(T_SPACE, " ", pos));
  69. // 21 is the max required size for a 64 bit integer represented as a
  70. // string
  71. char buffer[22];
  72. using namespace std; // for some systems sprintf is in namespace std
  73. sprintf (buffer, "%d", pos.get_line());
  74. pos.set_column(++column); // account for ' '
  75. pending.push_back(result_type(T_INTLIT, buffer, pos));
  76. pos.set_column(column += (unsigned int)strlen(buffer)); // account for <number>
  77. pending.push_back(result_type(T_SPACE, " ", pos));
  78. pos.set_column(++column); // account for ' '
  79. std::string file("\"");
  80. boost::filesystem::path filename(
  81. boost::wave::util::create_path(ctx.get_current_relative_filename().c_str()));
  82. using boost::wave::util::impl::escape_lit;
  83. file += escape_lit(boost::wave::util::native_file_string(filename)) + "\"";
  84. pending.push_back(result_type(T_STRINGLIT, file.c_str(), pos));
  85. pos.set_column(column += (unsigned int)file.size()); // account for filename
  86. pending.push_back(result_type(T_GENERATEDNEWLINE, "\n", pos));
  87. return true;
  88. }
  89. };
  90. #endif // !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)