ROSE 0.11.145.192
advanced_preprocessing_hooks.h
1/*=============================================================================
2 Boost.Wave: A Standard compliant C++ preprocessor library
3 http://www.boost.org/
4
5 Copyright (c) 2001-2005 Hartmut Kaiser. Distributed under the Boost
6 Software License, Version 1.0. (See accompanying file
7 LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8=============================================================================*/
9
10#if !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
11#define BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED
12
13// ROSE standard include files
14
15#include <cstdio>
16#include <ostream>
17#include <string>
18
19#include <boost/assert.hpp>
20#include <boost/config.hpp>
21
22#include <boost/wave/token_ids.hpp>
23#include <boost/wave/util/macro_helpers.hpp>
24#include <boost/wave/preprocessing_hooks.hpp>
25
26#include "attributeListMap.h"
27
28#define ROSE_WAVE_PSEUDO_FILE "<rose wave fix>"
29
30#if 0
31namespace {
32
33 char const *get_directivename(boost::wave::token_id id)
34 {
35 using namespace boost::wave;
36 switch (static_cast<unsigned int>(id)) {
37 case T_PP_IFDEF: return "#ifdef";
38 case T_PP_IFNDEF: return "#ifndef";
39 case T_PP_IF: return "#if";
40 case T_PP_ELSE: return "#else";
41 case T_PP_ELIF: return "#elif";
42 case T_PP_ENDIF: return "#endif";
43 default:
44 return "#unknown directive";
45 }
46 }
47}
48
49#endif
50
52//
53// The advanced_preprocessing_hooks policy class is used to register some
54// of the more advanced (and probably more rarely used hooks with the Wave
55// library.
56//
57// This policy type is used as a template parameter to the boost::wave::context<>
58// object.
59//
61//template<typename ContextT>
63: public boost::wave::context_policies::default_preprocessing_hooks
64{
65
66public:
67 AttributeListMap* attributeListMap;
68 std::list< token_type > tokens;
69
70 token_type lastPreprocDirective;
71 int numberOfIfs;
72
73 std::string includeDirective;
74 token_type includeDirectiveToken;
75 bool skipping;
76 bool updatingLastToken;
77 token_type last_token;
79 : attributeListMap(NULL)
80 , tokens()
81 , lastPreprocDirective()
82 , numberOfIfs(0)
83 , includeDirective()
84 , skipping(false)
85 , updatingLastToken(false)
86 { }
87
88
89
91 //
92 //Note from AS:
93 //The typename ContainerT is often equivalent to list<TokenT>.
94 //TokentT is often equivalent to boost::wave::cpplexer::lex_token<>
95 //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
96 //
98
99
100
101
103 //
104 // The function 'expanding_function_like_macro' is called, whenever a
105 // function-like macro is to be expanded.
106 //
107 // The macroname parameter marks the position, where the macro to expand
108 // is defined.
109 // The formal_args parameter holds the formal arguments used during the
110 // definition of the macro.
111 // The definition parameter holds the macro definition for the macro to
112 // trace.
113 //
114 // The macro call parameter marks the position, where this macro invoked.
115 // The arguments parameter holds the macro arguments used during the
116 // invocation of the macro
117 //
119
120 template <typename ContextT, typename TokenT, typename ContainerT, typename IteratorT>
121 bool expanding_function_like_macro(ContextT const&,
122 TokenT const& macrodef, std::vector<TokenT> const& formal_args,
123 ContainerT const& definition,
124 TokenT const& macrocall, std::vector<ContainerT> const& arguments,
125 IteratorT const&/*seqstart*/, IteratorT const&/*seqend*/)
126 {
128 //
129 //Note from AS:
130 //The typename ContainerT is often equivalent to list<TokenT>.
131 //TokentT is often equivalent to boost::wave::cpplexer::lex_token<>
132 //found in boost_1_33_0/boost/wave/cpplexer/cpp_lex_token.hpp.
133 //
135
136 attributeListMap->expanding_function_like_macro(macrodef, formal_args, definition, macrocall, arguments);
137
138 return false;
139 }
140
142 //
143 // The function 'expanding_object_like_macro' is called, whenever a
144 // object-like macro is to be expanded .
145 //
146 // The macroname parameter marks the position, where the macro to expand
147 // is defined.
148 // The definition parameter holds the macro definition for the macro to
149 // trace.
150 //
151 // The macro call parameter marks the position, where this macro invoked.
152 //
154
155 template <typename ContextT, typename TokenT, typename ContainerT>
156 bool expanding_object_like_macro(ContextT const& ctx, TokenT const& macro,
157 ContainerT const& definition, TokenT const& macrocall)
158 {
159 attributeListMap->expanding_object_like_macro(macro, definition, macrocall);
160 return false;
161 }
162
164 //
165 // The function 'expanded_macro' is called, whenever the expansion of a
166 // macro is finished but before the rescanning process starts.
167 //
168 // The parameter 'result' contains the token sequence generated as the
169 // result of the macro expansion.
170 //
172 template <typename ContextT, typename ContainerT>
173 void expanded_macro(ContextT const&, ContainerT const& result)
174 {
175 attributeListMap->expanded_macro(result);
176 }
177
179 //
180 // The function 'rescanned_macro' is called, whenever the rescanning of a
181 // macro is finished.
182 //
183 // The parameter 'result' contains the token sequence generated as the
184 // result of the rescanning.
185 //
187 template <typename ContextT, typename ContainerT>
188 void rescanned_macro(ContextT const&, ContainerT const& result)
189 {
190 attributeListMap->rescanned_macro(result);
191 }
192
194 //
195 // The function 'found_include_directive' is called, whenever a #include
196 // directive was located.
197 //
198 // The parameter 'filename' contains the (expanded) file name found after
199 // the #include directive. This has the format '<file>', '"file"' or
200 // 'file'.
201 // The formats '<file>' or '"file"' are used for #include directives found
202 // in the preprocessed token stream, the format 'file' is used for files
203 // specified through the --force_include command line argument.
204 //
205 // The parameter 'include_next' is set to true if the found directive was
206 // a #include_next directive and the BOOST_WAVE_SUPPORT_INCLUDE_NEXT
207 // preprocessing constant was defined to something != 0.
208 //
210
211 template <typename ContextT>
212 bool
213 found_include_directive(ContextT const&, std::string const& filename, bool /*include_next*/)
214 {
215 if(SgProject::get_verbose() >= 1)
216 std::cout << "Found include directive: " << filename << std::endl;
217
218 includeDirective = filename;
219 return false;
220 }
221
223 //
224 // The function 'opened_include_file' is called, whenever a file referred
225 // by an #include directive was successfully located and opened.
226 //
227 // The parameter 'filename' contains the file system path of the
228 // opened file (this is relative to the directory of the currently
229 // processed file or a absolute path depending on the paths given as the
230 // include search paths).
231 //
232 // The include_depth parameter contains the current include file depth.
233 //
234 // The is_system_include parameter denotes, whether the given file was
235 // found as a result of a #include <...> directive.
236 //
238 template <typename ContextT>
239 void
240 opened_include_file(ContextT const&, std::string const& relname,
241 std::string const& absname, bool /*is_system_include*/)
242 {
243
244 if(SgProject::get_verbose() >= 1){
245 std::cout << "openend include file relname: " << relname << " absname: " << absname << std::endl;
246 std::cout << "it is connected to : " << includeDirective << std::endl;
247 }
248 attributeListMap->found_include_directive(includeDirectiveToken, relname, absname);
249 }
250
252 //
253 // The function 'returning_from_include_file' is called, whenever an
254 // included file is about to be closed after it's processing is complete.
255 //
257 // new signature
258 template <typename ContextT>
259 void
260 returning_from_include_file(ContextT const&)
261 {}
262
264 //
265 // The function 'interpret_pragma' is called, whenever a #pragma wave
266 // directive is found, which isn't known to the core Wave library.
267 //
268 // The parameter 'ctx' is a reference to the context object used for
269 // instantiating the preprocessing iterators by the user.
270 //
271 // The parameter 'pending' may be used to push tokens back into the input
272 // stream, which are to be used as the replacement text for the whole
273 // #pragma wave() directive.
274 //
275 // The parameter 'option' contains the name of the interpreted pragma.
276 //
277 // The parameter 'values' holds the values of the parameter provided to
278 // the pragma operator.
279 //
280 // The parameter 'act_token' contains the actual #pragma token, which may
281 // be used for error output.
282 //
283 // If the return value is 'false', the whole #pragma directive is
284 // interpreted as unknown and a corresponding error message is issued. A
285 // return value of 'true' signs a successful interpretation of the given
286 // #pragma.
287 //
289 template <typename ContextT, typename ContainerT>
290 bool
291 interpret_pragma(ContextT const&, ContainerT &/*pending*/,
292 typename ContextT::token_type const &/*option*/, ContainerT const &/*values*/,
293 typename ContextT::token_type const &/*act_token*/)
294 {
295 return false;
296 }
297
299 //
300 // The function 'defined_macro' is called, whenever a macro was defined
301 // successfully.
302 //
303 // The parameter 'name' is a reference to the token holding the macro name.
304 //
305 // The parameter 'is_functionlike' is set to true, whenever the newly
306 // defined macro is defined as a function like macro.
307 //
308 // The parameter 'parameters' holds the parameter tokens for the macro
309 // definition. If the macro has no parameters or if it is a object like
310// macro, then this container is empty.
311 //
312 // The parameter 'definition' contains the token sequence given as the
313 // replacement sequence (definition part) of the newly defined macro.
314 //
315 // The parameter 'is_predefined' is set to true for all macros predefined
316 // during the initialisation phase of the library.
317 //
319 template <typename ContextT, typename TokenT, typename ParametersT,
320 typename DefinitionT>
321 void
322 defined_macro(ContextT const&, TokenT const& macro_name,
323 bool is_functionlike, ParametersT const& parameters,
324 DefinitionT const& definition, bool is_predefined)
325 {
326#if 0
327// The "#if 0" was already here, but I also commented these lines out because '{' and '}' do not balance otherwise. The
328// unbalanced braces cause some problems for some tools (indenting, automatic enum detection, etc) [RPM 2010-10-11]
329// string name(macro_name.get_value().c_str());
330// //add all macros which is not a builtin macro to ROSE attribute
331// if(! (name.substr(0,2)=="__")
332// //&&(name.substr(name.length()-2,name.length())=="__"))
333// ){
334// //AS(041906) Filter out macros defined on the commandline as they are not
335// //part of a file and is therefore not interesting for macro-rewrapping.
336#endif
337 //if(is_predefined!=true)
338 if( macro_name.get_position().get_file().size()!=0 )
339 {
340 if( (macro_name.get_position().get_file()!="<built-in>") )
341 {
342 attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
343
344 }
345 }
346 else
347 {
348 attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
349 }
350
351
352 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
353 tokens.push_back(space);
354 tokens.push_back(macro_name);
355
356 boost::wave::util::file_position_type filepos;
357 if (
358 macro_name.get_position().get_file().find("<default>") == std::string::npos &&
359 macro_name.get_position().get_file().find("<built-in>") == std::string::npos &&
360 macro_name.get_position().get_file().find("<command line>") == std::string::npos &&
361 macro_name.get_position().get_file().find("rose_edg_required_macros_and_functions") == std::string::npos)
362 filepos = boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0);
363 else
364 filepos = boost::wave::util::file_position_type(macro_name.get_position().get_file(), 0, 0);
365
366 if (is_functionlike)
367 {
368 token_type left = token_type(boost::wave::T_LEFTPAREN, "(", filepos);
369 tokens.push_back(left);
370 bool first = true;
371 for (typename ParametersT::const_iterator i = parameters.begin(); i != parameters.end(); ++i)
372 {
373 if (!first)
374 {
375 token_type comma = token_type(boost::wave::T_COMMA, ",", filepos);
376 tokens.push_back(comma);
377 }
378 tokens.push_back(*i);
379 first = false;
380 }
381 token_type right = token_type(boost::wave::T_RIGHTPAREN, ")", filepos);
382 tokens.push_back(right);
383 }
384 token_type space2 = token_type(boost::wave::T_SPACE, " ", filepos);
385 tokens.push_back(space2);
386 for (typename DefinitionT::const_iterator i = definition.begin(); i != definition.end(); ++i)
387 {
388 token_type space = token_type(boost::wave::T_SPACE, " ", filepos);
389 tokens.push_back(space);
390 tokens.push_back(*i);
391 }
392
393 }
394
395
397 //
398 // The function 'found_directive' is called, whenever a preprocessor
399 // directive was encountered, but before the corresponding action is
400 // executed.
401 //
402 // The parameter 'directive' is a reference to the token holding the
403 // preprocessing directive.
404 //
406 template <typename ContextT, typename TokenT>
407 bool
408 found_directive(ContextT const&, TokenT const& directive)
409 {
410 if(SgProject::get_verbose() >= 1)
411 std::cout << "found_directive!" << std::endl;
412
413 skipping = false;
414 lastPreprocDirective = directive;
415 // print the commented conditional directives
416 using namespace boost::wave;
417 token_id id = token_id(directive);
418
419 bool record = true;
420 switch(id)
421 {
422 case T_PP_LINE: //#line
423 case T_PP_UNDEF: //#undef
424 case T_PP_WARNING: //#warning
425 case T_PP_DEFINE: //#define
426 record = false;
427 break; // handled via lastPreprocDirective in their own methods
428 case T_PP_IF: //#if
429 case T_PP_IFDEF: //#ifdef
430 case T_PP_IFNDEF: //#ifndef
431 case T_PP_ELSE: //#else
432 case T_PP_ELIF: //#elif
433 break; // appended too as necessary in skipped_token and evaluated_conditional_expression
434 case T_PP_ENDIF: //#endif
435 case T_PP_ERROR: //#error
436 case T_PP_PRAGMA: //#pragma
437 case T_PP_INCLUDE: //#include \"...\"
438 break;
439 case T_PP_QHEADER: //#include <...>
440 case T_PP_HHEADER: //#include ...
441 break;
442 default: //<something else (" << directive.get_value() << ")>
443 break;
444 }
445 if (record)
446 attributeListMap->found_directive(directive);
447
448 attributeListMap->flush_token_stream();
449 updatingLastToken = true;
450
451 if(SgProject::get_verbose() >= 1)
452 {
453 switch(id)
454 {
455 case T_PP_DEFINE: std::cout << "Directive is: #define\n"; break;
456 case T_PP_IF: std::cout << "Directive is: #if\n"; break;
457 case T_PP_IFDEF: std::cout << "Directive is: #ifdef\n"; break;
458 case T_PP_IFNDEF: std::cout << "Directive is: #ifndef\n"; break;
459 case T_PP_ELSE: std::cout << "Directive is: #else\n"; break;
460 case T_PP_ELIF: std::cout << "Directive is: #elif\n"; break;
461 case T_PP_ENDIF: std::cout << "Directive is: #endif\n"; break;
462 case T_PP_ERROR: std::cout << "Directive is: #error\n"; break;
463 case T_PP_LINE: std::cout << "Directive is: #line\n"; break;
464 case T_PP_PRAGMA: std::cout << "Directive is: #pragma\n"; break;
465 case T_PP_UNDEF: std::cout << "Directive is: #undef\n"; break;
466 case T_PP_WARNING: std::cout << "Directive is: #warning\n"; break;
467 case T_PP_INCLUDE: std::cout << "Directive is: #include \"...\"\n"; break;
468 case T_PP_QHEADER: std::cout << "Directive is: #include <...>\n"; break;
469 case T_PP_HHEADER: std::cout << "Directive is: #include ...\n"; break;
470 default: std::cout << "Directive is: <something else>\n"; break;
471 }
472 }
473
474 last_token = directive;
475 tokens.push_back(directive);
476 return false;
477 }
478
480 //
481 // The function 'generated_token' is called, whenever a token is about
482 // to be returned from the library
483 //
485 template <typename ContextT, typename TokenT>
486 TokenT const& generated_token(ContextT const&, TokenT const& token)
487 {
488 if(SgProject::get_verbose() >= 1)
489 std::cout << "Generating token: ";
490
491 using namespace boost::wave;
492 token_id id = token_id(token);
493
494 if(SgProject::get_verbose() >= 1)
495 {
496 switch(id)
497 {
498 case T_PP_DEFINE: std::cout << "#define: "; break;
499 case T_PP_IF: std::cout << "#if: "; break;
500 case T_PP_IFDEF: std::cout << "#ifdef: "; break;
501 case T_PP_IFNDEF: std::cout << "#ifndef: "; break;
502 case T_PP_ELSE: std::cout << "#else: "; break;
503 case T_PP_ELIF: std::cout << "#elif: "; break;
504 case T_PP_ENDIF: std::cout << "#endif: "; break;
505 case T_PP_ERROR: std::cout << "#error: "; break;
506 case T_PP_LINE: std::cout << "#line: "; break;
507 case T_PP_PRAGMA: std::cout << "#pragma: "; break;
508 case T_PP_UNDEF: std::cout << "#undef: "; break;
509 case T_PP_WARNING: std::cout << "#warning: "; break;
510 case T_PP_INCLUDE: std::cout << "#include \"...\": "; break;
511 case T_PP_QHEADER: std::cout << "#include <...>: "; break;
512 case T_PP_HHEADER: std::cout << "#include ...: "; break;
513 default: std::cout << "<something else (" << id << ")>: "; break;
514 }
515// std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
516 if (token != token_type())
517 std::cout << token.get_value().c_str() << std::endl;
518 }
519 return token;
520 }
521
523 //
524 // The function 'evaluated_conditional_expression' is called, whenever a
525 // conditional preprocessing expression was evaluated (the expression
526 // given to a #if, #ifdef or #ifndef directive)
527 //
528 // The parameter 'expression' holds the non-expanded token sequence
529 // comprising the evaluated expression.
530 //
531 // The parameter expression_value contains the result of the evaluation of
532 // the expression in the current preprocessing context.
533 //
535 template <typename ContextT, typename TokenT, typename ContainerT>
536 bool
537 evaluated_conditional_expression(ContextT const&, TokenT const& directive, ContainerT const& expression,
538 bool expression_value)
539 {
540 using namespace boost::wave;
541 token_id id = token_id(directive);
542
543 ROSE_ASSERT(directive == lastPreprocDirective);
544
545 if(SgProject::get_verbose() >= 1)
546 {
547 std::cout << "Conditional: ";
548 switch(id)
549 {
550 case T_PP_DEFINE: std::cout << "#define: "; break;
551 case T_PP_IF: std::cout << "#if: "; break;
552 case T_PP_IFDEF: std::cout << "#ifdef: "; break;
553 case T_PP_IFNDEF: std::cout << "#ifndef: "; break;
554 case T_PP_ELSE: std::cout << "#else: "; break;
555 case T_PP_ELIF: std::cout << "#elif: "; break;
556 case T_PP_ENDIF: std::cout << "#endif: "; break;
557 case T_PP_ERROR: std::cout << "#error: "; break;
558 case T_PP_LINE: std::cout << "#line: "; break;
559 case T_PP_PRAGMA: std::cout << "#pragma: "; break;
560 case T_PP_UNDEF: std::cout << "#undef: "; break;
561 case T_PP_WARNING: std::cout << "#warning: "; break;
562 case T_PP_INCLUDE: std::cout << "#include \"...\": "; break;
563 case T_PP_QHEADER: std::cout << "#include <...>: "; break;
564 case T_PP_HHEADER: std::cout << "#include ...: "; break;
565 default: std::cout << "<something else (" << id << ")>: "; break;
566 }
567// std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
568 std::cout << directive.get_value().c_str() << std::endl;
569 }
570 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
571 token_container whitespace;
572 whitespace.push_back(space);
573 // directive was already given up in found_directive. here we add to the expression
574 attributeListMap->update_token(lastPreprocDirective, whitespace, expression_value);
575 attributeListMap->update_token(lastPreprocDirective, expression, expression_value);
576
577// tokens.push_back(space);
578 for (typename ContainerT::const_iterator i = expression.begin(); i != expression.end(); ++i)
579 {
580 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
581 tokens.push_back(space);
582 tokens.push_back(*i);
583 }
584
585 token_type newline = token_type(boost::wave::T_NEWLINE, "\n", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
586 token_container whitespace2;
587 whitespace2.push_back(newline);
588 attributeListMap->update_token(lastPreprocDirective, whitespace2, expression_value);
589
590 // King84 (2010.09.09):
591 // Tell later guys to update the previous token as soon as we start skipping
592 // This is important to associate conditions with skipped #elif directives
593 updatingLastToken = true;
594
595 last_token = directive;
596 return false; // ok to continue, do not re-evaluate expression
597 }
598
600 //
601 // The function 'skipped_token' is called, whenever a token is about to be
602 // skipped due to a false preprocessor condition (code fragments to be
603 // skipped inside the not evaluated conditional #if/#else/#endif branches).
604 //
605 // The parameter 'token' refers to the token to be skipped.
606 //
607 //
609 template <typename ContextT, typename TokenT>
610 void
611 skipped_token(ContextT const&, TokenT const& token)
612 {
613 using namespace boost::wave;
614 //Process all tokens to be skipped except the ones without a filename,
615 //e.g macro definitions from the commandline
616 if (token.get_position().get_file().size() == 0)
617 return;
618 if (token == last_token && token.get_position() == last_token.get_position())
619 return;
620
621 token_id id = token_id(token);
622 token_id lastid = token_id(lastPreprocDirective);
623 if (lastPreprocDirective == token_type())
624 {
625 attributeListMap->skipped_token(token);
626 }
627 else if (token != lastPreprocDirective)
628 {
629 tokens.push_back(token);
630
631 if (id == T_NEWLINE) // if it's a newline, it's the end of the previous token not that trailing-slash linesare already taken into account by wave
632 updatingLastToken = false;
633
634 // This is if we have to associated skipped tokens with a previous token. We do this for the last directive until we get a newline
635 if (updatingLastToken)
636 {
637 token_container tc;
638 tc.push_back(token);
639 if(SgProject::get_verbose() >= 1)
640 std::cout << "Updating previous token (" << lastPreprocDirective.get_value().c_str() << ") with token " << token.get_value().c_str() << std::endl;
641 attributeListMap->update_token(lastPreprocDirective, tc, false);
642 }
643 else if (skipping || (lastid != T_PP_IF && lastid != T_PP_IFDEF && lastid != T_PP_IFNDEF && lastid != T_PP_ELIF)) // if we skipped the first newline
644 {
645 attributeListMap->skipped_token(token);
646 }
647 }
648
649 switch(id)
650 {
651 case T_PP_DEFINE:
652 case T_PP_IF:
653 case T_PP_IFDEF:
654 case T_PP_IFNDEF:
655 case T_PP_ELSE:
656 case T_PP_ELIF:
657 case T_PP_ENDIF:
658 case T_PP_ERROR:
659 case T_PP_LINE:
660 case T_PP_PRAGMA:
661 case T_PP_UNDEF:
662 case T_PP_WARNING:
663 case T_PP_INCLUDE:
664 case T_PP_QHEADER:
665 case T_PP_HHEADER:
666 lastPreprocDirective = token; // since found_directive doesn't get called
667 break;
668 default:
669 break;
670 }
671
672 if(SgProject::get_verbose() >= 1)
673 {
674 switch(id)
675 {
676 case T_PP_DEFINE: std::cout << "Skipped: #define\n"; break;
677 case T_PP_IF: std::cout << "Skipped: #if\n"; break;
678 case T_PP_IFDEF: std::cout << "Skipped: #ifdef\n"; break;
679 case T_PP_IFNDEF: std::cout << "Skipped: #ifndef\n"; break;
680 case T_PP_ELSE: std::cout << "Skipped: #else\n"; break;
681 case T_PP_ELIF: std::cout << "Skipped: #elif\n"; break;
682 case T_PP_ENDIF: std::cout << "Skipped: #endif\n"; break;
683 case T_PP_ERROR: std::cout << "Skipped: #error\n"; break;
684 case T_PP_LINE: std::cout << "Skipped: #line\n"; break;
685 case T_PP_PRAGMA: std::cout << "Skipped: #pragma\n"; break;
686 case T_PP_UNDEF: std::cout << "Skipped: #undef\n"; break;
687 case T_PP_WARNING: std::cout << "Skipped: #warning\n"; break;
688 case T_PP_INCLUDE: std::cout << "Skipped: #include \"...\"\n"; break;
689 case T_PP_QHEADER: std::cout << "Skipped: #include <...>\n"; break;
690 case T_PP_HHEADER: std::cout << "Skipped: #include ...\n"; break;
691 default: std::cout << "Skipped: <something else (" << token.get_value().c_str() << ")>\n"; break;
692 }
693 if (lastPreprocDirective != token_type())
694 std::cout << "\tskipping is " << skipping << "\tupdatingLastToken is " << updatingLastToken << "\tlastPreprocDirective is " << lastPreprocDirective.get_value().c_str() << std::endl;
695 }
696 skipping = true; // skipping lets us skip the extra newline that shows up after #if statements
697 last_token = token;
698 }
699
701 //
702 // The function 'undefined_macro' is called, whenever a macro definition
703 // was removed successfully.
704 //
705 // The parameter 'name' holds the name of the macro, which definition was
706 // removed.
707 //
709 template <typename ContextT, typename TokenT>
710 void
711 undefined_macro(ContextT const&, TokenT const& macro_name)
712 {
713 token_list_container tokListCont;
714 tokListCont.push_back(macro_name);
715 attributeListMap->found_directive(lastPreprocDirective,tokListCont, false);
716
717 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
718 tokens.push_back(space);
719 tokens.push_back(macro_name);
720 }
721
722#if 0
723 template <typename ContainerT>
724 void
725 on_warning(ContainerT const& tokenStream)
726 {
727 attributeListMap->found_directive(lastPreprocDirective,tokenStream, false);
728
729 std::cout << "ON TOKEN WARNING: " << boost::wave::util::impl::as_string(tokenStream) << std::endl;
730 }
731#endif
732
734 //
735 // The function 'found_warning_directive' is called, will be called by the
736 // library, whenever a #warning directive is found.
737 //
738 // The parameter 'ctx' is a reference to the context object used for
739 // instantiating the preprocessing iterators by the user.
740 //
741 // The parameter 'message' references the argument token sequence of the
742 // encountered #warning directive.
743 //
745 template <typename ContextT, typename ContainerT>
746 bool
747 found_warning_directive(ContextT const&, ContainerT const& message)
748 {
749 attributeListMap->found_directive(lastPreprocDirective,message, false);
750
751 if(SgProject::get_verbose() >= 1)
752 std::cout << "ON TOKEN WARNING: " << boost::wave::util::impl::as_string(message) << std::endl;
753
754 //Do not throw warning message
755 return true;
756 }
757
758
760 //
761 // The function 'found_line_directive' will be called by the library
762 // whenever a #line directive is found.
763 //
764 // The parameter 'ctx' is a reference to the context object used for
765 // instantiating the preprocessing iterators by the user.
766 //
767 // The parameter 'arguments' references the argument token sequence of the
768 // encountered #line directive.
769 //
770 // The parameter 'line' contains the recognized line number from the #line
771 // directive.
772 //
773 // The parameter 'filename' references the recognized file name from the
774 // #line directive (if there was one given).
775 //
777 template <typename ContextT, typename ContainerT>
778 void
779 found_line_directive(ContextT const&, ContainerT const& arguments, unsigned int, std::string const& filename)
780 {
781 std::string filenameString(filename.c_str());
782
783 if (SgProject::get_verbose() >= 1)
784 std::cout << "On line found" << std::endl;
785 /*
786 token_list_container toexpand;
787 std::copy(first, make_ref_transform_iterator(end, boost::wave::util::get_value),
788 std::inserter(toexpand, toexpand.end()));
789 */
790
791 attributeListMap->found_directive(lastPreprocDirective,arguments, false);
792
793 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
794 token_container whitespace;
795 whitespace.push_back(space);
796 // directive was already given up in found_directive. here we add to it the arguments
797 attributeListMap->update_token(lastPreprocDirective, whitespace, false);
798 attributeListMap->update_token(lastPreprocDirective, arguments, false);
799
800// tokens.push_back(space);
801 for (typename ContainerT::const_iterator i = arguments.begin(); i != arguments.end(); ++i)
802 {
803 token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
804 tokens.push_back(space);
805 tokens.push_back(*i);
806 }
807 }
808
809
810 template <typename ContextT, typename TokenT>
811 bool
812 may_skip_whitespace(ContextT const& ctx, TokenT& token, bool& skipped_newline)
813 {
814 if (token == lastPreprocDirective && token.get_position() == lastPreprocDirective.get_position())
815 return false;
816 if (token == last_token && token.get_position() == last_token.get_position())
817 return false;
818 if (SgProject::get_verbose() >= 1)
819 if (token != TokenT())
820 std::cout << "MAX_SKIP_WHITESPACE: " << token.get_value().c_str() << std::endl;
821
822 using namespace boost::wave;
823 token_id id = token_id(token);
824 if (id != T_EOF && id != T_EOI)
825 tokens.push_back(token);
826 if (id != T_EOF && id != T_EOI && id != T_NEWLINE)
827 {
828 if (SgProject::get_verbose() >= 1)
829 std::cout << "Normal reported" << std::endl;
830 attributeListMap->may_skip_whitespace(ctx, token, skipped_newline);
831 }
832 else if (skipping) // then we need to flush tokens
833 {
834 if (SgProject::get_verbose() >= 1)
835 std::cout << "Skip leads to flushing" << std::endl;
836 attributeListMap->flush_token_stream();
837 }
838 else
839 {
840 if (SgProject::get_verbose() >= 1)
841 std::cout << "EOF or newline leads to flushing" << std::endl;
842 attributeListMap->flush_token_stream();
843 }
844 return false;
845 }
846
847 template <typename ContextT, typename ExceptionT>
848 void throw_exception(ContextT const&, ExceptionT const&)
849 {
850 if (SgProject::get_verbose() >= 1)
851 std::cout << "THROW_EXCEPTION" << std::endl;
852 }
853
854 template <typename ContextT>
855 void detected_include_guard(ContextT const&, std::string const& filename, std::string const& include_guard)
856 {
857 if (SgProject::get_verbose() >= 1)
858 std::cout << "DETECTED_INCLUDE_GUARD" << include_guard << " in file " << filename << std::endl;
859 }
860
861 template <typename ContextT, typename TokenT>
862 void detected_pragma_once(ContextT const&, TokenT const& pragma_token, std::string const& filename)
863 {
864 if (SgProject::get_verbose() >= 1)
865 std::cout << "DETECTED_PRAGMA_ONCE " << pragma_token.get_value() << " in file " << filename << std::endl;
866 }
867
868 template <typename ContextT, typename ContainerT>
869 bool found_error_directive(ContextT const&, ContainerT const&)
870 {
871 if (SgProject::get_verbose() >= 1)
872 std::cout << "FOUND_ERROR_DIRECTIVE" << std::endl;
873 return false;
874 }
875
876
877#if 0
878 bool need_comment;
879#endif
880};
881
882#endif // !defined(BOOST_WAVE_ADVANCED_PREPROCESSING_HOOKS_INCLUDED)
883
bool found_directive(TokenT const &directive, ContainerT const &expression, bool expression_value)
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...