ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
attributeListMap.h
Go to the documentation of this file.
1 #ifndef XYZ_ATTRIBUTE_LIST_MAP
2 #define XYZ_ATTRIBUTE_LIST_MAP
3 
4 #define DEBUG_WAVE_ROSE_CONNECTION 1
5 #define DEBUG_USE_ROSE_BOOST_WAVE_SUPPORT 1
6 
7 // DQ (11/30/2008): This will be defined within the header file system for ROSE.
8 // #include <map>
9 // Header files needed for ROSE
10 
12 // Include Wave itself
13 #ifndef _MSC_VER
14 #include <boost/wave.hpp>
15 #endif
16 
18 // Include the lexer stuff
19 #include <boost/wave/cpplexer/cpp_lex_token.hpp> // token class
20 #include <boost/wave/cpplexer/cpp_lex_iterator.hpp> // lexer class
21 
22 // DQ: I don't think this forward declaration is required...
23 // class AttributeListMap;
24 
26 // Function queryFloatDoubleValExp() finds all nodes with type
27 // SgDoubleVal, SgLongDoubleVal or SgFloatVal
29 NodeQuerySynthesizedAttributeType
30 queryFloatDoubleValExp (SgNode * astNode);
31 
32 
33 //class advanced_preprocessing_hooks;
34 //#include "advanced_preprocessing_hooks.hpp"
35 
37 
38  private:
39  //rescan_macro_status is a helper for extracting the corresponding expanded macro to a macro call from Wave.
40  //This variable makes it so that the complexity of the macro expansion process can be ignoredd while still
41  //safely extracting the expanded string.
43  std::string macro_expand_filename;
44  //If rescan_macro_status!=0 the variable macro_call_to_expand should point to the macro call which is expanded. If other macros are
45  //called as an argument or as part of the macro definition corresponding to the macro call this data is *not* inside this variable.
48 
49  //For optimization and practical purposes a list of preprocessor attributes is created
50  //for each file. Since the preprocessor does an auxiliary pass over the AST a map
51  //is created mapping the filename to the ROSEAttributesList.
52 
53  public:
54  //A map of a filename to an ROSEAttributesList. All preprocessingdirectives and macros found in a file will be put into this list.
55  typedef std::map<std::string,ROSEAttributesList*> attribute_map_type;
57 
59 
60  //A map over all macro definitions found and their corresponding {filename, line number}
61  std::map<std::pair<std::string,int>, PreprocessingInfo*> defMap;
62 
63  // DQ (4/13/2007): These were required to support holding literals as strings (not required as a result of Rama's work).
64  // std::list<SgNode*> valueExpList;
65  // DQ (4/13/2007): This is due to a bug in ROSE, or a misunderstanding about constant folded values and their source position information.
66  // token_type lastOperator;
67 
68  AttributeListMap(SgFile* sageFilePtr);
69 
70  template <typename TokenT> bool found_include_directive(TokenT directive, std::string relname, std::string absname );
71 
72 
73 
75  // The function
76  // found_directive(TokenT const&, ...)
77  // will register a preprocessor directive with an expression (e.g #if, #ifdef etc) and will attach it to the AST.
78  //
80  template <typename TokenT, typename ContainerT>
81  bool
82  found_directive(TokenT const& directive, ContainerT const& expression, bool expression_value)
83  {
84  //Map between the wave preprocessorid to the ROSE preprocessorid
86  using namespace boost::wave;
87  token_id wave_typeid = token_id(directive);
88 
89  //Translate from wave to rose type-id notation
90 
91  switch(wave_typeid){
92  case T_PP_DEFINE: //#define
94  break;
95  case T_PP_IFDEF: //#ifdef
97  break;
98  case T_PP_IFNDEF: //#ifndef
100  break;
101  case T_PP_IF: //#if
103  break;
104  case T_PP_ELIF: //#elif
105  // DQ (4/17/2008): Commented out to avoid fly-make interpreting as an error!
106  // std::cout << "ELIF\n";
108  break;
109  case T_PP_ELSE: //#else
111  break;
112  case T_PP_ENDIF: //#endif
114  break;
115  case T_CPPCOMMENT: // // ... \n
117  break;
118  case T_CCOMMENT:
119  rose_typeid = PreprocessingInfo::C_StyleComment;
120  break;
121  case T_PP_ERROR: //#error
123  break;
124  case T_PP_LINE: //#line
126  break;
127  case T_PP_UNDEF: //#undef
129  break;
130  case T_PP_WARNING: //#warning
132  break;
133  case T_PP_QHEADER: //#include "..."
134  case T_PP_HHEADER: //#include <...>
135  case T_PP_INCLUDE: //#include "..."
136  if(SgProject::get_verbose() >= 1)
137  std::cout << "Token to include directive: " << directive.get_value() << std::endl;
139  break;
140  case T_PP_PRAGMA: //#pragma
141  // Part of the AST in ROSE. Do not handle it this way
142  return false;
143  // DQ (8/29/2009): Unreachable statement after "return"
144  // break;
145 
146  default:
147  // This case should not be reached
148  ROSE_ASSERT(false==true);
150  break;
151 
152  }
153  if(SgProject::get_verbose() >= 1){
154 
155  std::cout << "THE FOUND DIRECTIVE IS: " << directive.get_value().c_str() << std::endl;
156  std::cout << "THE FOUND DEF IS: " << boost::wave::util::impl::as_string(expression) << std::endl;
157  }
158  //
159  std::string filename(directive.get_position().get_file().c_str());
160  token_list_container tokListCont;
161 
162  copy (expression.begin(), expression.end(),
163  inserter(tokListCont, tokListCont.end()));
164 
165 
166 
167  if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
168  currentMapOfAttributes[filename] = new ROSEAttributesList();
169  currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(directive,tokListCont,expression_value,rose_typeid,PreprocessingInfo::before)));
170 
171  return false;
172  }
173 
174  // King84 (2010.09.09): Added to support getting arguments for conditionals which had been skipped
175  template <typename TokenT, typename ContainerT>
176  void
177  update_token(TokenT const& token, ContainerT const& stream, bool expression_value)
178  {
179 // typename TokenT::position_type::string_type filename(token.get_position().get_file().c_str());
180  std::string filename(token.get_position().get_file().c_str());
181  // ensure that the file exists
182  ROSE_ASSERT(currentMapOfAttributes.find(filename) != currentMapOfAttributes.end());
183  // get the list of attributes
184  std::vector<PreprocessingInfo*>& infos = currentMapOfAttributes.find(filename)->second->getList();
185  for(std::vector<PreprocessingInfo*>::reverse_iterator i = infos.rbegin(); i != infos.rend(); ++i)
186  {
187  // match this one
188  if ((*(*i)->get_token_stream())[0] == token && (*(*i)->get_token_stream())[0].get_position() == token.get_position())
189  {
190  // TODO: something with expression_value once the PreprocessingInfo actually decides to start storing it
191  for (typename ContainerT::const_iterator item = stream.begin(); item != stream.end(); ++item)
192  {
193  (*i)->push_back_token_stream(*item);
194  }
195  return;
196  }
197  }
198  ROSE_ASSERT(!"Token to update not found!");
199  }
200 
201 
203  // The function
204  // found_directive(TokenT const&, ...)
205  // will register a preprocessor directive when it is found (e.g #define, #if, #endif etc) and will attach it to the AST.
206  //
208 
209  template <typename TokenT>
210  void
211  found_directive(TokenT const& directive)
212  {
213  //Map between the wave preprocessorid to the ROSE preprocessorid
215  using namespace boost::wave;
216  token_id wave_typeid = token_id(directive);
217 
218 
219  //Translate from wave to rose type-id notation
220  switch(wave_typeid){
221  case T_PP_IFDEF: //#ifdef
223  break;
224  case T_PP_IFNDEF: //#ifndef
226  break;
227  case T_PP_IF: //#if
229  break;
230  //These directive have expression attached to them and should be handled
231  //by found_directive(TokenT const& directive, ContainerT const& expression)
232  ROSE_ASSERT(false);
233  break;
234  case T_PP_DEFINE: //#define
236  break;
237  case T_PP_ELIF: //#elif
239  break;
240  case T_PP_ELSE: //#else
242  break;
243  case T_PP_ENDIF: //#endif
245  break;
246  case T_CPPCOMMENT: // // ... \n
248  break;
249  case T_CCOMMENT:
250  rose_typeid = PreprocessingInfo::C_StyleComment;
251  break;
252  case T_PP_ERROR: //#error
254  break;
255  case T_PP_LINE: //#line
257  break;
258  case T_PP_UNDEF: //#undef
260  break;
261  case T_PP_WARNING: //#warning
263  break;
264  case T_PP_QHEADER: //#include "..."
265  case T_PP_HHEADER: //#include <...>
266  case T_PP_INCLUDE: //#include ...
267  if(SgProject::get_verbose() >= 1)
268  std::cout << "Token to include directive: " << directive.get_value() << std::endl;
270  break;
271  case boost::wave::T_PP_HHEADER_NEXT:
272  if(SgProject::get_verbose() >= 1)
273  std::cout << "Token to include next directive: " << directive.get_value() << std::endl;
275 
276  break;
277  case T_PP_PRAGMA: //#pragma
278  // Part of the AST in ROSE. Do not handle it this way
279  return;
280 
281  // DQ (8/29/2009): Unreachable statement after "return"
282  // break;
283 
284  default:
285  {
286  // This case should not be reached
287 
288  // DQ (8/29/2009): It is a horrible idea to only fail when verbose mode is turned on!
289  if (SgProject::get_verbose() >= 1)
290  {
291  std::cout << "Error: Unknown preprocessor declaration found : " << directive.get_value().c_str() << std::endl;
292  std::cout << boost::wave::get_token_name(wave_typeid) << " " << directive.get_position().get_file().c_str() << " " << directive.get_position().get_line()
293  << " " << directive.get_position().get_column() << std::endl;
294  ROSE_ASSERT(false);
295  }
296 
298  break;
299  }
300 
301  }
302 
303  //std::cout << "THE FOUND DIRECTIVE IS: " << directive.get_value().c_str() << std::endl;
304 
305  token_container currentTokSeq2;
306  currentTokSeq2.push_back(directive);
307  std::string filename(directive.get_position().get_file().c_str());
308  if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
309  currentMapOfAttributes[filename] = new ROSEAttributesList();
310  currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(currentTokSeq2,rose_typeid,PreprocessingInfo::before)));
311 
312 
313  }
314 
315 
316 
318  // The function
319  // PreprocessingInfo* build_preprocessingInfo_macro_def(TokenT&
320  // macro_name, bool is_functionlike,..)
321  // will create a PreprocessingInfo object for a preprocessor
322  // defined macro definition. E.g
323  // #ifdef NOT_DEFINED_MACRO
324  // #endif
326 
327  template<typename TokenT, typename ParametersT, typename DefinitionT>
328  PreprocessingInfo* build_preprocessingInfo_macro_def(TokenT& macro_name, bool is_functionlike,
329  ParametersT& parameters, DefinitionT &definition, bool is_predefined){
330 
332 
333  //Make copies of all the variables for ROSE
334  macro_def->is_functionlike = is_functionlike;
335  macro_def->is_predefined = is_predefined;
336 
337  macro_def->macro_name = macro_name;
338  macro_def->paramaters = parameters;
339 
340  copy (definition.begin(), definition.end(),
341  inserter(macro_def->definition, macro_def->definition.end()));
342  PreprocessingInfo* preprocMacroDef = new PreprocessingInfo(macro_def,PreprocessingInfo::before);
343 
344  return preprocMacroDef;
345  }
346 
348  // The function
349  // defined_macro<TokentT,ParametersT, DefinitionT>
350  // takes a macro definition as paramaters and convert it into a PreprocessingInfo object for the AST
352  template<typename TokenT, typename ParametersT, typename DefinitionT>
353  void defined_macro(TokenT& macro_name, bool is_functionlike,
354  ParametersT& parameters, DefinitionT &definition, bool is_predefined){
355  if(skippedTokenStream != NULL){
356 
357  if(macro_name.get_position().get_file().size()!=0){
358  if(macro_name.get_position().get_file()!="<built-in>")
359  skipped_token(macro_name,true);
360  }else if(SgProject::get_verbose() >= 1)
361  std::cout << "SKIPPED BECAUSE FILE IS NULL: " << macro_name.get_value().c_str() << std::endl;
362 
363  }
364  //All the information in the paramaters here comes from an macro_definition object declared in boost/wave/utils/macro_defintion.hpp
365  //The real values of the typename which is found in this class is
366  // typedef std::vector<TokenT> parameter_container_t;
367  // typedef ContainerT definition_container_t;
368 
369  //From cpp_context
370  //DefinitionT is a ContextT::token_sequence_type which is the type of a token sequence defined in cpp_context
371  // typedef std::list<token_type, boost::fast_pool_allocator<token_type> > token_sequence_type;
372 
373  PreprocessingInfo* preprocMacroDef = build_preprocessingInfo_macro_def(macro_name, is_functionlike, parameters, definition, is_predefined);
374  ROSE_ASSERT(preprocMacroDef != NULL);
375 
376  Sg_File_Info* file_info = preprocMacroDef->get_file_info();
377  ROSE_ASSERT(file_info != NULL);
378 
379  std::string filename = file_info->get_filenameString();
380 
381  //Make sure that the macro definition has been declared within a file
382  //and not on the commandline
383  ROSE_ASSERT(filename != "");
384 
385  if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
386  currentMapOfAttributes[filename] = new ROSEAttributesList();
387  if(SgProject::get_verbose() >= 1)
388  std::cout << "DONE adding to map" << std::endl;
389  currentMapOfAttributes.find(filename)->second->addElement(*preprocMacroDef);
390  if(SgProject::get_verbose() >= 1)
391  std::cout << "Before mapKey" << std::endl;
392  //Insert the macro definition into the map of macro definitions (used for macro calls)
393  std::pair<std::string,int> mapKey(filename,macro_name.get_position().get_line());
394  if(SgProject::get_verbose() >= 1){
395  std::cout << "After mapKey" << std::endl;
396 
397  std::cout << "ASXXX Defining macro: " << macro_name.get_value().c_str() << std::endl;
398  std::cout << "at " << filename << " l" << mapKey.second << std::endl;
399  }
400 
401  //A macro can not be defined twice
402  //ROSE_ASSERT( defMap.find(mapKey) == defMap.end() );
403  //Although a macro can not be defined twice it is possible that a macro
404  //can be undefined and then defined again. Since we do not yet use the
405  //#undef information we should just consolidate those macro definitions
406  //into one macro
407  if( defMap.find(mapKey) == defMap.end() )
408  defMap[mapKey]=preprocMacroDef;
409 
410  }
411 
413  // The function
414  // addElement<TokentT,ContainerT>
415  // takes an expansion of a function like macro as paramater and convert it into a PreprocessingInfo::rose_macro_call object for the AST
417  template<typename TokenT, typename ContainerT>
418  bool expanding_function_like_macro(TokenT const &macrodef, std::vector<TokenT> const &formal_args,
419  ContainerT const &definition, TokenT const &macrocall, std::vector<ContainerT> const &arguments){
420  if(skippedTokenStream != NULL)
421  skipped_token(macrodef,true);
422 
424  //
425  //Note from AS:
426  //The typename ContainerT is often equivalent to list<TokenT>.
427  //TokentT is often equivalent to boost::wave::cpplexer::lex_token<>
428  //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
429  //
431  //All the information in the paramaters here comes from an macro_definition object declared in boost/wave/utils/macro_defintion.hpp
432  //The real values of the typename which is found in this class is
433  // typedef std::vector<TokenT> parameter_container_t;
434  // typedef ContainerT definition_container_t;
435 
436  //From cpp_context
437  //DefinitionT is a ContextT::token_sequence_type which is the type of a token sequence defined in cpp_context
438  // typedef std::list<token_type, boost::fast_pool_allocator<token_type> > token_sequence_type;
439 
440  if(rescan_macro_status==0){
441 
442  if(SgProject::get_verbose() >= 1){
443 
444  std::cout << "DEFINITION: " << boost::wave::util::impl::as_string(definition);
445 
446  std::cout << "\n MACRO CALL: " << macrocall.get_value() << std::endl;
447  }
448  //have to implement mechanism to find macro definition here
449  ROSE_ASSERT(macro_call_to_expand == NULL);
452  macro_call_to_expand->macro_call = macrocall;
453 
454  // std::pair<std::string,int> mapKey(string(definition.begin()->get_position().get_file().c_str()),
455  // definition.begin()->get_position().get_line());
456 
457  std::pair<std::string,int> mapKey;
458 
459  if(macrodef.get_position().get_file()!="<built-in>"){
460  mapKey.first = string(macrodef.get_position().get_file().c_str());
461  mapKey.second = macrodef.get_position().get_line();
462  ROSE_ASSERT( defMap.find(mapKey) != defMap.end() );
464  // std::cout << definition.begin()->get_position().get_line() << std::endl;
465 
466  }else{
467  bool is_function_like = true;
468  bool is_predefined = false;
469  macro_call_to_expand->macro_def = build_preprocessingInfo_macro_def(macrodef, is_function_like, formal_args, definition, is_predefined);
470  }
471 
472  if( (defMap.find(mapKey) == defMap.end())&&(SgProject::get_verbose() >= 1) ){
473  std::cout << "Did not find: " << macrodef.get_value().c_str() << " " << boost::wave::util::impl::as_string(definition) << std::endl;
474  std::cout << "in " << mapKey.first << " l " << mapKey.second << std::endl;
475  };
476 
477 
478  // typedef typename std::vector<std::list<token_type,boost::fast_pool_allocator<token_type> > > testType;
479  typedef typename std::vector<ContainerT>::const_iterator vec_call_iterator_t;
480 
481  //BEGIN: Make a copy of the arguments
482 
483  vec_call_iterator_t it = arguments.begin();
484  vec_call_iterator_t it_end = arguments.end();
485 
486  //extract the arguments in the macro call from wave
487 
488  //ARGUMENTS
489  if(SgProject::get_verbose() >= 1)
490  std::cout << "ARGUMENTS:\n";
491 
492  while (it != it_end ){
493  if(SgProject::get_verbose() >= 1){
494  std::cout << boost::wave::util::impl::as_string(*it);
495  }
496  std::list<token_type> tk;
497 
498  copy (it->begin(), it->end(),
499  inserter(tk, tk.end()));
500 
501  macro_call_to_expand->arguments.push_back(tk);
502  ++it;
503  }
504 
505  //END: Make a copy of the arguments
506  }
507 
509 
510 
511 #if 0
512  typename testType::iterator it2 = test.begin();
513  typename testType::iterator it_end2 = test.end();
514 
515  while (it2 != it_end2 ){
516  std::cout<< boost::wave::util::impl::as_string(*it2);
517  ++it2;
518  }
519 #endif
520  return false;
521 
522  }
523 
525  // The function
526  // expanding_object_like_macro<TokentT,ContainerT>
527  // takes an expansion of a object like macro as paramater and convert it into a PreprocessingInfo::macr_call object for the AST
528  // The macroname parameter marks the position, where the macro to expand
529  // is defined.
530  // The definition parameter holds the macro definition for the macro to
531  // trace.
532  //
533  // The macro call parameter marks the position, where this macro invoked.
534  //
536  template<typename TokenT, typename ContainerT>
537  bool expanding_object_like_macro(TokenT const &macro, ContainerT const &definition, TokenT const &macrocall){
538  if(skippedTokenStream != NULL)
539  skipped_token(macro,true);
540 
541  //All the information in the paramaters here comes from an macro_definition object declared in boost/wave/utils/macro_defintion.hpp
542  //The real values of the typename which is found in this class is
543  // typedef std::vector<TokenT> parameter_container_t;
544  // typedef ContainerT definition_container_t;
545 
546  //From cpp_context
547  //DefinitionT is a ContextT::token_sequence_type which is the type of a token sequence defined in cpp_context
548  // typedef std::list<token_type, boost::fast_pool_allocator<token_type> > token_sequence_type;
549 
550  //Put the macro_definition into the AST
551 
552  //have to implement mechanism to find macro definition here
553 
554  if(rescan_macro_status==0){
555  ROSE_ASSERT(macro_call_to_expand == NULL);
556  if(SgProject::get_verbose() >= 1)
557  std::cout << "DEFINITION: " << boost::wave::util::impl::as_string(definition);
558 
560 
562  macro_call_to_expand->macro_call = macrocall;
563 
564  std::pair<std::string,int> mapKey;
565 
566  if( (macro.get_position().get_file().size() != 0 ) && (macro.get_position().get_file()!="<built-in>")
567  && (macro.get_position().get_file()!="<command line>") ){
568  mapKey.first = string(macro.get_position().get_file().c_str());
569  mapKey.second = macro.get_position().get_line();
570 
571  if( defMap.find(mapKey) == defMap.end() ){
572  std::cout << "Did not find: " << macro.get_value().c_str() << " " <<
573  macrocall.get_value().c_str() << " " << boost::wave::util::impl::as_string(definition) << std::endl;
574  std::cout << "in " << mapKey.first << " l " << mapKey.second << std::endl;
575  };
576 
577  ROSE_ASSERT( defMap.find(mapKey) != defMap.end() );
579  // std::cout << definition.begin()->get_position().get_line() << std::endl;
580 
581  }else{
582 
583  bool is_function_like = false;
584  bool is_predefined = false;
585 
586  token_container parameters;
587  macro_call_to_expand->macro_def = build_preprocessingInfo_macro_def(macro, is_function_like, parameters, definition, is_predefined);
588  }
589 
590 
591  if(SgProject::get_verbose() >= 1)
592  std::cout << "\n MACRO CALL: " << macrocall.get_value() << std::endl;
593  }
594 
596  return false;
597  }
598 
600  //
601  // The function 'expanded_macro' is called, whenever the expansion of a
602  // macro is finished but before the rescanning process starts.
603  //
604  // The parameter 'result' contains the token sequence generated as the
605  // result of the macro expansion.
606  //
608  template <typename ContainerT>
609  void expanded_macro(ContainerT const &result)
610  {
611 
612  }
613 
614 
616  //
617  // The function 'rescanned_macro' is called, whenever the rescanning of a
618  // macro is finished. It connects the macro_call and expanded macro call
619  // from Wave, and inserts it into the AST.
620  //
621  // The parameter 'result' contains the token sequence generated as the
622  // result of the rescanning.
623  //
625  template <typename ContainerT>
626  void rescanned_macro(ContainerT const &result)
627  {
628 
629  //Attach the expanded macro to the macro call
631  ROSE_ASSERT( rescan_macro_status >= 0 );
632 #if 0
633  std::cout << "Rescanned macro: " << boost::wave::util::impl::as_string(result) << std::endl;
634 #endif
635  if(rescan_macro_status==0){
636  ROSE_ASSERT(macro_call_to_expand != NULL);
637 
638  copy (result.begin(), result.end(),
640 
641 
642  //Attach the define to ROSE
643  std::string filename(macro_call_to_expand->macro_call.get_position().get_file().c_str());
644  if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
645  currentMapOfAttributes[filename] = new ROSEAttributesList();
647  macro_call_to_expand = NULL;
648 
649  }
650  }
651 
653  // The functor
654  // struct findDirective: public std::binary_function<TokenIterator,DirectiveType,bool>
655  // helps to see if TokenIterator is of type directive.
657 
658  template<typename TokenIterator, typename DirectiveType>
659  struct findDirective: public std::binary_function<TokenIterator,DirectiveType,bool>
660  {
661  bool operator()(TokenIterator node, DirectiveType directive) const{
662  bool returnValue = false;
663 
664  using namespace boost::wave;
665 
666  token_id wave_typeid = token_id(node);
667 
668  if(wave_typeid == directive)
669  returnValue = true;
670 
671  return returnValue;
672  };
673 
674  };
675 
677  // The functor
678  // struct findDirectiveInList: public
679  // std::binary_function<TokenIterator,std::list<DirectiveType>,bool>
680  // helps to see if the token is of one of the types in directiveList.
682  template<typename TokenIterator, typename DirectiveType>
683  struct findDirectiveInList: public std::binary_function<TokenIterator,std::list<DirectiveType>,bool>
684  {
685  bool operator()(TokenIterator node, std::list<DirectiveType> directiveList) const{
686  bool returnValue = false;
687 
688  using namespace boost::wave;
689 
690  token_id wave_typeid = token_id(node);
691 #if 0
692  // DQ (4/17/2008): Commented out to avoid error in fly-make!
693  if( T_PP_ELIF == wave_typeid)
694  std::cout << "Found an #elif\n";
695 #endif
696 
697  if(std::find(directiveList.begin(),directiveList.end(), wave_typeid) != directiveList.end())
698  returnValue = true;
699 
700  return returnValue;
701  };
702 
703  };
704 
705  template <typename TokenT>
706  void
707  skipped_token(TokenT const& token, bool last_skipped = false)
708  {
709  //The skipped_token(...) function is called whenever a
710  //part of a preprocessing #if #else/#elif #endif conditional
711  //is evaluated as false. The false part is handled here.
712  //King84 (2010.09.09):
713  //This does not handle the test conditions of #elif or #if
714  //Those are handled via update_token(...). For now, other
715  //directives that are within the false branch are just skipped
716  //and don't have directives built from them.
717 
718  if(skippedTokenStream == NULL)
720 
721  if(last_skipped == false)
722  {
723  if(SgProject::get_verbose() >= 1)
724  std::cout << "Pushed Skipped Token: " << token.get_value().c_str() << std::endl;
725  skippedTokenStream->push_back(token);
726  }
727  else
728  {
729  skippedTokenStream->push_back(token);
730 
731  if(SgProject::get_verbose() >= 1)
732  {
733  std::cout << "Pushed Skipped Token: " << token.get_value().c_str() << std::endl;
734  std::cout << "Popping Skipped Tokens: " << boost::wave::util::impl::as_string(*skippedTokenStream).c_str() << std::endl;
735  }
736  std::string filename(skippedTokenStream->begin()->get_position().get_file().c_str());
737  if (currentMapOfAttributes.find(filename) == currentMapOfAttributes.end())
738  currentMapOfAttributes[filename] = new ROSEAttributesList();
740 
741  ROSE_ASSERT(skippedTokenStream != NULL);
742  delete skippedTokenStream;
743  skippedTokenStream = NULL;
744  }
745  if (SgProject::get_verbose() >= 1)
746  std::cout << "SKIPPED TOKEN: " << token.get_value().c_str() << std::endl;
747  }
748 
749  inline void flush_token_stream()
750  {
751  if (skippedTokenStream == NULL || skippedTokenStream->begin() == skippedTokenStream->end())
752  return;
753 
754  std::string filename(skippedTokenStream->begin()->get_position().get_file().c_str());
755  if (currentMapOfAttributes.find(filename) == currentMapOfAttributes.end())
756  currentMapOfAttributes[filename] = new ROSEAttributesList();
758  delete skippedTokenStream;
759  skippedTokenStream = NULL;
760  }
761 
762  template <typename ContextT, typename TokenT>
763  bool
764  may_skip_whitespace(ContextT const& ctx, TokenT& token, bool& skipped_newline)
765  {
766  using namespace boost::wave;
767  //After the last skipped token has been processed the first non-skipped
768  //token will trigger this call to attach the skipped tokens to the AST
769  token_id id = token_id(token);
770  bool skip = id == T_PP_ELSE || id == T_PP_ELIF || id == T_PP_ENDIF;
771  using namespace boost::wave;
772  if(SgProject::get_verbose() >= 1)
773  {
774  switch(token_id(token))
775  {
776  case T_PP_DEFINE: std::cout << "Skip White: #define\n"; break;
777  case T_PP_IF: std::cout << "Skip White: #if\n"; break;
778  case T_PP_IFDEF: std::cout << "Skip White: #ifdef\n"; break;
779  case T_PP_IFNDEF: std::cout << "Skip White: #ifndef\n"; break;
780  case T_PP_ELSE: std::cout << "Skip White: #else\n"; break;
781  case T_PP_ELIF: std::cout << "Skip White: #elif\n"; break;
782  case T_PP_ENDIF: std::cout << "Skip White: #endif\n"; break;
783  case T_PP_ERROR: std::cout << "Skip White: #error\n"; break;
784  case T_PP_LINE: std::cout << "Skip White: #line\n"; break;
785  case T_PP_PRAGMA: std::cout << "Skip White: #pragma\n"; break;
786  case T_PP_UNDEF: std::cout << "Skip White: #undef\n"; break;
787  case T_PP_WARNING: std::cout << "Skip White: #warning\n"; break;
788  case T_PP_INCLUDE: std::cout << "Skip White: #include \"...\"\n"; break;
789  case T_PP_QHEADER: std::cout << "Skip White: #include <...>\n"; break;
790  case T_PP_HHEADER: std::cout << "Skip White: #include ...\n"; break;
791  default: std::cout << "Skip White: <something else (" << token.get_value() << ")>\n"; break;
792  }
793  }
794  if (skip)
795  {
796  skipped_token(token, true);
797  }
798  else
799  {
800  if (skippedTokenStream != NULL) // flush the tokens and don't add this one (instead of calling skipped_token)
801  {
802  if(SgProject::get_verbose() >= 1)
803  {
804  std::cout << "Whitespace makes us pop skipped tokens: " << boost::wave::util::impl::as_string(*skippedTokenStream).c_str() << std::endl;
805  }
807  }
808  else if(SgProject::get_verbose() >= 1)
809  std::cout << "Token stream is null?" << std::endl;
810  }
811 
812  if(SgProject::get_verbose() >= 1)
813  std::cout << "MAX_SKIP_WHITESPACE: " << token.get_value().c_str() << std::endl;
814  return false;
815  }
816 
817 
819  //The function
820  // attach_line_to_macro_call()
821  //will replace the line where a macro is called with the line from
822  //the sourcecode.
823  //WARNING! Currently disabled
826 
827 
828  template<typename IteratorT>
829  void attach_line_to_macro_call(std::vector<IteratorT*> vec){
830  }
831 
832  template <typename StringT, typename IteratorT>
833  inline StringT
834  as_string(IteratorT it, IteratorT end)
835  {
836  StringT result;
837  for (; it != end; ++it)
838  {
839  result += (*it).get_value();
840  }
841  return result;
842  }
843 };
844 
845 
846 template <typename TokenT>
847 bool AttributeListMap::found_include_directive(TokenT directive, std::string relname, std::string absname )
848  {
849  boost::wave::token_id wave_typeid = boost::wave::token_id(directive);
850 
851  switch(wave_typeid)
852  {
853  case boost::wave::T_PP_INCLUDE:
854  break;
855  case boost::wave::T_EOI: //end of input reached
856  break;
857  default:
858 
859  if( directive.get_position().get_file().size() == 0 ) break;
860 
862 
863  inclDir->directive = directive;
864  inclDir->absname = absname;
865  inclDir->relname = relname;
866 
867  std::string filename(directive.get_position().get_file().c_str());
868  if (currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
869  currentMapOfAttributes[filename] = new ROSEAttributesList();
870  currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(inclDir, PreprocessingInfo::before ) ));
871  break;
872  }
873  return false;
874  }
875 
876 #endif
877 
878