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