#include #include #include #include #include #include #include #define CONDITIONALS #undef CONDITIONALS struct James : public boost::wave::context_policies::default_preprocessing_hooks { typedef boost::wave::cpplexer::lex_token<> token_type; std::list< token_type > tokens; token_type last_directive; James() : tokens() , last_directive() { } // general hook functions template bool found_directive(ContextT const &ctx, TokenT const &directive) { std::cout << __FUNCTION__ << std::endl; using namespace boost::wave; token_id id = token_id(directive); last_directive = directive; switch(id) { case T_PP_DEFINE: std::cout << "Directive is: #define\n"; break; case T_PP_IF: std::cout << "Directive is: #if\n"; break; case T_PP_IFDEF: std::cout << "Directive is: #ifdef\n"; break; case T_PP_IFNDEF: std::cout << "Directive is: #ifndef\n"; break; case T_PP_ELSE: std::cout << "Directive is: #else\n"; case T_PP_ELIF: std::cout << "Directive is: #elif\n"; break; case T_PP_ENDIF: std::cout << "Directive is: #endif\n"; break; case T_PP_ERROR: std::cout << "Directive is: #error\n"; break; case T_PP_LINE: std::cout << "Directive is: #line\n"; break; case T_PP_PRAGMA: std::cout << "Directive is: #pragma\n"; break; case T_PP_UNDEF: std::cout << "Directive is: #undef\n"; break; case T_PP_WARNING: std::cout << "Directive is: #warning\n"; break; case T_PP_INCLUDE: std::cout << "Directive is: #include \"...\"\n"; break; case T_PP_QHEADER: std::cout << "Directive is: #include <...>\n"; break; case T_PP_HHEADER: std::cout << "Directive is: #include ...\n"; break; default: std::cout << "Directive is: \n"; break; } tokens.push_back(directive); #ifdef CONDITIONALS return false; #else // tokens.push_back(token_type(boost::wave::T_NEWLINE, "\n", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(), 0, 0))); return true; #endif } template void throw_exception(ContextT const &ctx, ExceptionT const& e) { std::cout << __FUNCTION__ << std::endl; } // test, whether a given token may be skipped template bool may_skip_whitespace (ContextT const& ctx, TokenT &token, bool &skipped_newline) { std::cout << __FUNCTION__ << std::endl; using namespace boost::wave; if (token == last_directive) return false; token_id id = token_id(token); if (id != T_EOF && id != T_EOI) { tokens.push_back(token); std::cout << " bool evaluated_conditional_expression( ContextT const &ctx, TokenT const& directive, ContainerT const& expression, bool expression_value) { std::cout << __FUNCTION__ << std::endl; using namespace boost::wave; std::cout << "...if: "; token_type whitespace = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(), 0, 0)); tokens.push_back(whitespace); BOOST_FOREACH(token_type token, expression) { token_type whitespace = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(), 0, 0)); tokens.push_back(whitespace); std::cout << token.get_value().c_str(); tokens.push_back(token); } token_type comment = token_type(boost::wave::T_CPPCOMMENT, expression_value ? " // [Taken]\n" : " // [Not Taken]\n", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(), 0, 0)); tokens.push_back(comment); std::cout << std::endl; return false; } template void skipped_token(ContextT const &ctx, TokenT const& token) { std::cout << __FUNCTION__ << std::endl; using namespace boost::wave; if (token != last_directive) { tokens.push_back(token); } std::cout << "< " << token.get_value().c_str() << std::endl; } template TokenT const& generated_token(ContextT const &ctx, TokenT const& token) { std::cout << __FUNCTION__ << std::endl; return token; } // macro expansion tracing template < typename ContextT, typename TokenT, typename ContainerT, typename IteratorT > bool expanding_function_like_macro( ContextT const &ctx, TokenT const ¯odef, std::vector const &formal_args, ContainerT const &definition, TokenT const ¯ocall, std::vector const &arguments, IteratorT const &seqstart, IteratorT const &seqend) { std::cout << __FUNCTION__ << std::endl; return false; } template bool expanding_object_like_macro( ContextT const &ctx, TokenT const ¯o, ContainerT const &definition, TokenT const ¯ocall) { std::cout << __FUNCTION__ << std::endl; return false; } template void expanded_macro(ContextT const &ctx, ContainerT const &result) { std::cout << __FUNCTION__ << std::endl; } template void rescanned_macro(ContextT const &ctx, ContainerT const &result) { std::cout << __FUNCTION__ << std::endl; } // include file tracing functions template bool found_include_directive(ContextT const &ctx, std::string const &filename, bool include_next) { std::cout << __FUNCTION__ << std::endl; return false; } template void opened_include_file(ContextT const &ctx, std::string const &relname, std::string const& absname, bool is_system_include) { std::cout << __FUNCTION__ << std::endl; } template void returning_from_include_file(ContextT const &ctx) { std::cout << __FUNCTION__ << std::endl; } template void detected_include_guard(ContextT const &ctx, std::string const& filename, std::string const& include_guard) { std::cout << __FUNCTION__ << std::endl; } template void detected_pragma_once(ContextT const &ctx, TokenT const& pragma_token, std::string const& filename) { std::cout << __FUNCTION__ << std::endl; } // interpretation of #pragma's of the form // 'wave option[(value)]' template bool interpret_pragma(ContextT const &ctx, ContainerT &pending, typename ContextT::token_type const &option, ContainerT const &values, typename ContextT::token_type const &pragma_token) { std::cout << __FUNCTION__ << std::endl; return true; } // macro definition hooks template < typename ContextT, typename TokenT, typename ParametersT, typename DefinitionT > void defined_macro(ContextT const &ctx, TokenT const &name, bool is_functionlike, ParametersT const ¶meters, DefinitionT const &definition, bool is_predefined) { std::cout << __FUNCTION__ << std::endl; } template void undefined_macro(ContextT const &ctx, TokenT const &name) { std::cout << __FUNCTION__ << std::endl; } // #error and #warning directive hooks template bool found_warning_directive(ContextT const &ctx, ContainerT const &message) { std::cout << __FUNCTION__ << std::endl; return false; } template bool found_error_directive(ContextT const &ctx, ContainerT const &message) { std::cout << __FUNCTION__ << std::endl; return false; } // #line directive hook template void found_line_directive(ContextT const &ctx, ContainerT const &arguments, unsigned int line, std::string const& filename) { std::cout << __FUNCTION__ << std::endl; } }; int main() { // The following preprocesses a given input file. // Open the file and read it into a string variable const std::string inputfilename("input_minimal.cxx"); std::ifstream instream(inputfilename.c_str()); // std::ifstream instream = cin; std::string input( std::istreambuf_iterator(instream.rdbuf()), std::istreambuf_iterator()); // The template boost::wave::cpplexer::lex_token<> is the // token type to be used by the Wave library. // This token type is one of the central types throughout // the library, because it is a template parameter to some // of the public classes and templates and it is returned // from the iterators. // The template boost::wave::cpplexer::lex_iterator<> is // the lexer iterator to use as the token source for the // preprocessing engine. In this case this is parametrized // with the token type. typedef boost::wave::cpplexer::lex_token<> token_type; typedef boost::wave::cpplexer::lex_iterator< token_type > lex_iterator_type; typedef boost::wave::context< std::string::iterator, lex_iterator_type, boost::wave::iteration_context_policies::load_file_to_string, James > context_type; context_type ctx(input.begin(), input.end(), inputfilename.c_str()); // At this point you may want to set the parameters of the // preprocessing as include paths and/or predefined macros. // ctx.add_include_path("..."); // ctx.add_macro_definition(...); #if 0 if( sageFilePtr->get_C_only() == true){ // Tentaive support for C. For now treat it like C99 since Wave does not // have an option for just C. ctx.set_language(boost::wave::support_c99); }else if( sageFilePtr->get_C99_only() == true ){ ctx.set_language(boost::wave::support_c99); }else{ ctx.set_language(boost::wave::support_cpp); } #else // ctx.set_language(boost::wave::support_c99); ctx.set_language(boost::wave::support_cpp); #endif std::cout << "< settings >" << std::endl; ctx.set_language(boost::wave::enable_long_long(ctx.get_language())); ctx.set_language(boost::wave::enable_preserve_comments(ctx.get_language())); ctx.set_language(boost::wave::enable_variadics(ctx.get_language())); // Force a specific file to be included before all others #if 0 if( sageFilePtr->get_C_only() == true){ // Tentaive support for C. For now treat it like C99 since Wave does not // have an option for just C. ctx.add_macro_definition(std::string("ROSE_LANGUAGE_MODE=0"),true); }else if( sageFilePtr->get_C99_only() == true ){ ctx.add_macro_definition(std::string("ROSE_LANGUAGE_MODE=0"),true); }else{ ctx.add_macro_definition(std::string("ROSE_LANGUAGE_MODE=1"),true); } #endif std::cout << "< /settings >" << std::endl; // Get the preprocessor iterators and use them to generate // the token sequence. context_type::iterator_type first = ctx.begin(); context_type::iterator_type last = ctx.end(); // The input stream is preprocessed for you during iteration // over [first, last) std::cout << "< iterating >" << std::endl; while (first != last) { // std::cout << "> " << (*first).get_value(); // std::cout << (*first).get_value(); std::cout << "[" << (*first).get_value() << "]"; ++first; } std::cout << "< /iterating >" << std::endl; std::cout << std::endl << "FILE" << std::endl; BOOST_FOREACH(James::token_type tok, ctx.get_hooks().tokens) { std::cout << tok.get_value().c_str(); } }