Program Listing for File advanced_preprocessing_hooks.h

Program Listing for File advanced_preprocessing_hooks.h#

↰ Return to documentation for file (src/frontend/SageIII/advanced_preprocessing_hooks.h)

/*=============================================================================
    Boost.Wave: A Standard compliant C++ preprocessor library
    http://www.boost.org/

    Copyright (c) 2001-2005 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(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
#define BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED

// ROSE standard include files

#include <cstdio>
#include <ostream>
#include <string>

#include <boost/assert.hpp>
#include <boost/config.hpp>

#include <boost/wave/token_ids.hpp>
#include <boost/wave/util/macro_helpers.hpp>
#include <boost/wave/preprocessing_hooks.hpp>

#include "attributeListMap.h"

#define ROSE_WAVE_PSEUDO_FILE "<rose wave fix>"

#if 0
namespace {

    char const *get_directivename(boost::wave::token_id id)
    {
        using namespace boost::wave;
        switch (static_cast<unsigned int>(id)) {
        case T_PP_IFDEF:          return "#ifdef";
        case T_PP_IFNDEF:         return "#ifndef";
        case T_PP_IF:             return "#if";
        case T_PP_ELSE:           return "#else";
        case T_PP_ELIF:           return "#elif";
        case T_PP_ENDIF:          return "#endif";
        default:
            return "#unknown directive";
        }
    }
}

#endif

//
//  The advanced_preprocessing_hooks policy class is used to register some
//  of the more advanced (and probably more rarely used hooks with the Wave
//  library.
//
//  This policy type is used as a template parameter to the boost::wave::context<>
//  object.
//
//template<typename ContextT>
class advanced_preprocessing_hooks
:   public boost::wave::context_policies::default_preprocessing_hooks
{

public:
    AttributeListMap* attributeListMap;
        std::list< token_type > tokens;

    token_type lastPreprocDirective;
    int numberOfIfs;

    std::string includeDirective;
    token_type includeDirectiveToken;
        bool skipping;
        bool updatingLastToken;
        token_type last_token;
    advanced_preprocessing_hooks()
                : attributeListMap(NULL)
                , tokens()
                , lastPreprocDirective()
                , numberOfIfs(0)
                , includeDirective()
                , skipping(false)
                , updatingLastToken(false)
        { }



       //
       //Note from AS:
       //The typename ContainerT is often equivalent to list<TokenT>.
       //TokentT is often equivalent to  boost::wave::cpplexer::lex_token<>
       //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
       //




    //
    //  The function 'expanding_function_like_macro' is called, whenever a
    //  function-like macro is to be expanded.
    //
    //  The macroname parameter marks the position, where the macro to expand
    //  is defined.
    //  The formal_args parameter holds the formal arguments used during the
    //  definition of the macro.
    //  The definition parameter holds the macro definition for the macro to
    //  trace.
    //
    //  The macro call parameter marks the position, where this macro invoked.
    //  The arguments parameter holds the macro arguments used during the
    //  invocation of the macro
    //

    template <typename ContextT, typename TokenT, typename ContainerT, typename IteratorT>
    bool expanding_function_like_macro(ContextT const& ctx,
        TokenT const& macrodef, std::vector<TokenT> const& formal_args,
        ContainerT const& definition,
        TokenT const& macrocall, std::vector<ContainerT> const& arguments,
        IteratorT const& seqstart, IteratorT const& seqend)
    {
       //
       //Note from AS:
       //The typename ContainerT is often equivalent to list<TokenT>.
       //TokentT is often equivalent to  boost::wave::cpplexer::lex_token<>
       //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
       //

       attributeListMap->expanding_function_like_macro(macrodef, formal_args, definition, macrocall, arguments);

      return false;
    }

    //
    //  The function 'expanding_object_like_macro' is called, whenever a
    //  object-like macro is to be expanded .
    //
    //  The macroname parameter marks the position, where the macro to expand
    //  is defined.
    //  The definition parameter holds the macro definition for the macro to
    //  trace.
    //
    //  The macro call parameter marks the position, where this macro invoked.
    //

    template <typename ContextT, typename TokenT, typename ContainerT>
    bool expanding_object_like_macro(ContextT const& ctx, TokenT const& macro,
        ContainerT const& definition, TokenT const& macrocall)
    {
        attributeListMap->expanding_object_like_macro(macro, definition, macrocall);
        return false;
    }

    //
    //  The function 'expanded_macro' is called, whenever the expansion of a
    //  macro is finished but before the rescanning process starts.
    //
    //  The parameter 'result' contains the token sequence generated as the
    //  result of the macro expansion.
    //
    template <typename ContextT, typename ContainerT>
    void expanded_macro(ContextT const& ctx, ContainerT const& result)
    {
       attributeListMap->expanded_macro(result);
    }

    //
    //  The function 'rescanned_macro' is called, whenever the rescanning of a
    //  macro is finished.
    //
    //  The parameter 'result' contains the token sequence generated as the
    //  result of the rescanning.
    //
    template <typename ContextT, typename ContainerT>
    void rescanned_macro(ContextT const& ctx, ContainerT const& result)
    {
        attributeListMap->rescanned_macro(result);
    }

    //
    //  The function 'found_include_directive' is called, whenever a #include
    //  directive was located.
    //
    //  The parameter 'filename' contains the (expanded) file name found after
    //  the #include directive. This has the format '<file>', '"file"' or
    //  'file'.
    //  The formats '<file>' or '"file"' are used for #include directives found
    //  in the preprocessed token stream, the format 'file' is used for files
    //  specified through the --force_include command line argument.
    //
    //  The parameter 'include_next' is set to true if the found directive was
    //  a #include_next directive and the BOOST_WAVE_SUPPORT_INCLUDE_NEXT
    //  preprocessing constant was defined to something != 0.
    //

    template <typename ContextT>
    bool
    found_include_directive(ContextT const& ctx, std::string const& filename,
        bool include_next)
    {
       if(SgProject::get_verbose() >= 1)
           std::cout << "Found include directive: " << filename << std::endl;

       includeDirective = filename;
       return false;
    }

    //
    //  The function 'opened_include_file' is called, whenever a file referred
    //  by an #include directive was successfully located and opened.
    //
    //  The parameter 'filename' contains the file system path of the
    //  opened file (this is relative to the directory of the currently
    //  processed file or a absolute path depending on the paths given as the
    //  include search paths).
    //
    //  The include_depth parameter contains the current include file depth.
    //
    //  The is_system_include parameter denotes, whether the given file was
    //  found as a result of a #include <...> directive.
    //
    template <typename ContextT>
    void
    opened_include_file(ContextT const& ctx, std::string const& relname,
        std::string const& absname, bool is_system_include)
    {

       if(SgProject::get_verbose() >= 1){
           std::cout << "openend include file relname: " << relname << " absname: " << absname << std::endl;
           std::cout << "it is connected to : " << includeDirective << std::endl;
       }
       attributeListMap->found_include_directive(includeDirectiveToken, relname, absname);
    }

    //
    //  The function 'returning_from_include_file' is called, whenever an
    //  included file is about to be closed after it's processing is complete.
    //
    // new signature
    template <typename ContextT>
    void
    returning_from_include_file(ContextT const& ctx)
    {}

    //
    //  The function 'interpret_pragma' is called, whenever a #pragma wave
    //  directive is found, which isn't known to the core Wave library.
    //
    //  The parameter 'ctx' is a reference to the context object used for
    //  instantiating the preprocessing iterators by the user.
    //
    //  The parameter 'pending' may be used to push tokens back into the input
    //  stream, which are to be used as the replacement text for the whole
    //  #pragma wave() directive.
    //
    //  The parameter 'option' contains the name of the interpreted pragma.
    //
    //  The parameter 'values' holds the values of the parameter provided to
    //  the pragma operator.
    //
    //  The parameter 'act_token' contains the actual #pragma token, which may
    //  be used for error output.
    //
    //  If the return value is 'false', the whole #pragma directive is
    //  interpreted as unknown and a corresponding error message is issued. A
    //  return value of 'true' signs a successful interpretation of the given
    //  #pragma.
    //
    template <typename ContextT, typename ContainerT>
    bool
    interpret_pragma(ContextT const &ctx, ContainerT &pending,
        typename ContextT::token_type const &option, ContainerT const &values,
        typename ContextT::token_type const &act_token)
    {
        return false;
    }

    //
    //  The function 'defined_macro' is called, whenever a macro was defined
    //  successfully.
    //
    //  The parameter 'name' is a reference to the token holding the macro name.
    //
    //  The parameter 'is_functionlike' is set to true, whenever the newly
    //  defined macro is defined as a function like macro.
    //
    //  The parameter 'parameters' holds the parameter tokens for the macro
    //  definition. If the macro has no parameters or if it is a object like
//  macro, then this container is empty.
    //
    //  The parameter 'definition' contains the token sequence given as the
    //  replacement sequence (definition part) of the newly defined macro.
    //
    //  The parameter 'is_predefined' is set to true for all macros predefined
    //  during the initialisation phase of the library.
    //
    template <typename ContextT, typename TokenT, typename ParametersT,
        typename DefinitionT>
    void
    defined_macro(ContextT const& ctx, TokenT const& macro_name,
        bool is_functionlike, ParametersT const& parameters,
        DefinitionT const& definition, bool is_predefined)
    {
#if 0
// The "#if 0" was already here, but I also commented these lines out because '{' and '}' do not balance otherwise. The
// unbalanced braces cause some problems for some tools (indenting, automatic enum detection, etc) [RPM 2010-10-11]
//       string name(macro_name.get_value().c_str());
//       //add all macros which is not a builtin macro to ROSE attribute
//       if(! (name.substr(0,2)=="__")
//            //&&(name.substr(name.length()-2,name.length())=="__"))
//        ){
//       //AS(041906) Filter out macros defined on the commandline as they are not
//       //part of a file and is therefore not interesting for macro-rewrapping.
#endif
       //if(is_predefined!=true)
       if( macro_name.get_position().get_file().size()!=0 )
           {
                   if( (macro_name.get_position().get_file()!="<built-in>") )
                   {
                          attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);

                   }
       }
           else
           {
                        attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
           }


                token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                tokens.push_back(space);
                tokens.push_back(macro_name);

                boost::wave::util::file_position_type filepos;
                if (
               macro_name.get_position().get_file().find("<default>") == std::string::npos &&
               macro_name.get_position().get_file().find("<built-in>") == std::string::npos &&
               macro_name.get_position().get_file().find("<command line>") == std::string::npos &&
               macro_name.get_position().get_file().find("rose_edg_required_macros_and_functions") == std::string::npos)
                        filepos = boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0);
                else
                        filepos = boost::wave::util::file_position_type(macro_name.get_position().get_file(), 0, 0);

                if (is_functionlike)
                {
                        token_type left = token_type(boost::wave::T_LEFTPAREN, "(", filepos);
                        tokens.push_back(left);
                        bool first = true;
                        for (typename ParametersT::const_iterator i = parameters.begin(); i != parameters.end(); ++i)
                        {
                                if (!first)
                                {
                                        token_type comma = token_type(boost::wave::T_COMMA, ",", filepos);
                                        tokens.push_back(comma);
                                }
                                tokens.push_back(*i);
                                first = false;
                        }
                        token_type right = token_type(boost::wave::T_RIGHTPAREN, ")", filepos);
                        tokens.push_back(right);
                }
                token_type space2 = token_type(boost::wave::T_SPACE, " ", filepos);
                tokens.push_back(space2);
                for (typename DefinitionT::const_iterator i = definition.begin(); i != definition.end(); ++i)
                {
                        token_type space = token_type(boost::wave::T_SPACE, " ", filepos);
                        tokens.push_back(space);
                        tokens.push_back(*i);
                }

    }


    //
    //  The function 'found_directive' is called, whenever a preprocessor
    //  directive was encountered, but before the corresponding action is
    //  executed.
    //
    //  The parameter 'directive' is a reference to the token holding the
    //  preprocessing directive.
    //
        template <typename ContextT, typename TokenT>
        bool
        found_directive(ContextT const& ctx, TokenT const& directive)
        {
                if(SgProject::get_verbose() >= 1)
                        std::cout << "found_directive!" << std::endl;

                skipping = false;
        lastPreprocDirective = directive;
        // print the commented conditional directives
        using namespace boost::wave;
        token_id id = token_id(directive);

                bool record = true;
                switch(id)
                {
                        case T_PP_LINE:    //#line
                        case T_PP_UNDEF:   //#undef
                        case T_PP_WARNING: //#warning
                        case T_PP_DEFINE:  //#define
                                record = false;
                                break; // handled via lastPreprocDirective in their own methods
                        case T_PP_IF:      //#if
                        case T_PP_IFDEF:   //#ifdef
                        case T_PP_IFNDEF:  //#ifndef
                        case T_PP_ELSE:    //#else
                        case T_PP_ELIF:    //#elif
                                break; // appended too as necessary in skipped_token and evaluated_conditional_expression
                        case T_PP_ENDIF:   //#endif
                        case T_PP_ERROR:   //#error
                        case T_PP_PRAGMA:  //#pragma
                        case T_PP_INCLUDE: //#include \"...\"
                                break;
                        case T_PP_QHEADER: //#include <...>
                        case T_PP_HHEADER: //#include ...
                                break;
                        default:           //<something else (" << directive.get_value() << ")>
                                break;
                }
                if (record)
                        attributeListMap->found_directive(directive);

                attributeListMap->flush_token_stream();
                updatingLastToken = true;

                if(SgProject::get_verbose() >= 1)
                {
                        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"; break;
                                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: <something else>\n"; break;
                        }
                }

                last_token = directive;
                tokens.push_back(directive);
                return false;
        }

        //
        //  The function 'generated_token' is called, whenever a token is about
        //  to be returned from the library
        //
        template <typename ContextT, typename TokenT>
        TokenT const& generated_token(ContextT const& ctx, TokenT const& token)
        {
                if(SgProject::get_verbose() >= 1)
                        std::cout << "Generating token: ";

                using namespace boost::wave;
                token_id id = token_id(token);

                if(SgProject::get_verbose() >= 1)
                {
                        switch(id)
                        {
                                case T_PP_DEFINE:    std::cout << "#define: "; break;
                                case T_PP_IF:        std::cout << "#if: "; break;
                                case T_PP_IFDEF:     std::cout << "#ifdef: "; break;
                                case T_PP_IFNDEF:    std::cout << "#ifndef: "; break;
                                case T_PP_ELSE:      std::cout << "#else: "; break;
                                case T_PP_ELIF:      std::cout << "#elif: "; break;
                                case T_PP_ENDIF:     std::cout << "#endif: "; break;
                                case T_PP_ERROR:     std::cout << "#error: "; break;
                                case T_PP_LINE:      std::cout << "#line: "; break;
                                case T_PP_PRAGMA:    std::cout << "#pragma: "; break;
                                case T_PP_UNDEF:     std::cout << "#undef: "; break;
                                case T_PP_WARNING:   std::cout << "#warning: "; break;
                                case T_PP_INCLUDE:   std::cout << "#include \"...\": "; break;
                                case T_PP_QHEADER:   std::cout << "#include <...>: "; break;
                                case T_PP_HHEADER:   std::cout << "#include ...: "; break;
                                default:             std::cout << "<something else (" << id << ")>: "; break;
                        }
//                 std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
                        if (token != token_type())
                                std::cout << token.get_value().c_str() << std::endl;
                }
                return token;
        }

        //
        //  The function 'evaluated_conditional_expression' is called, whenever a
        //  conditional preprocessing expression was evaluated (the expression
        //  given to a #if, #ifdef or #ifndef directive)
        //
        //  The parameter 'expression' holds the non-expanded token sequence
        //  comprising the evaluated expression.
        //
        //  The parameter expression_value contains the result of the evaluation of
        //  the expression in the current preprocessing context.
        //
        template <typename ContextT, typename TokenT, typename ContainerT>
        bool
        evaluated_conditional_expression(ContextT const& ctx, TokenT const& directive, ContainerT const& expression, bool expression_value)
        {
                using namespace boost::wave;
                token_id id = token_id(directive);

                ROSE_ASSERT(directive == lastPreprocDirective);

                if(SgProject::get_verbose() >= 1)
                {
                        std::cout << "Conditional: ";
                        switch(id)
                        {
                                case T_PP_DEFINE:    std::cout << "#define: "; break;
                                case T_PP_IF:        std::cout << "#if: "; break;
                                case T_PP_IFDEF:     std::cout << "#ifdef: "; break;
                                case T_PP_IFNDEF:    std::cout << "#ifndef: "; break;
                                case T_PP_ELSE:      std::cout << "#else: "; break;
                                case T_PP_ELIF:      std::cout << "#elif: "; break;
                                case T_PP_ENDIF:     std::cout << "#endif: "; break;
                                case T_PP_ERROR:     std::cout << "#error: "; break;
                                case T_PP_LINE:      std::cout << "#line: "; break;
                                case T_PP_PRAGMA:    std::cout << "#pragma: "; break;
                                case T_PP_UNDEF:     std::cout << "#undef: "; break;
                                case T_PP_WARNING:   std::cout << "#warning: "; break;
                                case T_PP_INCLUDE:   std::cout << "#include \"...\": "; break;
                                case T_PP_QHEADER:   std::cout << "#include <...>: "; break;
                                case T_PP_HHEADER:   std::cout << "#include ...: "; break;
                                default:             std::cout << "<something else (" << id << ")>: "; break;
                        }
//                 std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
                        std::cout << directive.get_value().c_str() << std::endl;
                }
                token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                token_container whitespace;
                whitespace.push_back(space);
                // directive was already given up in found_directive.  here we add to the expression
                attributeListMap->update_token(lastPreprocDirective, whitespace, expression_value);
                attributeListMap->update_token(lastPreprocDirective, expression, expression_value);

//              tokens.push_back(space);
                for (typename ContainerT::const_iterator i = expression.begin(); i != expression.end(); ++i)
                {
                        token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                        tokens.push_back(space);
                        tokens.push_back(*i);
                }

                token_type newline = token_type(boost::wave::T_NEWLINE, "\n", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                token_container whitespace2;
                whitespace2.push_back(newline);
                attributeListMap->update_token(lastPreprocDirective, whitespace2, expression_value);

                // King84 (2010.09.09):
                // Tell later guys to update the previous token as soon as we start skipping
                // This is important to associate conditions with skipped #elif directives
                updatingLastToken = true;

                last_token = directive;
                return false; // ok to continue, do not re-evaluate expression
        }

        //
        //  The function 'skipped_token' is called, whenever a token is about to be
        //  skipped due to a false preprocessor condition (code fragments to be
        //  skipped inside the not evaluated conditional #if/#else/#endif branches).
        //
        //  The parameter 'token' refers to the token to be skipped.
        //
        //
        template <typename ContextT, typename TokenT>
        void
        skipped_token(ContextT const& ctx, TokenT const& token)
        {
                using namespace boost::wave;
                //Process all tokens to be skipped except the ones without a filename,
                //e.g macro definitions from the commandline
                if (token.get_position().get_file().size() == 0)
                        return;
                if (token == last_token && token.get_position() == last_token.get_position())
                        return;

                token_id id = token_id(token);
                token_id lastid = token_id(lastPreprocDirective);
                if (lastPreprocDirective == token_type())
                {
                        attributeListMap->skipped_token(token);
                }
                else if (token != lastPreprocDirective)
                {
                        tokens.push_back(token);

                        if (id == T_NEWLINE) // if it's a newline, it's the end of the previous token not that trailing-slash linesare already taken into account by wave
                                updatingLastToken = false;

                        // This is if we have to associated skipped tokens with a previous token.  We do this for the last directive until we get a newline
                        if (updatingLastToken)
                        {
                                token_container tc;
                                tc.push_back(token);
                                if(SgProject::get_verbose() >= 1)
                                        std::cout << "Updating previous token (" << lastPreprocDirective.get_value().c_str() << ") with token " << token.get_value().c_str() << std::endl;
                                attributeListMap->update_token(lastPreprocDirective, tc, false);
                        }
                        else if (skipping || (lastid != T_PP_IF && lastid != T_PP_IFDEF && lastid != T_PP_IFNDEF && lastid != T_PP_ELIF)) // if we skipped the first newline
                        {
                                attributeListMap->skipped_token(token);
                        }
                }

                switch(id)
                {
                        case T_PP_DEFINE:
                        case T_PP_IF:
                        case T_PP_IFDEF:
                        case T_PP_IFNDEF:
                        case T_PP_ELSE:
                        case T_PP_ELIF:
                        case T_PP_ENDIF:
                        case T_PP_ERROR:
                        case T_PP_LINE:
                        case T_PP_PRAGMA:
                        case T_PP_UNDEF:
                        case T_PP_WARNING:
                        case T_PP_INCLUDE:
                        case T_PP_QHEADER:
                        case T_PP_HHEADER:
                                lastPreprocDirective = token; // since found_directive doesn't get called
                                break;
                        default:
                                break;
                }

                if(SgProject::get_verbose() >= 1)
                {
                        switch(id)
                        {
                                case T_PP_DEFINE:    std::cout << "Skipped: #define\n"; break;
                                case T_PP_IF:        std::cout << "Skipped: #if\n"; break;
                                case T_PP_IFDEF:     std::cout << "Skipped: #ifdef\n"; break;
                                case T_PP_IFNDEF:    std::cout << "Skipped: #ifndef\n"; break;
                                case T_PP_ELSE:      std::cout << "Skipped: #else\n"; break;
                                case T_PP_ELIF:      std::cout << "Skipped: #elif\n"; break;
                                case T_PP_ENDIF:     std::cout << "Skipped: #endif\n"; break;
                                case T_PP_ERROR:     std::cout << "Skipped: #error\n"; break;
                                case T_PP_LINE:      std::cout << "Skipped: #line\n"; break;
                                case T_PP_PRAGMA:    std::cout << "Skipped: #pragma\n"; break;
                                case T_PP_UNDEF:     std::cout << "Skipped: #undef\n"; break;
                                case T_PP_WARNING:   std::cout << "Skipped: #warning\n"; break;
                                case T_PP_INCLUDE:   std::cout << "Skipped: #include \"...\"\n"; break;
                                case T_PP_QHEADER:   std::cout << "Skipped: #include <...>\n"; break;
                                case T_PP_HHEADER:   std::cout << "Skipped: #include ...\n"; break;
                                default:             std::cout << "Skipped: <something else (" << token.get_value().c_str() << ")>\n"; break;
                        }
                        if (lastPreprocDirective != token_type())
                                std::cout << "\tskipping is " << skipping << "\tupdatingLastToken is " << updatingLastToken << "\tlastPreprocDirective is " << lastPreprocDirective.get_value().c_str() << std::endl;
                }
                skipping = true; // skipping lets us skip the extra newline that shows up after #if statements
                last_token = token;
        }

 //
 //  The function 'undefined_macro' is called, whenever a macro definition
 //  was removed successfully.
 //
 //  The parameter 'name' holds the name of the macro, which definition was
 //  removed.
 //
    template <typename ContextT, typename TokenT>
            void
            undefined_macro(ContextT const& ctx, TokenT const& macro_name)
               {
                 token_list_container tokListCont;
                 tokListCont.push_back(macro_name);
                 attributeListMap->found_directive(lastPreprocDirective,tokListCont, false);

                                token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                                tokens.push_back(space);
                                tokens.push_back(macro_name);
               }

#if 0
    template <typename ContainerT>
            void
            on_warning(ContainerT const& tokenStream)
               {
                 attributeListMap->found_directive(lastPreprocDirective,tokenStream, false);

                 std::cout << "ON TOKEN WARNING: " << boost::wave::util::impl::as_string(tokenStream) << std::endl;
               }
#endif

 //
 //  The function 'found_warning_directive' is called, will be called by the
 //  library, whenever a #warning directive is found.
 //
 //  The parameter 'ctx' is a reference to the context object used for
 //  instantiating the preprocessing iterators by the user.
 //
 //  The parameter 'message' references the argument token sequence of the
 //  encountered #warning directive.
 //
    template <typename ContextT, typename ContainerT>
            bool
            found_warning_directive(ContextT const& ctx, ContainerT const& message)
               {
                 attributeListMap->found_directive(lastPreprocDirective,message, false);

                 if(SgProject::get_verbose() >= 1)
                     std::cout << "ON TOKEN WARNING: " << boost::wave::util::impl::as_string(message) << std::endl;

              //Do not throw warning message
                 return true;
               }


 //
 //  The function 'found_line_directive' will be called by the library
 //  whenever a #line directive is found.
 //
 //  The parameter 'ctx' is a reference to the context object used for
 //  instantiating the preprocessing iterators by the user.
 //
 //  The parameter 'arguments' references the argument token sequence of the
 //  encountered #line directive.
 //
 //  The parameter 'line' contains the recognized line number from the #line
 //  directive.
 //
 //  The parameter 'filename' references the recognized file name from the
 //  #line directive (if there was one given).
 //
        template <typename ContextT, typename ContainerT>
        void
        found_line_directive(ContextT const& ctx, ContainerT const& arguments, unsigned int line, std::string const& filename)
        {
                std::string filenameString(filename.c_str());

                if (SgProject::get_verbose() >= 1)
                        std::cout << "On line found" << std::endl;
                /*
                token_list_container toexpand;
                std::copy(first, make_ref_transform_iterator(end, boost::wave::util::get_value),
                std::inserter(toexpand, toexpand.end()));
                */

                attributeListMap->found_directive(lastPreprocDirective,arguments, false);

                token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                token_container whitespace;
                whitespace.push_back(space);
                // directive was already given up in found_directive.  here we add to it the arguments
                attributeListMap->update_token(lastPreprocDirective, whitespace, false);
                attributeListMap->update_token(lastPreprocDirective, arguments, false);

//              tokens.push_back(space);
                for (typename ContainerT::const_iterator i = arguments.begin(); i != arguments.end(); ++i)
                {
                        token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
                        tokens.push_back(space);
                        tokens.push_back(*i);
                }
        }


        template <typename ContextT, typename TokenT>
        bool
        may_skip_whitespace(ContextT const& ctx, TokenT& token, bool& skipped_newline)
        {
                if (token == lastPreprocDirective && token.get_position() == lastPreprocDirective.get_position())
                        return false;
                if (token == last_token && token.get_position() == last_token.get_position())
                        return false;
                if (SgProject::get_verbose() >= 1)
                        if (token != TokenT())
                                std::cout << "MAX_SKIP_WHITESPACE: " << token.get_value().c_str() << std::endl;

                using namespace boost::wave;
                token_id id = token_id(token);
                if (id != T_EOF && id != T_EOI)
                        tokens.push_back(token);
                if (id != T_EOF && id != T_EOI && id != T_NEWLINE)
                {
                        if (SgProject::get_verbose() >= 1)
                                std::cout << "Normal reported" << std::endl;
                        attributeListMap->may_skip_whitespace(ctx, token, skipped_newline);
                }
                else if (skipping) // then we need to flush tokens
                {
                        if (SgProject::get_verbose() >= 1)
                                std::cout << "Skip leads to flushing" << std::endl;
                        attributeListMap->flush_token_stream();
                }
                else
                {
                        if (SgProject::get_verbose() >= 1)
                                std::cout << "EOF or newline leads to flushing" << std::endl;
                        attributeListMap->flush_token_stream();
                }
                return false;
        }

        template <typename ContextT, typename ExceptionT>
        void throw_exception(ContextT const &ctx, ExceptionT const& e)
        {
                if (SgProject::get_verbose() >= 1)
                        std::cout << "THROW_EXCEPTION" << std::endl;
        }

        template <typename ContextT>
        void detected_include_guard(ContextT const &ctx, std::string const& filename, std::string const& include_guard)
        {
                if (SgProject::get_verbose() >= 1)
                        std::cout << "DETECTED_INCLUDE_GUARD" << include_guard << " in file " << filename << std::endl;
        }

        template <typename ContextT, typename TokenT>
        void detected_pragma_once(ContextT const &ctx, TokenT const& pragma_token, std::string const& filename)
        {
                if (SgProject::get_verbose() >= 1)
                        std::cout << "DETECTED_PRAGMA_ONCE " << pragma_token.get_value() << " in file " << filename << std::endl;
        }

        template <typename ContextT, typename ContainerT>
        bool found_error_directive(ContextT const &ctx, ContainerT const &message)
        {
                if (SgProject::get_verbose() >= 1)
                        std::cout << "FOUND_ERROR_DIRECTIVE" << std::endl;
                return false;
        }


#if 0
                 bool need_comment;
#endif
};

#endif // !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)