attributeListMap.h

Go to the documentation of this file.
00001 #ifndef  XYZ_ATTRIBUTE_LIST_MAP
00002 #define XYZ_ATTRIBUTE_LIST_MAP
00003 
00004 #define DEBUG_WAVE_ROSE_CONNECTION 1
00005 #define DEBUG_USE_ROSE_BOOST_WAVE_SUPPORT 1
00006 
00007 // DQ (11/30/2008): This will be defined within the header file system for ROSE.
00008 // #include <map>
00009 // Header files needed for ROSE
00010 
00012 //  Include Wave itself
00013 #ifndef _MSC_VER
00014 #include <boost/wave.hpp>
00015 #endif
00016 
00018 // Include the lexer stuff
00019 #include <boost/wave/cpplexer/cpp_lex_token.hpp>    // token class
00020 #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer class
00021 
00022 // DQ: I don't think this forward declaration is required...
00023 // class AttributeListMap;
00024 
00026 // Function queryFloatDoubleValExp()  finds all nodes with type 
00027 //      SgDoubleVal, SgLongDoubleVal or SgFloatVal
00029 NodeQuerySynthesizedAttributeType
00030 queryFloatDoubleValExp (SgNode * astNode);
00031 
00032 
00033 //class advanced_preprocessing_hooks;
00034 //#include "advanced_preprocessing_hooks.hpp"
00035 
00036 class AttributeListMap {
00037 
00038      private:
00039        //rescan_macro_status is a helper for extracting the corresponding expanded macro to a macro call from Wave. 
00040        //This variable makes it so that the complexity of the macro expansion process can be ignoredd while still
00041        //safely extracting the expanded string.
00042           int  rescan_macro_status;
00043           std::string macro_expand_filename;
00044        //If rescan_macro_status!=0 the variable macro_call_to_expand should point to the macro call which is expanded. If other macros are 
00045        //called as an argument or as part of the macro definition corresponding to the macro call this data is *not* inside this variable.
00046           PreprocessingInfo::rose_macro_call* macro_call_to_expand;
00047           token_container currentTokSeq;
00048 
00049        //For optimization and practical purposes a list of preprocessor attributes is created
00050        //for each file. Since the preprocessor does an auxiliary pass over the AST a map
00051        //is created mapping the filename to the ROSEAttributesList.
00052 
00053      public:
00054        //A map of a filename to an ROSEAttributesList. All preprocessingdirectives and macros found in a file will be put into this list.
00055           typedef  std::map<std::string,ROSEAttributesList*> attribute_map_type;
00056           attribute_map_type currentMapOfAttributes;
00057 
00058           token_container* skippedTokenStream;
00059 
00060        //A map over all macro definitions found and their corresponding {filename, line number} 
00061           std::map<std::pair<std::string,int>, PreprocessingInfo*> defMap;
00062 
00063   // DQ (4/13/2007): These were required to support holding literals as strings (not required as a result of Rama's work).
00064   // std::list<SgNode*> valueExpList;
00065   // DQ (4/13/2007): This is due to a bug in ROSE, or a misunderstanding about constant folded values and their source position information.
00066   // token_type lastOperator;
00067 
00068           AttributeListMap(SgFile* sageFilePtr);
00069 
00070           template <typename TokenT> bool found_include_directive(TokenT directive, std::string relname, std::string absname );
00071       
00072 
00073 
00075     //  The function
00076     //           found_directive(TokenT const&, ...)
00077     //  will register a preprocessor directive with an expression (e.g #if, #ifdef etc) and will attach it to the AST.
00078     //  
00080        template <typename TokenT, typename ContainerT>
00081                bool
00082                found_directive(TokenT const& directive, ContainerT const& expression, bool expression_value)
00083                   {
00084                  //Map between the wave preprocessorid to the ROSE preprocessorid
00085                     PreprocessingInfo::DirectiveType rose_typeid;
00086                     using namespace boost::wave;
00087                     token_id wave_typeid = token_id(directive);
00088 
00089                  //Translate from wave to rose type-id notation
00090 
00091                     switch(wave_typeid){
00092                          case T_PP_DEFINE:    //#define
00093                             rose_typeid = PreprocessingInfo::CpreprocessorDefineDeclaration;
00094                             break;
00095                          case T_PP_IFDEF:     //#ifdef
00096                             rose_typeid = PreprocessingInfo::CpreprocessorIfdefDeclaration;
00097                             break;
00098                          case T_PP_IFNDEF:    //#ifndef
00099                             rose_typeid = PreprocessingInfo::CpreprocessorIfndefDeclaration;
00100                             break;
00101                          case T_PP_IF:        //#if
00102                             rose_typeid = PreprocessingInfo::CpreprocessorIfDeclaration;
00103                             break;
00104                          case T_PP_ELIF:      //#elif
00105              // DQ (4/17/2008): Commented out to avoid fly-make interpreting as an error!
00106           // std::cout << "ELIF\n";
00107                             rose_typeid = PreprocessingInfo::CpreprocessorElifDeclaration;
00108                             break;
00109                          case T_PP_ELSE:      //#else
00110                             rose_typeid = PreprocessingInfo::CpreprocessorElseDeclaration;
00111                             break;
00112                          case T_PP_ENDIF:      //#endif
00113                             rose_typeid = PreprocessingInfo::CpreprocessorEndifDeclaration;
00114                             break;
00115                          case T_CPPCOMMENT:   //  // ... \n
00116                             rose_typeid = PreprocessingInfo::CplusplusStyleComment;
00117                             break;
00118                          case T_CCOMMENT:     
00119                             rose_typeid = PreprocessingInfo::C_StyleComment;
00120                             break;
00121                          case T_PP_ERROR:     //#error
00122                             rose_typeid = PreprocessingInfo::CpreprocessorErrorDeclaration;
00123                             break;
00124                          case T_PP_LINE:      //#line
00125                             rose_typeid = PreprocessingInfo::CpreprocessorLineDeclaration;
00126                             break;
00127                          case T_PP_UNDEF:     //#undef
00128                             rose_typeid = PreprocessingInfo::CpreprocessorUndefDeclaration;
00129                             break;
00130                          case T_PP_WARNING:   //#warning
00131                             rose_typeid = PreprocessingInfo::CpreprocessorWarningDeclaration;
00132                             break;
00133                          case T_PP_QHEADER:   //#include "..."
00134                          case T_PP_HHEADER:   //#include <...>
00135                          case T_PP_INCLUDE:   //#include "..."
00136                             if(SgProject::get_verbose() >= 1)
00137                                     std::cout << "Token to include directive: " << directive.get_value() << std::endl;        
00138                             rose_typeid = PreprocessingInfo::CpreprocessorIncludeDeclaration;
00139                             break;
00140                          case T_PP_PRAGMA:    //#pragma
00141                             // Part of the AST in ROSE. Do not handle it this way 
00142                             return false;
00143           // DQ (8/29/2009): Unreachable statement after "return" 
00144           // break; 
00145 
00146                          default:
00147                             // This case should not be reached 
00148                             ROSE_ASSERT(false==true);
00149                             rose_typeid  = PreprocessingInfo::CpreprocessorUnknownDeclaration;
00150                             break;
00151 
00152                     }
00153                     if(SgProject::get_verbose() >= 1){
00154 
00155                             std::cout << "THE FOUND DIRECTIVE IS: " << directive.get_value().c_str() << std::endl;
00156                             std::cout << "THE FOUND DEF IS: " << boost::wave::util::impl::as_string(expression) << std::endl;
00157                     }
00158                     // 
00159                     std::string filename(directive.get_position().get_file().c_str());
00160                     token_list_container tokListCont;
00161 
00162                     copy (expression.begin(), expression.end(),
00163                                     inserter(tokListCont, tokListCont.end()));
00164 
00165 
00166 
00167                     if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
00168                             currentMapOfAttributes[filename] = new ROSEAttributesList();
00169                     currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(directive,tokListCont,expression_value,rose_typeid,PreprocessingInfo::before)));
00170 
00171                  return false;
00172                   }
00173 
00174         // King84 (2010.09.09): Added to support getting arguments for conditionals which had been skipped
00175         template <typename TokenT, typename ContainerT>
00176         void
00177         update_token(TokenT const& token, ContainerT const& stream, bool expression_value)
00178         {
00179 //              typename TokenT::position_type::string_type filename(token.get_position().get_file().c_str());
00180                 std::string filename(token.get_position().get_file().c_str());
00181                 // ensure that the file exists
00182                 ROSE_ASSERT(currentMapOfAttributes.find(filename) != currentMapOfAttributes.end());
00183                 // get the list of attributes
00184                 std::vector<PreprocessingInfo*>& infos = currentMapOfAttributes.find(filename)->second->getList();
00185                 for(std::vector<PreprocessingInfo*>::reverse_iterator i = infos.rbegin(); i != infos.rend(); ++i)
00186                 {
00187                         // match this one
00188                         if ((*(*i)->get_token_stream())[0] == token && (*(*i)->get_token_stream())[0].get_position() == token.get_position())
00189                         {
00190                                 // TODO: something with expression_value once the PreprocessingInfo actually decides to start storing it
00191                                 for (typename ContainerT::const_iterator item = stream.begin(); item != stream.end(); ++item)
00192                                 {
00193                                         (*i)->push_back_token_stream(*item);
00194                                 }
00195                                 return;
00196                         }
00197                 }
00198                 ROSE_ASSERT(!"Token to update not found!");
00199         }
00200 
00201 
00203        //  The function
00204        //           found_directive(TokenT const&, ...)
00205        //  will register a preprocessor directive when it is found (e.g #define, #if, #endif etc) and will attach it to the AST.
00206        //  
00208 
00209        template <typename TokenT>
00210                void
00211                found_directive(TokenT const& directive)
00212                {
00213                        //Map between the wave preprocessorid to the ROSE preprocessorid
00214                        PreprocessingInfo::DirectiveType rose_typeid;
00215                        using namespace boost::wave;
00216                        token_id wave_typeid = token_id(directive);
00217 
00218 
00219                        //Translate from wave to rose type-id notation
00220                        switch(wave_typeid){
00221                                case T_PP_IFDEF:     //#ifdef
00222                                                 rose_typeid = PreprocessingInfo::CpreprocessorIfdefDeclaration;
00223                                                 break;
00224                                case T_PP_IFNDEF:    //#ifndef
00225                                                 rose_typeid = PreprocessingInfo::CpreprocessorIfndefDeclaration;
00226                                                 break;
00227                                case T_PP_IF:        //#if
00228                                                 rose_typeid = PreprocessingInfo::CpreprocessorIfDeclaration;
00229                                                 break;
00230                                        //These directive have expression attached to them and should be handled
00231                                        //by  found_directive(TokenT const& directive, ContainerT const& expression)
00232                                        ROSE_ASSERT(false); 
00233                                        break;
00234                                case T_PP_DEFINE:    //#define
00235                                        rose_typeid = PreprocessingInfo::CpreprocessorDefineDeclaration;
00236                                        break;
00237                                case T_PP_ELIF:      //#elif
00238                                        rose_typeid = PreprocessingInfo::CpreprocessorElifDeclaration;
00239                                        break;
00240                                case T_PP_ELSE:      //#else
00241                                        rose_typeid = PreprocessingInfo::CpreprocessorElseDeclaration;
00242                                        break;
00243                                case T_PP_ENDIF:      //#endif
00244                                        rose_typeid = PreprocessingInfo::CpreprocessorEndifDeclaration;
00245                                        break;
00246                                case T_CPPCOMMENT:   //  // ... \n
00247                                        rose_typeid = PreprocessingInfo::CplusplusStyleComment;
00248                                        break;
00249                                case T_CCOMMENT:     
00250                                        rose_typeid = PreprocessingInfo::C_StyleComment;
00251                                        break;
00252                                case T_PP_ERROR:     //#error
00253                                        rose_typeid = PreprocessingInfo::CpreprocessorErrorDeclaration;
00254                                        break;
00255                                case T_PP_LINE:      //#line
00256                                        rose_typeid = PreprocessingInfo::CpreprocessorLineDeclaration;
00257                                        break;
00258                                case T_PP_UNDEF:     //#undef
00259                                        rose_typeid = PreprocessingInfo::CpreprocessorUndefDeclaration;
00260                                        break;
00261                                case T_PP_WARNING:   //#warning
00262                                        rose_typeid = PreprocessingInfo::CpreprocessorWarningDeclaration;
00263                                        break;
00264                                case T_PP_QHEADER:   //#include "..."
00265                                case T_PP_HHEADER:   //#include <...>
00266                                case T_PP_INCLUDE:   //#include ...
00267                                        if(SgProject::get_verbose() >= 1)
00268                                                std::cout << "Token to include directive: " << directive.get_value() << std::endl;        
00269                                        rose_typeid = PreprocessingInfo::CpreprocessorIncludeDeclaration;
00270                                        break;
00271                                case boost::wave::T_PP_HHEADER_NEXT:
00272                                        if(SgProject::get_verbose() >= 1)
00273                                                std::cout << "Token to include next directive: " << directive.get_value() << std::endl;        
00274                                        rose_typeid = PreprocessingInfo::CpreprocessorIncludeNextDeclaration;
00275 
00276                                        break;
00277                                case T_PP_PRAGMA:    //#pragma
00278                                        // Part of the AST in ROSE. Do not handle it this way 
00279                                        return;
00280 
00281                 // DQ (8/29/2009): Unreachable statement after "return" 
00282                 // break; 
00283 
00284                                default:
00285                    {
00286                                       // This case should not be reached 
00287 
00288                   // DQ (8/29/2009): It is a horrible idea to only fail when verbose mode is turned on!
00289                                          if (SgProject::get_verbose() >= 1)
00290                         {
00291                           std::cout << "Error: Unknown preprocessor declaration found : " << directive.get_value().c_str() << std::endl;
00292                           std::cout << boost::wave::get_token_name(wave_typeid) << " " << directive.get_position().get_file().c_str() << " " << directive.get_position().get_line() 
00293                                     << " " << directive.get_position().get_column() << std::endl;
00294                           ROSE_ASSERT(false);
00295                         }
00296 
00297                      rose_typeid  = PreprocessingInfo::CpreprocessorUnknownDeclaration;
00298                      break;
00299                                        }
00300 
00301                        }
00302 
00303                        //std::cout << "THE FOUND DIRECTIVE IS: " << directive.get_value().c_str() << std::endl;
00304 
00305                        token_container currentTokSeq2;
00306                        currentTokSeq2.push_back(directive);
00307                        std::string filename(directive.get_position().get_file().c_str());
00308                        if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
00309                                currentMapOfAttributes[filename] = new ROSEAttributesList();
00310                        currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(currentTokSeq2,rose_typeid,PreprocessingInfo::before)));
00311 
00312 
00313                }
00314 
00315 
00316 
00318        //   The function
00319        //      PreprocessingInfo* build_preprocessingInfo_macro_def(TokenT&
00320        //                          macro_name, bool is_functionlike,..)
00321        //   will create a PreprocessingInfo object for a preprocessor
00322        //   defined macro definition. E.g
00323        //     #ifdef NOT_DEFINED_MACRO
00324        //     #endif
00326 
00327        template<typename TokenT, typename ParametersT, typename DefinitionT> 
00328                PreprocessingInfo* build_preprocessingInfo_macro_def(TokenT& macro_name, bool is_functionlike,
00329                                ParametersT& parameters, DefinitionT &definition, bool is_predefined){
00330 
00331                        PreprocessingInfo::rose_macro_definition* macro_def = new PreprocessingInfo::rose_macro_definition();
00332 
00333                        //Make copies of all the variables for ROSE 
00334                        macro_def->is_functionlike = is_functionlike;
00335                        macro_def->is_predefined   = is_predefined; 
00336 
00337                        macro_def->macro_name = macro_name;
00338                        macro_def->paramaters = parameters;
00339 
00340                        copy (definition.begin(), definition.end(),
00341                                        inserter(macro_def->definition, macro_def->definition.end()));
00342                        PreprocessingInfo* preprocMacroDef = new PreprocessingInfo(macro_def,PreprocessingInfo::before);
00343 
00344                        return preprocMacroDef;
00345                }
00346 
00348        //   The function 
00349        //               defined_macro<TokentT,ParametersT, DefinitionT>
00350        //   takes a macro definition as paramaters and convert it into a PreprocessingInfo object for the AST
00352        template<typename TokenT, typename ParametersT, typename DefinitionT> 
00353                void defined_macro(TokenT& macro_name, bool is_functionlike,
00354                                ParametersT& parameters, DefinitionT &definition, bool is_predefined){
00355                        if(skippedTokenStream != NULL){
00356 
00357                                if(macro_name.get_position().get_file().size()!=0){  
00358                                        if(macro_name.get_position().get_file()!="<built-in>") 
00359                                                skipped_token(macro_name,true);
00360                                }else if(SgProject::get_verbose() >= 1)
00361                                        std::cout << "SKIPPED BECAUSE FILE IS NULL: " << macro_name.get_value().c_str() << std::endl;
00362 
00363                        }
00364                        //All the information in the paramaters here comes from an  macro_definition object declared in boost/wave/utils/macro_defintion.hpp
00365                        //The real values of the typename which is found in this class is
00366                        //          typedef std::vector<TokenT> parameter_container_t;
00367                        //          typedef ContainerT          definition_container_t;
00368 
00369                        //From cpp_context
00370                        //DefinitionT is a ContextT::token_sequence_type which is the type of a token sequence defined in cpp_context
00371                        //    typedef std::list<token_type, boost::fast_pool_allocator<token_type> > token_sequence_type;
00372 
00373                        PreprocessingInfo* preprocMacroDef = build_preprocessingInfo_macro_def(macro_name, is_functionlike, parameters, definition, is_predefined);
00374                        ROSE_ASSERT(preprocMacroDef != NULL);
00375 
00376                        Sg_File_Info* file_info = preprocMacroDef->get_file_info();
00377                        ROSE_ASSERT(file_info != NULL);
00378 
00379                        std::string filename = file_info->get_filenameString();
00380 
00381                        //Make sure that the macro definition has been declared within a file
00382                        //and not on the commandline
00383                        ROSE_ASSERT(filename != "");
00384 
00385                        if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
00386                                currentMapOfAttributes[filename] = new ROSEAttributesList();
00387                        if(SgProject::get_verbose() >= 1)
00388                                std::cout << "DONE adding to map" << std::endl;
00389                        currentMapOfAttributes.find(filename)->second->addElement(*preprocMacroDef);
00390                        if(SgProject::get_verbose() >= 1)
00391                                std::cout << "Before mapKey" << std::endl;
00392                        //Insert the macro definition into the map of macro definitions (used for macro calls)
00393                        std::pair<std::string,int> mapKey(filename,macro_name.get_position().get_line());
00394                        if(SgProject::get_verbose() >= 1){
00395                                std::cout << "After mapKey" << std::endl;
00396 
00397                                std::cout << "ASXXX Defining macro: " << macro_name.get_value().c_str() << std::endl;
00398                                std::cout << "at " << filename << " l" << mapKey.second << std::endl;
00399                        }
00400 
00401                        //A macro can not be defined twice
00402                        //ROSE_ASSERT( defMap.find(mapKey) == defMap.end() );
00403                        //Although a macro can not be defined twice it is possible that a macro
00404                        //can be undefined and then defined again. Since we do not yet use the
00405                        //#undef information we should just consolidate those macro definitions
00406                        //into one macro
00407                        if( defMap.find(mapKey) == defMap.end() )
00408                                defMap[mapKey]=preprocMacroDef;
00409 
00410                }
00411 
00413        //   The function 
00414        //               addElement<TokentT,ContainerT>
00415        //   takes an expansion of a function like macro as paramater and convert it into a PreprocessingInfo::rose_macro_call object for the AST
00417        template<typename TokenT, typename ContainerT> 
00418                bool expanding_function_like_macro(TokenT const &macrodef, std::vector<TokenT> const &formal_args,
00419                                ContainerT const &definition, TokenT const &macrocall, std::vector<ContainerT> const &arguments){
00420                        if(skippedTokenStream != NULL)
00421                                skipped_token(macrodef,true);
00422 
00424                        //
00425                        //Note from AS:
00426                        //The typename ContainerT is often equivalent to list<TokenT>.
00427                        //TokentT is often equivalent to  boost::wave::cpplexer::lex_token<>
00428                        //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
00429                        //
00431                        //All the information in the paramaters here comes from an  macro_definition object declared in boost/wave/utils/macro_defintion.hpp
00432                        //The real values of the typename which is found in this class is
00433                        //          typedef std::vector<TokenT> parameter_container_t;
00434                        //          typedef ContainerT          definition_container_t;
00435 
00436                        //From cpp_context
00437                        //DefinitionT is a ContextT::token_sequence_type which is the type of a token sequence defined in cpp_context
00438                        //    typedef std::list<token_type, boost::fast_pool_allocator<token_type> > token_sequence_type;
00439 
00440                        if(rescan_macro_status==0){
00441 
00442                                if(SgProject::get_verbose() >= 1){
00443 
00444                                        std::cout << "DEFINITION: " << boost::wave::util::impl::as_string(definition);
00445 
00446                                        std::cout << "\n MACRO CALL: " << macrocall.get_value() << std::endl;
00447                                }
00448                                //have to implement mechanism to find macro definition here 
00449                                ROSE_ASSERT(macro_call_to_expand == NULL);
00450                                macro_call_to_expand = new PreprocessingInfo::rose_macro_call();
00451                                macro_call_to_expand->is_functionlike = true; 
00452                                macro_call_to_expand->macro_call      = macrocall;
00453 
00454                                //           std::pair<std::string,int> mapKey(string(definition.begin()->get_position().get_file().c_str()),
00455                                //                            definition.begin()->get_position().get_line());
00456 
00457                                std::pair<std::string,int> mapKey;
00458 
00459                                if(macrodef.get_position().get_file()!="<built-in>"){
00460                                        mapKey.first  =  string(macrodef.get_position().get_file().c_str());
00461                                        mapKey.second = macrodef.get_position().get_line();
00462                                        ROSE_ASSERT( defMap.find(mapKey) != defMap.end() );
00463                                        macro_call_to_expand->macro_def = defMap[mapKey];
00464                                        //     std::cout << definition.begin()->get_position().get_line() << std::endl;
00465 
00466                                }else{
00467                                        bool is_function_like = true;
00468                                        bool is_predefined    = false;
00469                                        macro_call_to_expand->macro_def = build_preprocessingInfo_macro_def(macrodef, is_function_like, formal_args, definition, is_predefined);
00470                                }
00471                                
00472                                if( (defMap.find(mapKey) == defMap.end())&&(SgProject::get_verbose() >= 1) ){
00473                                        std::cout << "Did not find: " <<  macrodef.get_value().c_str() <<  " " << boost::wave::util::impl::as_string(definition) << std::endl;
00474                                        std::cout << "in " << mapKey.first << " l " << mapKey.second << std::endl;
00475                                };
00476 
00477 
00478                                //       typedef typename std::vector<std::list<token_type,boost::fast_pool_allocator<token_type> > > testType;
00479                                typedef typename std::vector<ContainerT>::const_iterator vec_call_iterator_t;
00480 
00481                                //BEGIN: Make a copy of the arguments
00482 
00483                                vec_call_iterator_t it = arguments.begin();
00484                                vec_call_iterator_t it_end = arguments.end();
00485 
00486                                //extract the arguments in the macro call from wave    
00487 
00488                                //ARGUMENTS
00489                                if(SgProject::get_verbose() >= 1)
00490                                        std::cout << "ARGUMENTS:\n";
00491 
00492                                while (it != it_end ){
00493                                        if(SgProject::get_verbose() >= 1){
00494                                                std::cout << boost::wave::util::impl::as_string(*it);
00495                                        }
00496                                        std::list<token_type> tk;
00497 
00498                                        copy (it->begin(), it->end(),
00499                                                        inserter(tk, tk.end()));
00500 
00501                                        macro_call_to_expand->arguments.push_back(tk);
00502                                        ++it;
00503                                }
00504 
00505                                //END: Make a copy of the arguments
00506                        }
00507 
00508                        ++rescan_macro_status;
00509 
00510 
00511 #if 0
00512                        typename testType::iterator it2 = test.begin();
00513                        typename testType::iterator it_end2 = test.end();
00514 
00515                        while (it2 != it_end2 ){
00516                                std::cout<<  boost::wave::util::impl::as_string(*it2);
00517                                ++it2;
00518                        }
00519 #endif
00520                return false;        
00521 
00522                }
00523 
00525        //   The function 
00526        //               expanding_object_like_macro<TokentT,ContainerT>
00527        //   takes an expansion of a object like macro as paramater and convert it into a PreprocessingInfo::macr_call object for the AST
00528        //  The macroname parameter marks the position, where the macro to expand 
00529        //  is defined.
00530        //  The definition parameter holds the macro definition for the macro to 
00531        //  trace.
00532        //
00533        //  The macro call parameter marks the position, where this macro invoked.
00534        //
00536        template<typename TokenT, typename ContainerT> 
00537                bool expanding_object_like_macro(TokenT const &macro, ContainerT const &definition, TokenT const &macrocall){
00538                        if(skippedTokenStream != NULL)
00539                                skipped_token(macro,true);
00540 
00541                        //All the information in the paramaters here comes from an  macro_definition object declared in boost/wave/utils/macro_defintion.hpp
00542                        //The real values of the typename which is found in this class is
00543                        //          typedef std::vector<TokenT> parameter_container_t;
00544                        //          typedef ContainerT          definition_container_t;
00545 
00546                        //From cpp_context
00547                        //DefinitionT is a ContextT::token_sequence_type which is the type of a token sequence defined in cpp_context
00548                        //    typedef std::list<token_type, boost::fast_pool_allocator<token_type> > token_sequence_type;
00549 
00550                        //Put the macro_definition into the AST
00551 
00552                        //have to implement mechanism to find macro definition here 
00553 
00554                        if(rescan_macro_status==0){
00555                                ROSE_ASSERT(macro_call_to_expand == NULL);
00556                                if(SgProject::get_verbose() >= 1)
00557                                        std::cout << "DEFINITION: " << boost::wave::util::impl::as_string(definition);
00558 
00559                                macro_call_to_expand = new PreprocessingInfo::rose_macro_call();
00560 
00561                                macro_call_to_expand->is_functionlike = false;
00562                                macro_call_to_expand->macro_call      = macrocall;
00563 
00564                                std::pair<std::string,int> mapKey;
00565 
00566                                if( (macro.get_position().get_file().size() != 0 ) && (macro.get_position().get_file()!="<built-in>") 
00567                                    && (macro.get_position().get_file()!="<command line>") ){
00568                                        mapKey.first  = string(macro.get_position().get_file().c_str());
00569                                        mapKey.second = macro.get_position().get_line();
00570 
00571                                        if( defMap.find(mapKey) == defMap.end() ){
00572                                                std::cout << "Did not find: " <<  macro.get_value().c_str() << "  " << 
00573                                                        macrocall.get_value().c_str() <<  " " << boost::wave::util::impl::as_string(definition) << std::endl;
00574                                                std::cout << "in " << mapKey.first << " l " << mapKey.second << std::endl;
00575                                        };
00576 
00577                                        ROSE_ASSERT( defMap.find(mapKey) != defMap.end() );
00578                                        macro_call_to_expand->macro_def = defMap[mapKey];
00579                                        //                std::cout << definition.begin()->get_position().get_line() << std::endl;
00580 
00581                                }else{
00582 
00583                                        bool is_function_like = false;
00584                                        bool is_predefined    = false;
00585 
00586                                        token_container parameters;
00587                                        macro_call_to_expand->macro_def = build_preprocessingInfo_macro_def(macro, is_function_like, parameters, definition, is_predefined);
00588                                }
00589 
00590 
00591                                if(SgProject::get_verbose() >= 1)
00592                                        std::cout << "\n MACRO CALL: " << macrocall.get_value() << std::endl;
00593                        }
00594 
00595                        ++rescan_macro_status;
00596                 return false;
00597                }
00598 
00600        //  
00601        //  The function 'expanded_macro' is called, whenever the expansion of a 
00602        //  macro is finished but before the rescanning process starts.
00603        //
00604        //  The parameter 'result' contains the token sequence generated as the 
00605        //  result of the macro expansion.
00606        //
00608        template <typename ContainerT>
00609                void expanded_macro(ContainerT const &result)
00610                {
00611 
00612                }
00613 
00614 
00616        //  
00617        //  The function 'rescanned_macro' is called, whenever the rescanning of a 
00618        //  macro is finished. It connects the macro_call and expanded macro call
00619        //  from Wave, and inserts it into the AST.
00620        //
00621        //  The parameter 'result' contains the token sequence generated as the 
00622        //  result of the rescanning.
00623        //
00625        template <typename ContainerT>
00626                void rescanned_macro(ContainerT const &result)
00627                {
00628 
00629                        //Attach the expanded macro to the macro call
00630                        --rescan_macro_status;
00631                        ROSE_ASSERT( rescan_macro_status >= 0 );
00632 #if 0
00633                        std::cout << "Rescanned macro: " << boost::wave::util::impl::as_string(result) << std::endl;
00634 #endif
00635                        if(rescan_macro_status==0){
00636                                ROSE_ASSERT(macro_call_to_expand != NULL);
00637 
00638                                copy (result.begin(), result.end(),
00639                                                inserter(macro_call_to_expand->expanded_macro, macro_call_to_expand->expanded_macro.end()));
00640 
00641 
00642                                //Attach the define to ROSE
00643                                std::string filename(macro_call_to_expand->macro_call.get_position().get_file().c_str());
00644                                if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
00645                                        currentMapOfAttributes[filename] = new ROSEAttributesList();
00646                                currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(macro_call_to_expand,PreprocessingInfo::before)));
00647                                macro_call_to_expand = NULL;
00648 
00649                        }
00650                }
00651 
00653        // The functor
00654        //     struct findDirective: public std::binary_function<TokenIterator,DirectiveType,bool>
00655        // helps to see if TokenIterator is of type directive.
00657 
00658        template<typename TokenIterator, typename DirectiveType>
00659                struct findDirective: public std::binary_function<TokenIterator,DirectiveType,bool>
00660                {
00661                        bool operator()(TokenIterator node, DirectiveType directive) const{
00662                                bool returnValue = false;
00663 
00664                                using namespace boost::wave;
00665 
00666                                token_id wave_typeid = token_id(node);
00667 
00668                                if(wave_typeid == directive)
00669                                        returnValue = true;
00670 
00671                                return returnValue;
00672                        };
00673 
00674                };
00675 
00677        // The functor
00678        //     struct findDirectiveInList: public
00679        //     std::binary_function<TokenIterator,std::list<DirectiveType>,bool>
00680        // helps to see if the token is of one of the types in directiveList.
00682        template<typename TokenIterator, typename DirectiveType>
00683                struct findDirectiveInList: public std::binary_function<TokenIterator,std::list<DirectiveType>,bool>
00684                {
00685                        bool operator()(TokenIterator node, std::list<DirectiveType> directiveList) const{
00686                                bool returnValue = false;
00687 
00688                                using namespace boost::wave;
00689 
00690                                token_id wave_typeid = token_id(node);
00691 #if 0
00692              // DQ (4/17/2008): Commented out to avoid error in fly-make!
00693                                if( T_PP_ELIF  == wave_typeid)
00694                                        std::cout << "Found an #elif\n";
00695 #endif
00696 
00697                                if(std::find(directiveList.begin(),directiveList.end(), wave_typeid) != directiveList.end())
00698                                        returnValue = true;
00699 
00700                                return returnValue;
00701                        };
00702 
00703                };
00704 
00705                 template <typename TokenT>
00706                 void
00707                 skipped_token(TokenT const& token, bool last_skipped = false)
00708                 {
00709                         //The skipped_token(...) function is called whenever a 
00710                         //part of a preprocessing #if #else/#elif #endif conditional
00711                         //is evaluated as false. The false part is handled here.
00712                         //King84 (2010.09.09):
00713                         //This does not handle the test conditions of #elif or #if
00714                         //Those are handled via update_token(...).  For now, other
00715                         //directives that are within the false branch are just skipped
00716                         //and don't have directives built from them.
00717 
00718                         if(skippedTokenStream == NULL)
00719                                 skippedTokenStream = new token_container();
00720 
00721                         if(last_skipped == false)
00722                         {
00723                                 if(SgProject::get_verbose() >= 1)
00724                                         std::cout << "Pushed Skipped Token: " << token.get_value().c_str() << std::endl;
00725                                 skippedTokenStream->push_back(token);
00726                         }
00727                         else
00728                         {
00729                                 skippedTokenStream->push_back(token);
00730 
00731                                 if(SgProject::get_verbose() >= 1)
00732                                 {
00733                                         std::cout << "Pushed Skipped Token: " << token.get_value().c_str() << std::endl;
00734                                         std::cout << "Popping Skipped Tokens: " << boost::wave::util::impl::as_string(*skippedTokenStream).c_str() << std::endl;
00735                                 }
00736                                 std::string filename(skippedTokenStream->begin()->get_position().get_file().c_str());
00737                                 if (currentMapOfAttributes.find(filename) == currentMapOfAttributes.end())
00738                                         currentMapOfAttributes[filename] = new ROSEAttributesList();
00739                                 currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(*skippedTokenStream, PreprocessingInfo::CSkippedToken, PreprocessingInfo::before)));
00740 
00741                                 ROSE_ASSERT(skippedTokenStream != NULL);
00742                                 delete skippedTokenStream;
00743                                 skippedTokenStream = NULL;
00744                         }
00745                         if (SgProject::get_verbose() >= 1)
00746                                 std::cout << "SKIPPED TOKEN: " << token.get_value().c_str() << std::endl;
00747                 }
00748 
00749                 inline void flush_token_stream()
00750                 {
00751                         if (skippedTokenStream == NULL || skippedTokenStream->begin() == skippedTokenStream->end())
00752                                 return;
00753 
00754                         std::string filename(skippedTokenStream->begin()->get_position().get_file().c_str());
00755                         if (currentMapOfAttributes.find(filename) == currentMapOfAttributes.end())
00756                                 currentMapOfAttributes[filename] = new ROSEAttributesList();
00757                         currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(*skippedTokenStream, PreprocessingInfo::CSkippedToken, PreprocessingInfo::before)));
00758                         delete skippedTokenStream;
00759                         skippedTokenStream = NULL;
00760                 }
00761 
00762                 template <typename ContextT, typename TokenT>
00763             bool
00764             may_skip_whitespace(ContextT const& ctx, TokenT& token, bool& skipped_newline)
00765             {
00766                         using namespace boost::wave;
00767                         //After the last skipped token has been processed the first non-skipped
00768                         //token will trigger this call to attach the skipped tokens to the AST
00769                         token_id id = token_id(token);
00770                         bool skip = id == T_PP_ELSE || id == T_PP_ELIF || id == T_PP_ENDIF;
00771                         using namespace boost::wave;
00772                         if(SgProject::get_verbose() >= 1)
00773                         {
00774                                 switch(token_id(token))
00775                                 {
00776                                         case T_PP_DEFINE:    std::cout << "Skip White: #define\n"; break;
00777                                         case T_PP_IF:        std::cout << "Skip White: #if\n"; break;
00778                                         case T_PP_IFDEF:     std::cout << "Skip White: #ifdef\n"; break;
00779                                         case T_PP_IFNDEF:    std::cout << "Skip White: #ifndef\n"; break;
00780                                         case T_PP_ELSE:      std::cout << "Skip White: #else\n"; break;
00781                                         case T_PP_ELIF:      std::cout << "Skip White: #elif\n"; break;
00782                                         case T_PP_ENDIF:     std::cout << "Skip White: #endif\n"; break;
00783                                         case T_PP_ERROR:     std::cout << "Skip White: #error\n"; break;
00784                                         case T_PP_LINE:      std::cout << "Skip White: #line\n"; break;
00785                                         case T_PP_PRAGMA:    std::cout << "Skip White: #pragma\n"; break;
00786                                         case T_PP_UNDEF:     std::cout << "Skip White: #undef\n"; break;
00787                                         case T_PP_WARNING:   std::cout << "Skip White: #warning\n"; break;
00788                                         case T_PP_INCLUDE:   std::cout << "Skip White: #include \"...\"\n"; break;
00789                                         case T_PP_QHEADER:   std::cout << "Skip White: #include <...>\n"; break;
00790                                         case T_PP_HHEADER:   std::cout << "Skip White: #include ...\n"; break;
00791                                         default:             std::cout << "Skip White: <something else (" << token.get_value() << ")>\n"; break;
00792                                 }
00793                         }
00794                         if (skip)
00795                         {
00796                                 skipped_token(token, true);
00797                         }
00798                         else
00799                         {
00800                                 if (skippedTokenStream != NULL) // flush the tokens and don't add this one (instead of calling skipped_token)
00801                                 {
00802                                         if(SgProject::get_verbose() >= 1)
00803                                         {
00804                                                 std::cout << "Whitespace makes us pop skipped tokens: " << boost::wave::util::impl::as_string(*skippedTokenStream).c_str() << std::endl;
00805                                         }
00806                                         flush_token_stream();
00807                                 }
00808                                 else if(SgProject::get_verbose() >= 1)
00809                                         std::cout << "Token stream is null?" << std::endl;
00810                         }
00811 
00812                if(SgProject::get_verbose() >= 1)
00813                        std::cout << "MAX_SKIP_WHITESPACE: " << token.get_value().c_str() << std::endl;
00814                return false; 
00815        }
00816 
00817 
00819        //The function 
00820        //     attach_line_to_macro_call()
00821        //will replace the line where a macro is called with the line from
00822        //the sourcecode.
00823        //WARNING! Currently disabled
00825        void attach_line_to_macro_call();
00826 
00827 
00828        template<typename IteratorT>
00829          void attach_line_to_macro_call(std::vector<IteratorT*> vec){
00830                }
00831 
00832        template <typename StringT, typename IteratorT>
00833                inline StringT
00834                as_string(IteratorT it, IteratorT end)
00835                {
00836                        StringT result;
00837                        for (; it != end; ++it)
00838                        {
00839                                result += (*it).get_value();
00840                        }
00841                        return result;
00842                }
00843 };
00844 
00845 
00846 template <typename TokenT>
00847 bool AttributeListMap::found_include_directive(TokenT directive, std::string relname, std::string absname )
00848    {
00849      boost::wave::token_id wave_typeid = boost::wave::token_id(directive);
00850 
00851      switch(wave_typeid)
00852         {
00853           case boost::wave::T_PP_INCLUDE:
00854                break;
00855           case boost::wave::T_EOI: //end of input reached
00856                break;
00857           default:
00858 
00859                if( directive.get_position().get_file().size() == 0 ) break;
00860 
00861                PreprocessingInfo::r_include_directive* inclDir = new PreprocessingInfo::r_include_directive;
00862 
00863                inclDir->directive = directive;
00864                inclDir->absname   = absname;
00865                inclDir->relname   = relname;
00866 
00867                std::string filename(directive.get_position().get_file().c_str());
00868                if (currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
00869                     currentMapOfAttributes[filename] = new ROSEAttributesList();
00870                currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(inclDir, PreprocessingInfo::before ) ));
00871                break;                                     
00872         }
00873         return false;
00874    }
00875 
00876 #endif
00877 
00878 

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