ROSE 0.11.145.147
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
13// 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
31NodeQuerySynthesizedAttributeType
32queryFloatDoubleValExp (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_ABORT();
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_ABORT();
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
615 //
616 // The function 'rescanned_macro' is called, whenever the rescanning of a
617 // macro is finished. It connects the macro_call and expanded macro call
618 // from Wave, and inserts it into the AST.
619 //
620 // The parameter 'result' contains the token sequence generated as the
621 // result of the rescanning.
622 //
624 template <typename ContainerT>
625 void rescanned_macro(ContainerT const &result)
626 {
627
628 //Attach the expanded macro to the macro call
629 --rescan_macro_status;
630 ROSE_ASSERT( rescan_macro_status >= 0 );
631#if 0
632 std::cout << "Rescanned macro: " << boost::wave::util::impl::as_string(result) << std::endl;
633#endif
634 if(rescan_macro_status==0){
635 ROSE_ASSERT(macro_call_to_expand != NULL);
636
637 copy (result.begin(), result.end(),
638 inserter(macro_call_to_expand->expanded_macro, macro_call_to_expand->expanded_macro.end()));
639
640
641 //Attach the define to ROSE
642 std::string filename(macro_call_to_expand->macro_call.get_position().get_file().c_str());
643 if(currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
644 currentMapOfAttributes[filename] = new ROSEAttributesList();
645 currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(macro_call_to_expand,PreprocessingInfo::before)));
646 macro_call_to_expand = NULL;
647
648 }
649 }
650
652 // The functor
653 // struct findDirective: public std::binary_function<TokenIterator,DirectiveType,bool>
654 // helps to see if TokenIterator is of type directive.
656
657 template<typename TokenIterator, typename DirectiveType>
659 {
660 using result_type = bool;
661 result_type operator()(TokenIterator node, DirectiveType directive) const {
662 using namespace boost::wave;
663 result_type returnValue = false;
664
665 token_id wave_typeid = token_id(node);
666 if (wave_typeid == directive) {
667 returnValue = true;
668 }
669
670 return returnValue;
671 };
672
673 };
674
676 // The functor
677 // struct findDirectiveInList: public
678 // std::binary_function<TokenIterator,std::list<DirectiveType>,bool>
679 // helps to see if the token is of one of the types in directiveList.
681 template<typename TokenIterator, typename DirectiveType>
683 {
684 using result_type = bool;
685 result_type operator()(TokenIterator node, std::list<DirectiveType> directiveList) const{
686 using namespace boost::wave;
687 result_type returnValue = false;
688
689 token_id wave_typeid = token_id(node);
690 if (std::find(directiveList.begin(),directiveList.end(), wave_typeid) != directiveList.end()) {
691 returnValue = true;
692 }
693
694 return returnValue;
695 };
696
697 };
698
699 template <typename TokenT>
700 void
701 skipped_token(TokenT const& token, bool last_skipped = false)
702 {
703 //The skipped_token(...) function is called whenever a
704 //part of a preprocessing #if #else/#elif #endif conditional
705 //is evaluated as false. The false part is handled here.
706 //King84 (2010.09.09):
707 //This does not handle the test conditions of #elif or #if
708 //Those are handled via update_token(...). For now, other
709 //directives that are within the false branch are just skipped
710 //and don't have directives built from them.
711
712 if(skippedTokenStream == NULL)
713 skippedTokenStream = new token_container();
714
715 if(last_skipped == false)
716 {
717 if(SgProject::get_verbose() >= 1)
718 std::cout << "Pushed Skipped Token: " << token.get_value().c_str() << std::endl;
719 skippedTokenStream->push_back(token);
720 }
721 else
722 {
723 skippedTokenStream->push_back(token);
724
725 if(SgProject::get_verbose() >= 1)
726 {
727 std::cout << "Pushed Skipped Token: " << token.get_value().c_str() << std::endl;
728 std::cout << "Popping Skipped Tokens: " << boost::wave::util::impl::as_string(*skippedTokenStream).c_str() << std::endl;
729 }
730 std::string filename(skippedTokenStream->begin()->get_position().get_file().c_str());
731 if (currentMapOfAttributes.find(filename) == currentMapOfAttributes.end())
732 currentMapOfAttributes[filename] = new ROSEAttributesList();
733 currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(*skippedTokenStream, PreprocessingInfo::CSkippedToken, PreprocessingInfo::before)));
734
735 ROSE_ASSERT(skippedTokenStream != NULL);
736 delete skippedTokenStream;
737 skippedTokenStream = NULL;
738 }
739 if (SgProject::get_verbose() >= 1)
740 std::cout << "SKIPPED TOKEN: " << token.get_value().c_str() << std::endl;
741 }
742
743 inline void flush_token_stream()
744 {
745 if (skippedTokenStream == NULL || skippedTokenStream->begin() == skippedTokenStream->end())
746 return;
747
748 std::string filename(skippedTokenStream->begin()->get_position().get_file().c_str());
749 if (currentMapOfAttributes.find(filename) == currentMapOfAttributes.end())
750 currentMapOfAttributes[filename] = new ROSEAttributesList();
751 currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(*skippedTokenStream, PreprocessingInfo::CSkippedToken, PreprocessingInfo::before)));
752 delete skippedTokenStream;
753 skippedTokenStream = NULL;
754 }
755
756 template <typename ContextT, typename TokenT>
757 bool
758 may_skip_whitespace(ContextT const&, TokenT& token, bool&/*skipped_newline*/)
759 {
760 using namespace boost::wave;
761 //After the last skipped token has been processed the first non-skipped
762 //token will trigger this call to attach the skipped tokens to the AST
763 token_id id = token_id(token);
764 bool skip = id == T_PP_ELSE || id == T_PP_ELIF || id == T_PP_ENDIF;
765 using namespace boost::wave;
766 if(SgProject::get_verbose() >= 1)
767 {
768 switch(token_id(token))
769 {
770 case T_PP_DEFINE: std::cout << "Skip White: #define\n"; break;
771 case T_PP_IF: std::cout << "Skip White: #if\n"; break;
772 case T_PP_IFDEF: std::cout << "Skip White: #ifdef\n"; break;
773 case T_PP_IFNDEF: std::cout << "Skip White: #ifndef\n"; break;
774 case T_PP_ELSE: std::cout << "Skip White: #else\n"; break;
775 case T_PP_ELIF: std::cout << "Skip White: #elif\n"; break;
776 case T_PP_ENDIF: std::cout << "Skip White: #endif\n"; break;
777 case T_PP_ERROR: std::cout << "Skip White: #error\n"; break;
778 case T_PP_LINE: std::cout << "Skip White: #line\n"; break;
779 case T_PP_PRAGMA: std::cout << "Skip White: #pragma\n"; break;
780 case T_PP_UNDEF: std::cout << "Skip White: #undef\n"; break;
781 case T_PP_WARNING: std::cout << "Skip White: #warning\n"; break;
782 case T_PP_INCLUDE: std::cout << "Skip White: #include \"...\"\n"; break;
783 case T_PP_QHEADER: std::cout << "Skip White: #include <...>\n"; break;
784 case T_PP_HHEADER: std::cout << "Skip White: #include ...\n"; break;
785 default: std::cout << "Skip White: <something else (" << token.get_value() << ")>\n"; break;
786 }
787 }
788 if (skip)
789 {
790 skipped_token(token, true);
791 }
792 else
793 {
794 if (skippedTokenStream != NULL) // flush the tokens and don't add this one (instead of calling skipped_token)
795 {
796 if(SgProject::get_verbose() >= 1)
797 {
798 std::cout << "Whitespace makes us pop skipped tokens: " << boost::wave::util::impl::as_string(*skippedTokenStream).c_str() << std::endl;
799 }
800 flush_token_stream();
801 }
802 else if(SgProject::get_verbose() >= 1)
803 std::cout << "Token stream is null?" << std::endl;
804 }
805
806 if(SgProject::get_verbose() >= 1)
807 std::cout << "MAX_SKIP_WHITESPACE: " << token.get_value().c_str() << std::endl;
808 return false;
809 }
810
811
813 //The function
814 // attach_line_to_macro_call()
815 //will replace the line where a macro is called with the line from
816 //the sourcecode.
817 //WARNING! Currently disabled
819 void attach_line_to_macro_call();
820
821
822 template<typename IteratorT>
823 void attach_line_to_macro_call(std::vector<IteratorT*> vec){
824 }
825
826 template <typename StringT, typename IteratorT>
827 inline StringT
828 as_string(IteratorT it, IteratorT end)
829 {
830 StringT result;
831 for (; it != end; ++it)
832 {
833 result += (*it).get_value();
834 }
835 return result;
836 }
837};
838#endif
839
840
841#ifndef ROSE_SKIP_COMPILATION_OF_WAVE
842template <typename TokenT>
843bool AttributeListMap::found_include_directive(TokenT directive, std::string relname, std::string absname )
844 {
845 boost::wave::token_id wave_typeid = boost::wave::token_id(directive);
846
847 switch(wave_typeid)
848 {
849 case boost::wave::T_PP_INCLUDE:
850 break;
851 case boost::wave::T_EOI: //end of input reached
852 break;
853 default:
854
855 if( directive.get_position().get_file().size() == 0 ) break;
856
858
859 inclDir->directive = directive;
860 inclDir->absname = absname;
861 inclDir->relname = relname;
862
863 std::string filename(directive.get_position().get_file().c_str());
864 if (currentMapOfAttributes.find(filename)==currentMapOfAttributes.end())
865 currentMapOfAttributes[filename] = new ROSEAttributesList();
866 currentMapOfAttributes.find(filename)->second->addElement(*(new PreprocessingInfo(inclDir, PreprocessingInfo::before ) ));
867 break;
868 }
869 return false;
870 }
871#endif
872
873#endif
874
875
void found_directive(TokenT const &directive)
bool found_directive(TokenT const &directive, ContainerT const &expression, bool expression_value)
For preprocessing information including source comments, include , if, define, etc.
This class represents a source file for a project (which may contian many source files and or directo...
This class represents the base class for all IR nodes within Sage III.
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...
This class represents the location of the code associated with the IR node in the original source cod...
void copy(const Word *src, const BitRange &srcRange, Word *dst, const BitRange &dstRange)
Copy some bits.