ROSE  0.11.145.0
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
31 namespace {
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 
66 public:
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& ctx,
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& ctx, 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& ctx, 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& ctx, std::string const& filename,
214  bool include_next)
215  {
216  if(SgProject::get_verbose() >= 1)
217  std::cout << "Found include directive: " << filename << std::endl;
218 
219  includeDirective = filename;
220  return false;
221  }
222 
224  //
225  // The function 'opened_include_file' is called, whenever a file referred
226  // by an #include directive was successfully located and opened.
227  //
228  // The parameter 'filename' contains the file system path of the
229  // opened file (this is relative to the directory of the currently
230  // processed file or a absolute path depending on the paths given as the
231  // include search paths).
232  //
233  // The include_depth parameter contains the current include file depth.
234  //
235  // The is_system_include parameter denotes, whether the given file was
236  // found as a result of a #include <...> directive.
237  //
239  template <typename ContextT>
240  void
241  opened_include_file(ContextT const& ctx, std::string const& relname,
242  std::string const& absname, bool is_system_include)
243  {
244 
245  if(SgProject::get_verbose() >= 1){
246  std::cout << "openend include file relname: " << relname << " absname: " << absname << std::endl;
247  std::cout << "it is connected to : " << includeDirective << std::endl;
248  }
249  attributeListMap->found_include_directive(includeDirectiveToken, relname, absname);
250  }
251 
253  //
254  // The function 'returning_from_include_file' is called, whenever an
255  // included file is about to be closed after it's processing is complete.
256  //
258  // new signature
259  template <typename ContextT>
260  void
261  returning_from_include_file(ContextT const& ctx)
262  {}
263 
265  //
266  // The function 'interpret_pragma' is called, whenever a #pragma wave
267  // directive is found, which isn't known to the core Wave library.
268  //
269  // The parameter 'ctx' is a reference to the context object used for
270  // instantiating the preprocessing iterators by the user.
271  //
272  // The parameter 'pending' may be used to push tokens back into the input
273  // stream, which are to be used as the replacement text for the whole
274  // #pragma wave() directive.
275  //
276  // The parameter 'option' contains the name of the interpreted pragma.
277  //
278  // The parameter 'values' holds the values of the parameter provided to
279  // the pragma operator.
280  //
281  // The parameter 'act_token' contains the actual #pragma token, which may
282  // be used for error output.
283  //
284  // If the return value is 'false', the whole #pragma directive is
285  // interpreted as unknown and a corresponding error message is issued. A
286  // return value of 'true' signs a successful interpretation of the given
287  // #pragma.
288  //
290  template <typename ContextT, typename ContainerT>
291  bool
292  interpret_pragma(ContextT const &ctx, ContainerT &pending,
293  typename ContextT::token_type const &option, ContainerT const &values,
294  typename ContextT::token_type const &act_token)
295  {
296  return false;
297  }
298 
300  //
301  // The function 'defined_macro' is called, whenever a macro was defined
302  // successfully.
303  //
304  // The parameter 'name' is a reference to the token holding the macro name.
305  //
306  // The parameter 'is_functionlike' is set to true, whenever the newly
307  // defined macro is defined as a function like macro.
308  //
309  // The parameter 'parameters' holds the parameter tokens for the macro
310  // definition. If the macro has no parameters or if it is a object like
311 // macro, then this container is empty.
312  //
313  // The parameter 'definition' contains the token sequence given as the
314  // replacement sequence (definition part) of the newly defined macro.
315  //
316  // The parameter 'is_predefined' is set to true for all macros predefined
317  // during the initialisation phase of the library.
318  //
320  template <typename ContextT, typename TokenT, typename ParametersT,
321  typename DefinitionT>
322  void
323  defined_macro(ContextT const& ctx, TokenT const& macro_name,
324  bool is_functionlike, ParametersT const& parameters,
325  DefinitionT const& definition, bool is_predefined)
326  {
327 #if 0
328 // The "#if 0" was already here, but I also commented these lines out because '{' and '}' do not balance otherwise. The
329 // unbalanced braces cause some problems for some tools (indenting, automatic enum detection, etc) [RPM 2010-10-11]
330 // string name(macro_name.get_value().c_str());
331 // //add all macros which is not a builtin macro to ROSE attribute
332 // if(! (name.substr(0,2)=="__")
333 // //&&(name.substr(name.length()-2,name.length())=="__"))
334 // ){
335 // //AS(041906) Filter out macros defined on the commandline as they are not
336 // //part of a file and is therefore not interesting for macro-rewrapping.
337 #endif
338  //if(is_predefined!=true)
339  if( macro_name.get_position().get_file().size()!=0 )
340  {
341  if( (macro_name.get_position().get_file()!="<built-in>") )
342  {
343  attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
344 
345  }
346  }
347  else
348  {
349  attributeListMap->defined_macro(macro_name, is_functionlike, parameters, definition, is_predefined);
350  }
351 
352 
353  token_type space = token_type(boost::wave::T_SPACE, " ", boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0));
354  tokens.push_back(space);
355  tokens.push_back(macro_name);
356 
357  boost::wave::util::file_position_type filepos;
358  if (
359  macro_name.get_position().get_file().find("<default>") == std::string::npos &&
360  macro_name.get_position().get_file().find("<built-in>") == std::string::npos &&
361  macro_name.get_position().get_file().find("<command line>") == std::string::npos &&
362  macro_name.get_position().get_file().find("rose_edg_required_macros_and_functions") == std::string::npos)
363  filepos = boost::wave::util::file_position_type(BOOST_WAVE_STRINGTYPE(ROSE_WAVE_PSEUDO_FILE), 0, 0);
364  else
365  filepos = boost::wave::util::file_position_type(macro_name.get_position().get_file(), 0, 0);
366 
367  if (is_functionlike)
368  {
369  token_type left = token_type(boost::wave::T_LEFTPAREN, "(", filepos);
370  tokens.push_back(left);
371  bool first = true;
372  for (typename ParametersT::const_iterator i = parameters.begin(); i != parameters.end(); ++i)
373  {
374  if (!first)
375  {
376  token_type comma = token_type(boost::wave::T_COMMA, ",", filepos);
377  tokens.push_back(comma);
378  }
379  tokens.push_back(*i);
380  first = false;
381  }
382  token_type right = token_type(boost::wave::T_RIGHTPAREN, ")", filepos);
383  tokens.push_back(right);
384  }
385  token_type space2 = token_type(boost::wave::T_SPACE, " ", filepos);
386  tokens.push_back(space2);
387  for (typename DefinitionT::const_iterator i = definition.begin(); i != definition.end(); ++i)
388  {
389  token_type space = token_type(boost::wave::T_SPACE, " ", filepos);
390  tokens.push_back(space);
391  tokens.push_back(*i);
392  }
393 
394  }
395 
396 
398  //
399  // The function 'found_directive' is called, whenever a preprocessor
400  // directive was encountered, but before the corresponding action is
401  // executed.
402  //
403  // The parameter 'directive' is a reference to the token holding the
404  // preprocessing directive.
405  //
407  template <typename ContextT, typename TokenT>
408  bool
409  found_directive(ContextT const& ctx, TokenT const& directive)
410  {
411  if(SgProject::get_verbose() >= 1)
412  std::cout << "found_directive!" << std::endl;
413 
414  skipping = false;
415  lastPreprocDirective = directive;
416  // print the commented conditional directives
417  using namespace boost::wave;
418  token_id id = token_id(directive);
419 
420  bool record = true;
421  switch(id)
422  {
423  case T_PP_LINE: //#line
424  case T_PP_UNDEF: //#undef
425  case T_PP_WARNING: //#warning
426  case T_PP_DEFINE: //#define
427  record = false;
428  break; // handled via lastPreprocDirective in their own methods
429  case T_PP_IF: //#if
430  case T_PP_IFDEF: //#ifdef
431  case T_PP_IFNDEF: //#ifndef
432  case T_PP_ELSE: //#else
433  case T_PP_ELIF: //#elif
434  break; // appended too as necessary in skipped_token and evaluated_conditional_expression
435  case T_PP_ENDIF: //#endif
436  case T_PP_ERROR: //#error
437  case T_PP_PRAGMA: //#pragma
438  case T_PP_INCLUDE: //#include \"...\"
439  break;
440  case T_PP_QHEADER: //#include <...>
441  case T_PP_HHEADER: //#include ...
442  break;
443  default: //<something else (" << directive.get_value() << ")>
444  break;
445  }
446  if (record)
447  attributeListMap->found_directive(directive);
448 
449  attributeListMap->flush_token_stream();
450  updatingLastToken = true;
451 
452  if(SgProject::get_verbose() >= 1)
453  {
454  switch(id)
455  {
456  case T_PP_DEFINE: std::cout << "Directive is: #define\n"; break;
457  case T_PP_IF: std::cout << "Directive is: #if\n"; break;
458  case T_PP_IFDEF: std::cout << "Directive is: #ifdef\n"; break;
459  case T_PP_IFNDEF: std::cout << "Directive is: #ifndef\n"; break;
460  case T_PP_ELSE: std::cout << "Directive is: #else\n"; break;
461  case T_PP_ELIF: std::cout << "Directive is: #elif\n"; break;
462  case T_PP_ENDIF: std::cout << "Directive is: #endif\n"; break;
463  case T_PP_ERROR: std::cout << "Directive is: #error\n"; break;
464  case T_PP_LINE: std::cout << "Directive is: #line\n"; break;
465  case T_PP_PRAGMA: std::cout << "Directive is: #pragma\n"; break;
466  case T_PP_UNDEF: std::cout << "Directive is: #undef\n"; break;
467  case T_PP_WARNING: std::cout << "Directive is: #warning\n"; break;
468  case T_PP_INCLUDE: std::cout << "Directive is: #include \"...\"\n"; break;
469  case T_PP_QHEADER: std::cout << "Directive is: #include <...>\n"; break;
470  case T_PP_HHEADER: std::cout << "Directive is: #include ...\n"; break;
471  default: std::cout << "Directive is: <something else>\n"; break;
472  }
473  }
474 
475  last_token = directive;
476  tokens.push_back(directive);
477  return false;
478  }
479 
481  //
482  // The function 'generated_token' is called, whenever a token is about
483  // to be returned from the library
484  //
486  template <typename ContextT, typename TokenT>
487  TokenT const& generated_token(ContextT const& ctx, TokenT const& token)
488  {
489  if(SgProject::get_verbose() >= 1)
490  std::cout << "Generating token: ";
491 
492  using namespace boost::wave;
493  token_id id = token_id(token);
494 
495  if(SgProject::get_verbose() >= 1)
496  {
497  switch(id)
498  {
499  case T_PP_DEFINE: std::cout << "#define: "; break;
500  case T_PP_IF: std::cout << "#if: "; break;
501  case T_PP_IFDEF: std::cout << "#ifdef: "; break;
502  case T_PP_IFNDEF: std::cout << "#ifndef: "; break;
503  case T_PP_ELSE: std::cout << "#else: "; break;
504  case T_PP_ELIF: std::cout << "#elif: "; break;
505  case T_PP_ENDIF: std::cout << "#endif: "; break;
506  case T_PP_ERROR: std::cout << "#error: "; break;
507  case T_PP_LINE: std::cout << "#line: "; break;
508  case T_PP_PRAGMA: std::cout << "#pragma: "; break;
509  case T_PP_UNDEF: std::cout << "#undef: "; break;
510  case T_PP_WARNING: std::cout << "#warning: "; break;
511  case T_PP_INCLUDE: std::cout << "#include \"...\": "; break;
512  case T_PP_QHEADER: std::cout << "#include <...>: "; break;
513  case T_PP_HHEADER: std::cout << "#include ...: "; break;
514  default: std::cout << "<something else (" << id << ")>: "; break;
515  }
516 // std::cout << boost::wave::util::impl::as_string(token).c_str() << std::endl;
517  if (token != token_type())
518  std::cout << token.get_value().c_str() << std::endl;
519  }
520  return token;
521  }
522 
524  //
525  // The function 'evaluated_conditional_expression' is called, whenever a
526  // conditional preprocessing expression was evaluated (the expression
527  // given to a #if, #ifdef or #ifndef directive)
528  //
529  // The parameter 'expression' holds the non-expanded token sequence
530  // comprising the evaluated expression.
531  //
532  // The parameter expression_value contains the result of the evaluation of
533  // the expression in the current preprocessing context.
534  //
536  template <typename ContextT, typename TokenT, typename ContainerT>
537  bool
538  evaluated_conditional_expression(ContextT const& ctx, TokenT const& directive, ContainerT const& expression, 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& ctx, 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& ctx, 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& ctx, 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& ctx, ContainerT const& arguments, unsigned int line, 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 &ctx, ExceptionT const& e)
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 &ctx, 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 &ctx, 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 &ctx, ContainerT const &message)
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...