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