advanced_preprocessing_hooks.h

Go to the documentation of this file.
00001 /*=============================================================================
00002     Boost.Wave: A Standard compliant C++ preprocessor library
00003     http://www.boost.org/
00004 
00005     Copyright (c) 2001-2005 Hartmut Kaiser. Distributed under the Boost
00006     Software License, Version 1.0. (See accompanying file
00007     LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
00008 =============================================================================*/
00009 
00010 #if !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
00011 #define BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED
00012 
00013 // ROSE standard include files
00014 
00015 #include <cstdio>
00016 #include <ostream>
00017 #include <string>
00018 
00019 #include <boost/assert.hpp>
00020 #include <boost/config.hpp>
00021 
00022 #include <boost/wave/token_ids.hpp>
00023 #include <boost/wave/util/macro_helpers.hpp>
00024 #include <boost/wave/preprocessing_hooks.hpp>
00025 
00026 #include "attributeListMap.h"
00027 
00028 #define ROSE_WAVE_PSEUDO_FILE "<rose wave fix>"
00029 
00030 #if 0
00031 namespace {
00032 
00033     char const *get_directivename(boost::wave::token_id id)
00034     {
00035         using namespace boost::wave;
00036         switch (static_cast<unsigned int>(id)) {
00037         case T_PP_IFDEF:          return "#ifdef";
00038         case T_PP_IFNDEF:         return "#ifndef";
00039         case T_PP_IF:             return "#if";
00040         case T_PP_ELSE:           return "#else";
00041         case T_PP_ELIF:           return "#elif";
00042         case T_PP_ENDIF:          return "#endif";
00043         default:
00044             return "#unknown directive";
00045         }
00046     }
00047 }
00048 
00049 #endif
00050 
00052 //  
00053 //  The advanced_preprocessing_hooks policy class is used to register some
00054 //  of the more advanced (and probably more rarely used hooks with the Wave
00055 //  library.
00056 //
00057 //  This policy type is used as a template parameter to the boost::wave::context<>
00058 //  object.
00059 //
00061 //template<typename ContextT>
00062 class advanced_preprocessing_hooks
00063 :   public boost::wave::context_policies::default_preprocessing_hooks
00064 {
00065 
00066 public:
00067     AttributeListMap* attributeListMap;
00068         std::list< token_type > tokens;
00069 
00070     token_type lastPreprocDirective;
00071     int numberOfIfs;
00072 
00073     std::string includeDirective;
00074     token_type includeDirectiveToken;    
00075         bool skipping;
00076         bool updatingLastToken;
00077         token_type last_token;
00078     advanced_preprocessing_hooks()
00079                 : attributeListMap(NULL)
00080                 , tokens()
00081                 , lastPreprocDirective()
00082                 , numberOfIfs(0)
00083                 , includeDirective()
00084                 , skipping(false)
00085                 , updatingLastToken(false)
00086         { }
00087 
00088     
00089     
00091        //
00092        //Note from AS:
00093        //The typename ContainerT is often equivalent to list<TokenT>.
00094        //TokentT is often equivalent to  boost::wave::cpplexer::lex_token<>
00095        //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
00096        //
00098 
00099 
00100  
00101 
00103     //  
00104     //  The function 'expanding_function_like_macro' is called, whenever a 
00105     //  function-like macro is to be expanded.
00106     //
00107     //  The macroname parameter marks the position, where the macro to expand 
00108     //  is defined.
00109     //  The formal_args parameter holds the formal arguments used during the
00110     //  definition of the macro.
00111     //  The definition parameter holds the macro definition for the macro to 
00112     //  trace.
00113     //
00114     //  The macro call parameter marks the position, where this macro invoked.
00115     //  The arguments parameter holds the macro arguments used during the 
00116     //  invocation of the macro
00117     //
00119 
00120     template <typename ContextT, typename TokenT, typename ContainerT, typename IteratorT>
00121     bool expanding_function_like_macro(ContextT const& ctx,
00122         TokenT const& macrodef, std::vector<TokenT> const& formal_args, 
00123         ContainerT const& definition,
00124         TokenT const& macrocall, std::vector<ContainerT> const& arguments,
00125         IteratorT const& seqstart, IteratorT const& seqend) 
00126     {
00128        //
00129        //Note from AS:
00130        //The typename ContainerT is often equivalent to list<TokenT>.
00131        //TokentT is often equivalent to  boost::wave::cpplexer::lex_token<>
00132        //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
00133        //
00135 
00136        attributeListMap->expanding_function_like_macro(macrodef, formal_args, definition, macrocall, arguments);
00137 
00138       return false; 
00139     }
00140 
00142     //  
00143     //  The function 'expanding_object_like_macro' is called, whenever a 
00144     //  object-like macro is to be expanded .
00145     //
00146     //  The macroname parameter marks the position, where the macro to expand 
00147     //  is defined.
00148     //  The definition parameter holds the macro definition for the macro to 
00149     //  trace.
00150     //
00151     //  The macro call parameter marks the position, where this macro invoked.
00152     //
00154 
00155     template <typename ContextT, typename TokenT, typename ContainerT>
00156     bool expanding_object_like_macro(ContextT const& ctx, TokenT const& macro, 
00157         ContainerT const& definition, TokenT const& macrocall)
00158     {
00159         attributeListMap->expanding_object_like_macro(macro, definition, macrocall);
00160         return false;
00161     }
00162 
00164     //  
00165     //  The function 'expanded_macro' is called, whenever the expansion of a 
00166     //  macro is finished but before the rescanning process starts.
00167     //
00168     //  The parameter 'result' contains the token sequence generated as the 
00169     //  result of the macro expansion.
00170     //
00172     template <typename ContextT, typename ContainerT>
00173     void expanded_macro(ContextT const& ctx, ContainerT const& result)
00174     {
00175        attributeListMap->expanded_macro(result);
00176     }
00177 
00179     //  
00180     //  The function 'rescanned_macro' is called, whenever the rescanning of a 
00181     //  macro is finished.
00182     //
00183     //  The parameter 'result' contains the token sequence generated as the 
00184     //  result of the rescanning.
00185     //
00187     template <typename ContextT, typename ContainerT>
00188     void rescanned_macro(ContextT const& ctx, ContainerT const& result)
00189     {
00190         attributeListMap->rescanned_macro(result);
00191     }
00192 
00194     //  
00195     //  The function 'found_include_directive' is called, whenever a #include
00196     //  directive was located.
00197     //
00198     //  The parameter 'filename' contains the (expanded) file name found after 
00199     //  the #include directive. This has the format '<file>', '"file"' or 
00200     //  'file'.
00201     //  The formats '<file>' or '"file"' are used for #include directives found 
00202     //  in the preprocessed token stream, the format 'file' is used for files
00203     //  specified through the --force_include command line argument.
00204     //
00205     //  The parameter 'include_next' is set to true if the found directive was
00206     //  a #include_next directive and the BOOST_WAVE_SUPPORT_INCLUDE_NEXT
00207     //  preprocessing constant was defined to something != 0.
00208     //
00210 
00211     template <typename ContextT>
00212     bool
00213     found_include_directive(ContextT const& ctx, std::string const& filename, 
00214         bool include_next) 
00215     {
00216        if(SgProject::get_verbose() >= 1)
00217            std::cout << "Found include directive: " << filename << std::endl;
00218 
00219        includeDirective = filename;
00220        return false;
00221     }
00222     
00224     //  
00225     //  The function 'opened_include_file' is called, whenever a file referred 
00226     //  by an #include directive was successfully located and opened.
00227     //
00228     //  The parameter 'filename' contains the file system path of the 
00229     //  opened file (this is relative to the directory of the currently 
00230     //  processed file or a absolute path depending on the paths given as the
00231     //  include search paths).
00232     //
00233     //  The include_depth parameter contains the current include file depth.
00234     //
00235     //  The is_system_include parameter denotes, whether the given file was 
00236     //  found as a result of a #include <...> directive.
00237     //  
00239     template <typename ContextT>
00240     void 
00241     opened_include_file(ContextT const& ctx, std::string const& relname, 
00242         std::string const& absname, bool is_system_include) 
00243     {
00244                                    
00245        if(SgProject::get_verbose() >= 1){
00246            std::cout << "openend include file relname: " << relname << " absname: " << absname << std::endl;
00247            std::cout << "it is connected to : " << includeDirective << std::endl;
00248        }
00249        attributeListMap->found_include_directive(includeDirectiveToken, relname, absname);
00250     }
00251     
00253     //  
00254     //  The function 'returning_from_include_file' is called, whenever an
00255     //  included file is about to be closed after it's processing is complete.
00256     //
00258     // new signature
00259     template <typename ContextT>
00260     void
00261     returning_from_include_file(ContextT const& ctx) 
00262     {}
00263 
00265     //  
00266     //  The function 'interpret_pragma' is called, whenever a #pragma wave 
00267     //  directive is found, which isn't known to the core Wave library. 
00268     //
00269     //  The parameter 'ctx' is a reference to the context object used for 
00270     //  instantiating the preprocessing iterators by the user.
00271     //
00272     //  The parameter 'pending' may be used to push tokens back into the input 
00273     //  stream, which are to be used as the replacement text for the whole 
00274     //  #pragma wave() directive.
00275     //
00276     //  The parameter 'option' contains the name of the interpreted pragma.
00277     //
00278     //  The parameter 'values' holds the values of the parameter provided to 
00279     //  the pragma operator.
00280     //
00281     //  The parameter 'act_token' contains the actual #pragma token, which may 
00282     //  be used for error output.
00283     //
00284     //  If the return value is 'false', the whole #pragma directive is 
00285     //  interpreted as unknown and a corresponding error message is issued. A
00286     //  return value of 'true' signs a successful interpretation of the given 
00287     //  #pragma.
00288     //
00290     template <typename ContextT, typename ContainerT>
00291     bool 
00292     interpret_pragma(ContextT const &ctx, ContainerT &pending, 
00293         typename ContextT::token_type const &option, ContainerT const &values, 
00294         typename ContextT::token_type const &act_token)
00295     {
00296         return false;
00297     }
00298     
00300     //
00301     //  The function 'defined_macro' is called, whenever a macro was defined
00302     //  successfully.
00303     //
00304     //  The parameter 'name' is a reference to the token holding the macro name.
00305     //
00306     //  The parameter 'is_functionlike' is set to true, whenever the newly 
00307     //  defined macro is defined as a function like macro.
00308     //
00309     //  The parameter 'parameters' holds the parameter tokens for the macro
00310     //  definition. If the macro has no parameters or if it is a object like
00311 //  macro, then this container is empty.
00312     //
00313     //  The parameter 'definition' contains the token sequence given as the
00314     //  replacement sequence (definition part) of the newly defined macro.
00315     //
00316     //  The parameter 'is_predefined' is set to true for all macros predefined 
00317     //  during the initialisation phase of the library.
00318     //
00320     template <typename ContextT, typename TokenT, typename ParametersT, 
00321         typename DefinitionT>
00322     void
00323     defined_macro(ContextT const& ctx, TokenT const& macro_name, 
00324         bool is_functionlike, ParametersT const& parameters, 
00325         DefinitionT const& definition, bool is_predefined)
00326     {
00327 #if 0
00328 // The "#if 0" was already here, but I also commented these lines out because '{' and '}' do not balance otherwise. The
00329 // unbalanced braces cause some problems for some tools (indenting, automatic enum detection, etc) [RPM 2010-10-11]
00330 //       string name(macro_name.get_value().c_str());
00331 //       //add all macros which is not a builtin macro to ROSE attribute
00332 //       if(! (name.substr(0,2)=="__")
00333 //            //&&(name.substr(name.length()-2,name.length())=="__"))
00334 //        ){
00335 //       //AS(041906) Filter out macros defined on the commandline as they are not
00336 //       //part of a file and is therefore not interesting for macro-rewrapping.
00337 #endif
00338        //if(is_predefined!=true)
00339        if( macro_name.get_position().get_file().size()!=0 )
00340            {
00341                    if( (macro_name.get_position().get_file()!="<built-in>") )
00342                    {
00343                           attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
00344 
00345                    }
00346        }
00347            else
00348            {
00349                         attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
00350            }
00351 
00352 
00353                 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
00354                 tokens.push_back(space);
00355                 tokens.push_back(macro_name);
00356 
00357                 boost::wave::util::file_position_type filepos;
00358                 if (
00359                macro_name.get_position().get_file().find("<default>") == std::string::npos && 
00360                macro_name.get_position().get_file().find("<built-in>") == std::string::npos && 
00361                macro_name.get_position().get_file().find("<command line>") == std::string::npos && 
00362                macro_name.get_position().get_file().find("rose_edg_required_macros_and_functions") == std::string::npos)
00363                         filepos = boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0);
00364                 else
00365                         filepos = boost::wave::util::file_position_type(macro_name.get_position().get_file(), 0, 0);
00366 
00367                 if (is_functionlike)
00368                 {
00369                         token_type left = token_type(boost::wave::T_LEFTPAREN, "(", filepos);
00370                         tokens.push_back(left);
00371                         bool first = true;
00372                         for (typename ParametersT::const_iterator i = parameters.begin(); i != parameters.end(); ++i)
00373                         {
00374                                 if (!first)
00375                                 {
00376                                         token_type comma = token_type(boost::wave::T_COMMA, ",", filepos);
00377                                         tokens.push_back(comma);
00378                                 }
00379                                 tokens.push_back(*i);
00380                                 first = false;
00381                         }
00382                         token_type right = token_type(boost::wave::T_RIGHTPAREN, ")", filepos);
00383                         tokens.push_back(right);
00384                 }
00385                 token_type space2 = token_type(boost::wave::T_SPACE, " ", filepos);
00386                 tokens.push_back(space2);
00387                 for (typename DefinitionT::const_iterator i = definition.begin(); i != definition.end(); ++i)
00388                 {
00389                         token_type space = token_type(boost::wave::T_SPACE, " ", filepos);
00390                         tokens.push_back(space);
00391                         tokens.push_back(*i);
00392                 }
00393 
00394     }
00395    
00396 
00398     //
00399     //  The function 'found_directive' is called, whenever a preprocessor 
00400     //  directive was encountered, but before the corresponding action is 
00401     //  executed.
00402     //
00403     //  The parameter 'directive' is a reference to the token holding the 
00404     //  preprocessing directive.
00405     //
00407         template <typename ContextT, typename TokenT>
00408         bool 
00409         found_directive(ContextT const& ctx, TokenT const& directive)
00410         {
00411                 if(SgProject::get_verbose() >= 1)
00412                         std::cout << "found_directive!" << std::endl;
00413 
00414                 skipping = false;
00415         lastPreprocDirective = directive;
00416         // print the commented conditional directives
00417         using namespace boost::wave;
00418         token_id id = token_id(directive);
00419 
00420                 bool record = true;
00421                 switch(id)
00422                 {
00423                         case T_PP_LINE:    //#line
00424                         case T_PP_UNDEF:   //#undef
00425                         case T_PP_WARNING: //#warning
00426                         case T_PP_DEFINE:  //#define
00427                                 record = false;
00428                                 break; // handled via lastPreprocDirective in their own methods
00429                         case T_PP_IF:      //#if
00430                         case T_PP_IFDEF:   //#ifdef
00431                         case T_PP_IFNDEF:  //#ifndef
00432                         case T_PP_ELSE:    //#else
00433                         case T_PP_ELIF:    //#elif
00434                                 break; // appended too as necessary in skipped_token and evaluated_conditional_expression
00435                         case T_PP_ENDIF:   //#endif
00436                         case T_PP_ERROR:   //#error
00437                         case T_PP_PRAGMA:  //#pragma
00438                         case T_PP_INCLUDE: //#include \"...\"
00439                                 break;
00440                         case T_PP_QHEADER: //#include <...>
00441                         case T_PP_HHEADER: //#include ...
00442                                 break;
00443                         default:           //<something else (" << directive.get_value() << ")>
00444                                 break;
00445                 }
00446                 if (record)
00447                         attributeListMap->found_directive(directive);
00448 
00449                 attributeListMap->flush_token_stream();
00450                 updatingLastToken = true;
00451 
00452                 if(SgProject::get_verbose() >= 1)
00453                 {
00454                         switch(id)
00455                         {
00456                                 case T_PP_DEFINE:    std::cout << "Directive is: #define\n"; break;
00457                                 case T_PP_IF:        std::cout << "Directive is: #if\n"; break;
00458                                 case T_PP_IFDEF:     std::cout << "Directive is: #ifdef\n"; break;
00459                                 case T_PP_IFNDEF:    std::cout << "Directive is: #ifndef\n"; break;
00460                                 case T_PP_ELSE:      std::cout << "Directive is: #else\n"; break;
00461                                 case T_PP_ELIF:      std::cout << "Directive is: #elif\n"; break;
00462                                 case T_PP_ENDIF:     std::cout << "Directive is: #endif\n"; break;
00463                                 case T_PP_ERROR:     std::cout << "Directive is: #error\n"; break;
00464                                 case T_PP_LINE:      std::cout << "Directive is: #line\n"; break;
00465                                 case T_PP_PRAGMA:    std::cout << "Directive is: #pragma\n"; break;
00466                                 case T_PP_UNDEF:     std::cout << "Directive is: #undef\n"; break;
00467                                 case T_PP_WARNING:   std::cout << "Directive is: #warning\n"; break;
00468                                 case T_PP_INCLUDE:   std::cout << "Directive is: #include \"...\"\n"; break;
00469                                 case T_PP_QHEADER:   std::cout << "Directive is: #include <...>\n"; break;
00470                                 case T_PP_HHEADER:   std::cout << "Directive is: #include ...\n"; break;
00471                                 default:             std::cout << "Directive is: <something else>\n"; break;
00472                         }
00473                 }
00474 
00475                 last_token = directive;
00476                 tokens.push_back(directive);
00477                 return false;
00478         }
00479 
00481         //
00482         //  The function 'generated_token' is called, whenever a token is about
00483         //  to be returned from the library
00484         //
00486         template <typename ContextT, typename TokenT>
00487         TokenT const& generated_token(ContextT const& ctx, TokenT const& token)
00488         {
00489                 if(SgProject::get_verbose() >= 1)
00490                         std::cout << "Generating token: ";
00491 
00492                 using namespace boost::wave;
00493                 token_id id = token_id(token);
00494 
00495                 if(SgProject::get_verbose() >= 1)
00496                 {
00497                         switch(id)
00498                         {
00499                                 case T_PP_DEFINE:    std::cout << "#define: "; break;
00500                                 case T_PP_IF:        std::cout << "#if: "; break;
00501                                 case T_PP_IFDEF:     std::cout << "#ifdef: "; break;
00502                                 case T_PP_IFNDEF:    std::cout << "#ifndef: "; break;
00503                                 case T_PP_ELSE:      std::cout << "#else: "; break;
00504                                 case T_PP_ELIF:      std::cout << "#elif: "; break;
00505                                 case T_PP_ENDIF:     std::cout << "#endif: "; break;
00506                                 case T_PP_ERROR:     std::cout << "#error: "; break;
00507                                 case T_PP_LINE:      std::cout << "#line: "; break;
00508                                 case T_PP_PRAGMA:    std::cout << "#pragma: "; break;
00509                                 case T_PP_UNDEF:     std::cout << "#undef: "; break;
00510                                 case T_PP_WARNING:   std::cout << "#warning: "; break;
00511                                 case T_PP_INCLUDE:   std::cout << "#include \"...\": "; break;
00512                                 case T_PP_QHEADER:   std::cout << "#include <...>: "; break;
00513                                 case T_PP_HHEADER:   std::cout << "#include ...: "; break;
00514                                 default:             std::cout << "<something else (" << id << ")>: "; break;
00515                         }
00516 //                 std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
00517                         if (token != token_type())
00518                                 std::cout << token.get_value().c_str() << std::endl;
00519                 }
00520                 return token;
00521         }
00522 
00524         //
00525         //  The function 'evaluated_conditional_expression' is called, whenever a 
00526         //  conditional preprocessing expression was evaluated (the expression
00527         //  given to a #if, #ifdef or #ifndef directive)
00528         //
00529         //  The parameter 'expression' holds the non-expanded token sequence
00530         //  comprising the evaluated expression.
00531         //
00532         //  The parameter expression_value contains the result of the evaluation of
00533         //  the expression in the current preprocessing context.
00534         //
00536         template <typename ContextT, typename TokenT, typename ContainerT>
00537         bool
00538         evaluated_conditional_expression(ContextT const& ctx, TokenT const& directive, ContainerT const& expression, bool expression_value)
00539         {
00540                 using namespace boost::wave;
00541                 token_id id = token_id(directive);
00542 
00543                 ROSE_ASSERT(directive == lastPreprocDirective);
00544 
00545                 if(SgProject::get_verbose() >= 1)
00546                 {
00547                         std::cout << "Conditional: ";
00548                         switch(id)
00549                         {
00550                                 case T_PP_DEFINE:    std::cout << "#define: "; break;
00551                                 case T_PP_IF:        std::cout << "#if: "; break;
00552                                 case T_PP_IFDEF:     std::cout << "#ifdef: "; break;
00553                                 case T_PP_IFNDEF:    std::cout << "#ifndef: "; break;
00554                                 case T_PP_ELSE:      std::cout << "#else: "; break;
00555                                 case T_PP_ELIF:      std::cout << "#elif: "; break;
00556                                 case T_PP_ENDIF:     std::cout << "#endif: "; break;
00557                                 case T_PP_ERROR:     std::cout << "#error: "; break;
00558                                 case T_PP_LINE:      std::cout << "#line: "; break;
00559                                 case T_PP_PRAGMA:    std::cout << "#pragma: "; break;
00560                                 case T_PP_UNDEF:     std::cout << "#undef: "; break;
00561                                 case T_PP_WARNING:   std::cout << "#warning: "; break;
00562                                 case T_PP_INCLUDE:   std::cout << "#include \"...\": "; break;
00563                                 case T_PP_QHEADER:   std::cout << "#include <...>: "; break;
00564                                 case T_PP_HHEADER:   std::cout << "#include ...: "; break;
00565                                 default:             std::cout << "<something else (" << id << ")>: "; break;
00566                         }
00567 //                 std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
00568                         std::cout << directive.get_value().c_str() << std::endl;
00569                 }
00570                 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
00571                 token_container whitespace;
00572                 whitespace.push_back(space);
00573                 // directive was already given up in found_directive.  here we add to the expression
00574                 attributeListMap->update_token(lastPreprocDirective, whitespace, expression_value);
00575                 attributeListMap->update_token(lastPreprocDirective, expression, expression_value);
00576 
00577 //              tokens.push_back(space);
00578                 for (typename ContainerT::const_iterator i = expression.begin(); i != expression.end(); ++i)
00579                 {
00580                         token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
00581                         tokens.push_back(space);
00582                         tokens.push_back(*i);
00583                 }
00584 
00585                 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));
00586                 token_container whitespace2;
00587                 whitespace2.push_back(newline);
00588                 attributeListMap->update_token(lastPreprocDirective, whitespace2, expression_value);
00589 
00590                 // King84 (2010.09.09):
00591                 // Tell later guys to update the previous token as soon as we start skipping
00592                 // This is important to associate conditions with skipped #elif directives
00593                 updatingLastToken = true; 
00594 
00595                 last_token = directive;
00596                 return false; // ok to continue, do not re-evaluate expression
00597         }
00598 
00600         //
00601         //  The function 'skipped_token' is called, whenever a token is about to be
00602         //  skipped due to a false preprocessor condition (code fragments to be
00603         //  skipped inside the not evaluated conditional #if/#else/#endif branches).
00604         //
00605         //  The parameter 'token' refers to the token to be skipped.
00606         //  
00607         //
00609         template <typename ContextT, typename TokenT>
00610         void
00611         skipped_token(ContextT const& ctx, TokenT const& token)
00612         {
00613                 using namespace boost::wave;
00614                 //Process all tokens to be skipped except the ones without a filename,
00615                 //e.g macro definitions from the commandline
00616                 if (token.get_position().get_file().size() == 0)
00617                         return;
00618                 if (token == last_token && token.get_position() == last_token.get_position())
00619                         return;
00620 
00621                 token_id id = token_id(token);
00622                 token_id lastid = token_id(lastPreprocDirective);
00623                 if (lastPreprocDirective == token_type())
00624                 {
00625                         attributeListMap->skipped_token(token);
00626                 }
00627                 else if (token != lastPreprocDirective)
00628                 {
00629                         tokens.push_back(token);
00630 
00631                         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
00632                                 updatingLastToken = false;
00633 
00634                         // 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
00635                         if (updatingLastToken)
00636                         {
00637                                 token_container tc;
00638                                 tc.push_back(token);
00639                                 if(SgProject::get_verbose() >= 1)
00640                                         std::cout << "Updating previous token (" << lastPreprocDirective.get_value().c_str() << ") with token " << token.get_value().c_str() << std::endl;
00641                                 attributeListMap->update_token(lastPreprocDirective, tc, false);
00642                         }
00643                         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
00644                         {
00645                                 attributeListMap->skipped_token(token);
00646                         }
00647                 }
00648 
00649                 switch(id)
00650                 {
00651                         case T_PP_DEFINE:
00652                         case T_PP_IF:
00653                         case T_PP_IFDEF:
00654                         case T_PP_IFNDEF:
00655                         case T_PP_ELSE:
00656                         case T_PP_ELIF:
00657                         case T_PP_ENDIF:
00658                         case T_PP_ERROR:
00659                         case T_PP_LINE:
00660                         case T_PP_PRAGMA:
00661                         case T_PP_UNDEF:
00662                         case T_PP_WARNING:
00663                         case T_PP_INCLUDE:
00664                         case T_PP_QHEADER:
00665                         case T_PP_HHEADER:
00666                                 lastPreprocDirective = token; // since found_directive doesn't get called
00667                                 break;
00668                         default:
00669                                 break;
00670                 }
00671 
00672                 if(SgProject::get_verbose() >= 1)
00673                 {
00674                         switch(id)
00675                         {
00676                                 case T_PP_DEFINE:    std::cout << "Skipped: #define\n"; break;
00677                                 case T_PP_IF:        std::cout << "Skipped: #if\n"; break;
00678                                 case T_PP_IFDEF:     std::cout << "Skipped: #ifdef\n"; break;
00679                                 case T_PP_IFNDEF:    std::cout << "Skipped: #ifndef\n"; break;
00680                                 case T_PP_ELSE:      std::cout << "Skipped: #else\n"; break;
00681                                 case T_PP_ELIF:      std::cout << "Skipped: #elif\n"; break;
00682                                 case T_PP_ENDIF:     std::cout << "Skipped: #endif\n"; break;
00683                                 case T_PP_ERROR:     std::cout << "Skipped: #error\n"; break;
00684                                 case T_PP_LINE:      std::cout << "Skipped: #line\n"; break;
00685                                 case T_PP_PRAGMA:    std::cout << "Skipped: #pragma\n"; break;
00686                                 case T_PP_UNDEF:     std::cout << "Skipped: #undef\n"; break;
00687                                 case T_PP_WARNING:   std::cout << "Skipped: #warning\n"; break;
00688                                 case T_PP_INCLUDE:   std::cout << "Skipped: #include \"...\"\n"; break;
00689                                 case T_PP_QHEADER:   std::cout << "Skipped: #include <...>\n"; break;
00690                                 case T_PP_HHEADER:   std::cout << "Skipped: #include ...\n"; break;
00691                                 default:             std::cout << "Skipped: <something else (" << token.get_value().c_str() << ")>\n"; break;
00692                         }
00693                         if (lastPreprocDirective != token_type())
00694                                 std::cout << "\tskipping is " << skipping << "\tupdatingLastToken is " << updatingLastToken << "\tlastPreprocDirective is " << lastPreprocDirective.get_value().c_str() << std::endl;
00695                 }
00696                 skipping = true; // skipping lets us skip the extra newline that shows up after #if statements
00697                 last_token = token;
00698         }
00699 
00701  //
00702  //  The function 'undefined_macro' is called, whenever a macro definition
00703  //  was removed successfully.
00704  //
00705  //  The parameter 'name' holds the name of the macro, which definition was
00706  //  removed.
00707  //
00709     template <typename ContextT, typename TokenT>
00710             void
00711             undefined_macro(ContextT const& ctx, TokenT const& macro_name)
00712                {
00713                  token_list_container tokListCont;
00714                  tokListCont.push_back(macro_name);
00715                  attributeListMap->found_directive(lastPreprocDirective,tokListCont, false);
00716 
00717                                 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
00718                                 tokens.push_back(space);
00719                                 tokens.push_back(macro_name);
00720                }
00721 
00722 #if 0
00723     template <typename ContainerT>
00724             void
00725             on_warning(ContainerT const& tokenStream)
00726                {
00727                  attributeListMap->found_directive(lastPreprocDirective,tokenStream, false);
00728 
00729                  std::cout << "ON TOKEN WARNING: " << boost::wave::util::impl::as_string(tokenStream) << std::endl;
00730                }
00731 #endif
00732 
00734  //
00735  //  The function 'found_warning_directive' is called, will be called by the
00736  //  library, whenever a #warning directive is found.
00737  //
00738  //  The parameter 'ctx' is a reference to the context object used for
00739  //  instantiating the preprocessing iterators by the user.
00740  //
00741  //  The parameter 'message' references the argument token sequence of the
00742  //  encountered #warning directive.
00743  //
00745     template <typename ContextT, typename ContainerT>
00746             bool
00747             found_warning_directive(ContextT const& ctx, ContainerT const& message)
00748                { 
00749                  attributeListMap->found_directive(lastPreprocDirective,message, false);
00750 
00751                  if(SgProject::get_verbose() >= 1)
00752                      std::cout << "ON TOKEN WARNING: " << boost::wave::util::impl::as_string(message) << std::endl;
00753 
00754               //Do not throw warning message
00755                  return true; 
00756                }
00757 
00758 
00760  //
00761  //  The function 'found_line_directive' will be called by the library
00762  //  whenever a #line directive is found.
00763  //
00764  //  The parameter 'ctx' is a reference to the context object used for 
00765  //  instantiating the preprocessing iterators by the user.
00766  //
00767  //  The parameter 'arguments' references the argument token sequence of the
00768  //  encountered #line directive.
00769  //
00770  //  The parameter 'line' contains the recognized line number from the #line
00771  //  directive.
00772  //
00773  //  The parameter 'filename' references the recognized file name from the 
00774  //  #line directive (if there was one given).
00775  //
00777         template <typename ContextT, typename ContainerT>
00778         void
00779         found_line_directive(ContextT const& ctx, ContainerT const& arguments, unsigned int line, std::string const& filename)
00780         {
00781                 std::string filenameString(filename.c_str());
00782 
00783                 if (SgProject::get_verbose() >= 1)
00784                         std::cout << "On line found" << std::endl;
00785                 /*
00786                 token_list_container toexpand;
00787                 std::copy(first, make_ref_transform_iterator(end, boost::wave::util::get_value),
00788                 std::inserter(toexpand, toexpand.end()));
00789                 */
00790 
00791                 attributeListMap->found_directive(lastPreprocDirective,arguments, false);
00792 
00793                 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
00794                 token_container whitespace;
00795                 whitespace.push_back(space);
00796                 // directive was already given up in found_directive.  here we add to it the arguments
00797                 attributeListMap->update_token(lastPreprocDirective, whitespace, false);
00798                 attributeListMap->update_token(lastPreprocDirective, arguments, false);
00799 
00800 //              tokens.push_back(space);
00801                 for (typename ContainerT::const_iterator i = arguments.begin(); i != arguments.end(); ++i)
00802                 {
00803                         token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
00804                         tokens.push_back(space);
00805                         tokens.push_back(*i);
00806                 }
00807         }
00808 
00809 
00810         template <typename ContextT, typename TokenT>
00811         bool
00812         may_skip_whitespace(ContextT const& ctx, TokenT& token, bool& skipped_newline)
00813         {
00814                 if (token == lastPreprocDirective && token.get_position() == lastPreprocDirective.get_position())
00815                         return false;
00816                 if (token == last_token && token.get_position() == last_token.get_position())
00817                         return false;
00818                 if (SgProject::get_verbose() >= 1)
00819                         if (token != TokenT())
00820                                 std::cout << "MAX_SKIP_WHITESPACE: " << token.get_value().c_str() << std::endl;
00821 
00822                 using namespace boost::wave;
00823                 token_id id = token_id(token);
00824                 if (id != T_EOF && id != T_EOI)
00825                         tokens.push_back(token);
00826                 if (id != T_EOF && id != T_EOI && id != T_NEWLINE)
00827                 {
00828                         if (SgProject::get_verbose() >= 1)
00829                                 std::cout << "Normal reported" << std::endl;
00830                         attributeListMap->may_skip_whitespace(ctx, token, skipped_newline);
00831                 }
00832                 else if (skipping) // then we need to flush tokens
00833                 {
00834                         if (SgProject::get_verbose() >= 1)
00835                                 std::cout << "Skip leads to flushing" << std::endl;
00836                         attributeListMap->flush_token_stream();
00837                 }
00838                 else
00839                 {
00840                         if (SgProject::get_verbose() >= 1)
00841                                 std::cout << "EOF or newline leads to flushing" << std::endl;
00842                         attributeListMap->flush_token_stream();
00843                 }
00844                 return false;
00845         }
00846 
00847         template <typename ContextT, typename ExceptionT>
00848         void throw_exception(ContextT const &ctx, ExceptionT const& e)
00849         {
00850                 if (SgProject::get_verbose() >= 1)
00851                         std::cout << "THROW_EXCEPTION" << std::endl;
00852         }
00853 
00854         template <typename ContextT>
00855         void detected_include_guard(ContextT const &ctx, std::string const& filename, std::string const& include_guard)
00856         {
00857                 if (SgProject::get_verbose() >= 1)
00858                         std::cout << "DETECTED_INCLUDE_GUARD" << include_guard << " in file " << filename << std::endl;
00859         }
00860 
00861         template <typename ContextT, typename TokenT>
00862         void detected_pragma_once(ContextT const &ctx, TokenT const& pragma_token, std::string const& filename)
00863         {
00864                 if (SgProject::get_verbose() >= 1)
00865                         std::cout << "DETECTED_PRAGMA_ONCE " << pragma_token.get_value() << " in file " << filename << std::endl;
00866         }
00867 
00868         template <typename ContextT, typename ContainerT>
00869         bool found_error_directive(ContextT const &ctx, ContainerT const &message)
00870         {
00871                 if (SgProject::get_verbose() >= 1)
00872                         std::cout << "FOUND_ERROR_DIRECTIVE" << std::endl;
00873                 return false;
00874         }
00875 
00876 
00877 #if 0
00878                  bool need_comment;
00879 #endif
00880 };
00881 
00882 #endif // !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
00883 

Generated on Wed May 16 06:17:52 2012 for ROSE by  doxygen 1.4.7