collect_hooks_information.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. http://www.boost.org/
  4. Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
  5. Software License, Version 1.0. (See accompanying file
  6. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_WAVE_LIBS_WAVE_TEST_COLLECT_HOOKS_INFORMATION_HPP)
  9. #define BOOST_WAVE_LIBS_WAVE_TEST_COLLECT_HOOKS_INFORMATION_HPP
  10. #include <boost/config.hpp>
  11. #include <boost/lexical_cast.hpp>
  12. #include <boost/filesystem/path.hpp>
  13. #include <boost/filesystem/operations.hpp>
  14. ///////////////////////////////////////////////////////////////////////////////
  15. // workaround for missing ostringstream
  16. #ifdef BOOST_NO_STRINGSTREAM
  17. #include <strstream>
  18. #define BOOST_WAVETEST_OSSTREAM std::ostrstream
  19. std::string BOOST_WAVETEST_GETSTRING(std::ostrstream& ss)
  20. {
  21. ss << ends;
  22. std::string rval = ss.str();
  23. ss.freeze(false);
  24. return rval;
  25. }
  26. #else
  27. #include <sstream>
  28. #define BOOST_WAVETEST_GETSTRING(ss) ss.str()
  29. #define BOOST_WAVETEST_OSSTREAM std::ostringstream
  30. #endif
  31. ///////////////////////////////////////////////////////////////////////////////
  32. template <typename String>
  33. String handle_filepath(String const &name)
  34. {
  35. using boost::wave::util::impl::unescape_lit;
  36. String unesc_name (unescape_lit(name));
  37. typename String::size_type p = unesc_name.find_last_of("/\\");
  38. if (p != unesc_name.npos)
  39. unesc_name = unesc_name.substr(p+1);
  40. return unesc_name;
  41. }
  42. ///////////////////////////////////////////////////////////////////////////////
  43. template <typename String>
  44. inline String repr(boost::wave::util::file_position<String> const& pos)
  45. {
  46. std::string linenum = boost::lexical_cast<std::string>(pos.get_line());
  47. return handle_filepath(pos.get_file()) + String("(") + linenum.c_str() + ")";
  48. }
  49. template <typename String>
  50. inline String repr(String const& value)
  51. {
  52. String result;
  53. typename String::const_iterator end = value.end();
  54. for (typename String::const_iterator it = value.begin(); it != end; ++it)
  55. {
  56. typedef typename String::value_type char_type;
  57. char_type c = *it;
  58. if (c == static_cast<char_type>('\a'))
  59. result.append("\\a");
  60. else if (c == static_cast<char_type>('\b'))
  61. result.append("\\b");
  62. else if (c == static_cast<char_type>('\f'))
  63. result.append("\\f");
  64. else if (c == static_cast<char_type>('\n'))
  65. result.append("\\n");
  66. else if (c == static_cast<char_type>('\r'))
  67. result.append("\\r");
  68. else if (c == static_cast<char_type>('\t'))
  69. result.append("\\t");
  70. else if (c == static_cast<char_type>('\v'))
  71. result.append("\\v");
  72. else
  73. result += static_cast<char_type>(c);
  74. }
  75. return result;
  76. }
  77. #if defined(BOOST_WINDOWS)
  78. template <typename String>
  79. inline String replace_slashes(String value, char const* lookfor = "\\",
  80. char replace_with = '/')
  81. {
  82. typename String::size_type p = value.find_first_of(lookfor);
  83. while (p != value.npos) {
  84. value[p] = replace_with;
  85. p = value.find_first_of(lookfor, p+1);
  86. }
  87. return value;
  88. }
  89. #endif
  90. ///////////////////////////////////////////////////////////////////////////////
  91. template <typename Token>
  92. class collect_hooks_information
  93. : public boost::wave::context_policies::eat_whitespace<Token>
  94. {
  95. typedef boost::wave::context_policies::eat_whitespace<Token> base_type;
  96. public:
  97. collect_hooks_information(std::string& trace)
  98. : hooks_trace(trace), skipped_token_hooks(false)
  99. {}
  100. void set_skipped_token_hooks(bool flag)
  101. {
  102. skipped_token_hooks = flag;
  103. }
  104. ///////////////////////////////////////////////////////////////////////////
  105. //
  106. // The function 'expanding_function_like_macro' is called, whenever a
  107. // function-like macro is to be expanded.
  108. //
  109. // The parameter 'macrodef' marks the position, where the macro to expand
  110. // is defined.
  111. //
  112. // The parameter 'formal_args' holds the formal arguments used during the
  113. // definition of the macro.
  114. //
  115. // The parameter 'definition' holds the macro definition for the macro to
  116. // trace.
  117. //
  118. // The parameter 'macro_call' marks the position, where this macro invoked.
  119. //
  120. // The parameter 'arguments' holds the macro arguments used during the
  121. // invocation of the macro
  122. //
  123. // The parameters 'seqstart' and 'seqend' point into the input token
  124. // stream allowing to access the whole token sequence comprising the macro
  125. // invocation (starting with the opening parenthesis and ending after the
  126. // closing one).
  127. //
  128. // The return value defines, whether the corresponding macro will be
  129. // expanded (return false) or will be copied to the output (return true).
  130. // Note: the whole argument list is copied unchanged to the output as well
  131. // without any further processing.
  132. //
  133. ///////////////////////////////////////////////////////////////////////////
  134. template <typename Context, typename Container, typename Iterator>
  135. bool
  136. expanding_function_like_macro(Context const& ctx,
  137. Token const& macro, std::vector<Token> const& formal_args,
  138. Container const& definition,
  139. Token const& macrocall, std::vector<Container> const& arguments,
  140. Iterator const& seqstart, Iterator const& seqend)
  141. {
  142. BOOST_WAVETEST_OSSTREAM strm;
  143. // trace real macro call
  144. strm << "00: " << repr(macrocall.get_position()) << ": "
  145. << macrocall.get_value() << "(";
  146. for (typename std::vector<Token>::size_type i = 0;
  147. i < arguments.size(); ++i)
  148. {
  149. strm << boost::wave::util::impl::as_string(arguments[i]);
  150. if (i < arguments.size()-1)
  151. strm << ",";
  152. }
  153. strm << "), ";
  154. // trace macro definition
  155. strm << "[" << repr(macro.get_position()) << ": "
  156. << macro.get_value() << "(";
  157. for (typename std::vector<Token>::size_type i = 0;
  158. i < formal_args.size(); ++i)
  159. {
  160. strm << formal_args[i].get_value();
  161. if (i < formal_args.size()-1)
  162. strm << ", ";
  163. }
  164. strm << ")=" << boost::wave::util::impl::as_string(definition) << "]"
  165. << std::endl;
  166. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  167. return false; // default is to normally expand the macro
  168. }
  169. ///////////////////////////////////////////////////////////////////////////
  170. //
  171. // The function 'expanding_object_like_macro' is called, whenever a
  172. // object-like macro is to be expanded .
  173. //
  174. // The parameter 'ctx' is a reference to the context object used for
  175. // instantiating the preprocessing iterators by the user.
  176. //
  177. // The parameter 'macro' marks the position, where the macro to expand
  178. // is defined.
  179. //
  180. // The definition 'definition' holds the macro definition for the macro to
  181. // trace.
  182. //
  183. // The parameter 'macrocall' marks the position, where this macro invoked.
  184. //
  185. // The return value defines, whether the corresponding macro will be
  186. // expanded (return false) or will be copied to the output (return true).
  187. //
  188. ///////////////////////////////////////////////////////////////////////////
  189. template <typename Context, typename Container>
  190. bool
  191. expanding_object_like_macro(Context const& ctx, Token const& macro,
  192. Container const& definition, Token const& macrocall)
  193. {
  194. BOOST_WAVETEST_OSSTREAM strm;
  195. strm << "01: " << repr(macro.get_position()) << ": "
  196. << macro.get_value() << std::endl;
  197. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  198. return false; // default is to normally expand the macro
  199. }
  200. ///////////////////////////////////////////////////////////////////////////
  201. //
  202. // The function 'expanded_macro' is called, whenever the expansion of a
  203. // macro is finished but before the rescanning process starts.
  204. //
  205. // The parameter 'ctx' is a reference to the context object used for
  206. // instantiating the preprocessing iterators by the user.
  207. //
  208. // The parameter 'result' contains the token sequence generated as the
  209. // result of the macro expansion.
  210. //
  211. ///////////////////////////////////////////////////////////////////////////
  212. template <typename Context, typename Container>
  213. void expanded_macro(Context const& ctx, Container const& result)
  214. {
  215. BOOST_WAVETEST_OSSTREAM strm;
  216. strm << "02: " << boost::wave::util::impl::as_string(result) << std::endl;
  217. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  218. }
  219. ///////////////////////////////////////////////////////////////////////////
  220. //
  221. // The function 'rescanned_macro' is called, whenever the rescanning of a
  222. // macro is finished.
  223. //
  224. // The parameter 'ctx' is a reference to the context object used for
  225. // instantiating the preprocessing iterators by the user.
  226. //
  227. // The parameter 'result' contains the token sequence generated as the
  228. // result of the rescanning.
  229. //
  230. ///////////////////////////////////////////////////////////////////////////
  231. template <typename Context, typename Container>
  232. void rescanned_macro(Context const& ctx, Container const& result)
  233. {
  234. BOOST_WAVETEST_OSSTREAM strm;
  235. strm << "03: " << boost::wave::util::impl::as_string(result) << std::endl;
  236. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  237. }
  238. ///////////////////////////////////////////////////////////////////////////
  239. //
  240. // The function 'found_include_directive' is called, whenever a #include
  241. // directive was located.
  242. //
  243. // The parameter 'ctx' is a reference to the context object used for
  244. // instantiating the preprocessing iterators by the user.
  245. //
  246. // The parameter 'filename' contains the (expanded) file name found after
  247. // the #include directive. This has the format '<file>', '"file"' or
  248. // 'file'.
  249. // The formats '<file>' or '"file"' are used for #include directives found
  250. // in the preprocessed token stream, the format 'file' is used for files
  251. // specified through the --force_include command line argument.
  252. //
  253. // The parameter 'include_next' is set to true if the found directive was
  254. // a #include_next directive and the BOOST_WAVE_SUPPORT_INCLUDE_NEXT
  255. // preprocessing constant was defined to something != 0.
  256. //
  257. // The return value defines, whether the found file will be included
  258. // (return false) or will be skipped (return true).
  259. //
  260. ///////////////////////////////////////////////////////////////////////////
  261. template <typename Context>
  262. bool
  263. found_include_directive(Context const& ctx, std::string filename,
  264. bool include_next)
  265. {
  266. BOOST_WAVETEST_OSSTREAM strm;
  267. strm << "04: " << filename;
  268. if (include_next)
  269. strm << " (include_next)";
  270. strm << std::endl;
  271. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  272. return false; // ok to include this file
  273. }
  274. ///////////////////////////////////////////////////////////////////////////
  275. //
  276. // The function 'opened_include_file' is called, whenever a file referred
  277. // by an #include directive was successfully located and opened.
  278. //
  279. // The parameter 'ctx' is a reference to the context object used for
  280. // instantiating the preprocessing iterators by the user.
  281. //
  282. // The parameter 'filename' contains the file system path of the
  283. // opened file (this is relative to the directory of the currently
  284. // processed file or a absolute path depending on the paths given as the
  285. // include search paths).
  286. //
  287. // The include_depth parameter contains the current include file depth.
  288. //
  289. // The is_system_include parameter denotes, whether the given file was
  290. // found as a result of a #include <...> directive.
  291. //
  292. ///////////////////////////////////////////////////////////////////////////
  293. template <typename Context>
  294. void
  295. opened_include_file(Context const& ctx, std::string relname,
  296. std::string absname, bool is_system_include)
  297. {
  298. using boost::wave::util::impl::escape_lit;
  299. #if defined(BOOST_WINDOWS)
  300. relname = replace_slashes(relname);
  301. absname = replace_slashes(absname);
  302. #endif
  303. BOOST_WAVETEST_OSSTREAM strm;
  304. strm << "05: " << escape_lit(relname)
  305. << " (" << escape_lit(absname) << ")" << std::endl;
  306. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  307. }
  308. ///////////////////////////////////////////////////////////////////////////
  309. //
  310. // The function 'returning_from_include_file' is called, whenever an
  311. // included file is about to be closed after it's processing is complete.
  312. //
  313. // The parameter 'ctx' is a reference to the context object used for
  314. // instantiating the preprocessing iterators by the user.
  315. //
  316. ///////////////////////////////////////////////////////////////////////////
  317. template <typename Context>
  318. void
  319. returning_from_include_file(Context const& ctx)
  320. {
  321. BOOST_WAVETEST_OSSTREAM strm;
  322. strm << "06: " << std::endl;
  323. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  324. }
  325. ///////////////////////////////////////////////////////////////////////////
  326. //
  327. // The function 'interpret_pragma' is called, whenever a #pragma command
  328. // directive is found which isn't known to the core Wave library, where
  329. // command is the value defined as the BOOST_WAVE_PRAGMA_KEYWORD constant
  330. // which defaults to "wave".
  331. //
  332. // The parameter 'ctx' is a reference to the context object used for
  333. // instantiating the preprocessing iterators by the user.
  334. //
  335. // The parameter 'pending' may be used to push tokens back into the input
  336. // stream, which are to be used as the replacement text for the whole
  337. // #pragma directive.
  338. //
  339. // The parameter 'option' contains the name of the interpreted pragma.
  340. //
  341. // The parameter 'values' holds the values of the parameter provided to
  342. // the pragma operator.
  343. //
  344. // The parameter 'act_token' contains the actual #pragma token, which may
  345. // be used for error output.
  346. //
  347. // If the return value is 'false', the whole #pragma directive is
  348. // interpreted as unknown and a corresponding error message is issued. A
  349. // return value of 'true' signs a successful interpretation of the given
  350. // #pragma.
  351. //
  352. ///////////////////////////////////////////////////////////////////////////
  353. template <typename Context, typename Container>
  354. bool
  355. interpret_pragma(Context const& ctx, Container &pending,
  356. Token const& option, Container const& values, Token const& act_token)
  357. {
  358. BOOST_WAVETEST_OSSTREAM strm;
  359. strm << "07: " << std::endl;
  360. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  361. return false;
  362. }
  363. ///////////////////////////////////////////////////////////////////////////
  364. //
  365. // The function 'defined_macro' is called, whenever a macro was defined
  366. // successfully.
  367. //
  368. // The parameter 'ctx' is a reference to the context object used for
  369. // instantiating the preprocessing iterators by the user.
  370. //
  371. // The parameter 'name' is a reference to the token holding the macro name.
  372. //
  373. // The parameter 'is_functionlike' is set to true, whenever the newly
  374. // defined macro is defined as a function like macro.
  375. //
  376. // The parameter 'parameters' holds the parameter tokens for the macro
  377. // definition. If the macro has no parameters or if it is a object like
  378. // macro, then this container is empty.
  379. //
  380. // The parameter 'definition' contains the token sequence given as the
  381. // replacement sequence (definition part) of the newly defined macro.
  382. //
  383. // The parameter 'is_predefined' is set to true for all macros predefined
  384. // during the initialization phase of the library.
  385. //
  386. ///////////////////////////////////////////////////////////////////////////
  387. template <typename Context, typename Container>
  388. void
  389. defined_macro(Context const& ctx, Token const& macro,
  390. bool is_functionlike, std::vector<Token> const& pars,
  391. Container const& definition, bool is_predefined)
  392. {
  393. // do not trace the definition of the internal helper macros
  394. if (!is_predefined) {
  395. BOOST_WAVETEST_OSSTREAM strm;
  396. strm << "08: " << repr(macro.get_position()) << ": "
  397. << macro.get_value();
  398. if (is_functionlike) {
  399. // list the parameter names for function style macros
  400. strm << "(";
  401. for (typename std::vector<Token>::size_type i = 0;
  402. i < pars.size(); ++i)
  403. {
  404. strm << pars[i].get_value();
  405. if (i < pars.size()-1)
  406. strm << ", ";
  407. }
  408. strm << ")";
  409. }
  410. strm << "=" << boost::wave::util::impl::as_string(definition)
  411. << std::endl;
  412. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  413. }
  414. }
  415. ///////////////////////////////////////////////////////////////////////////
  416. //
  417. // The function 'undefined_macro' is called, whenever a macro definition
  418. // was removed successfully.
  419. //
  420. // The parameter 'ctx' is a reference to the context object used for
  421. // instantiating the preprocessing iterators by the user.
  422. //
  423. // The parameter 'name' holds the name of the macro, which definition was
  424. // removed.
  425. //
  426. ///////////////////////////////////////////////////////////////////////////
  427. template <typename Context>
  428. void
  429. undefined_macro(Context const& ctx, Token const& macro)
  430. {
  431. BOOST_WAVETEST_OSSTREAM strm;
  432. strm << "09: " << repr(macro.get_position()) << ": "
  433. << macro.get_value() << std::endl;
  434. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  435. }
  436. ///////////////////////////////////////////////////////////////////////////
  437. //
  438. // The function 'found_directive' is called, whenever a preprocessor
  439. // directive was encountered, but before the corresponding action is
  440. // executed.
  441. //
  442. // The parameter 'ctx' is a reference to the context object used for
  443. // instantiating the preprocessing iterators by the user.
  444. //
  445. // The parameter 'directive' is a reference to the token holding the
  446. // preprocessing directive.
  447. //
  448. // The return value defines, whether the given expression has to be
  449. // to be executed in a normal way (return 'false'), or if it has to be
  450. // skipped altogether (return 'true'), which means it gets replaced in the
  451. // output by a single newline.
  452. //
  453. ///////////////////////////////////////////////////////////////////////////
  454. template <typename Context>
  455. bool
  456. found_directive(Context const& ctx, Token const& directive)
  457. {
  458. BOOST_WAVETEST_OSSTREAM strm;
  459. strm << "10: " << repr(directive.get_position()) << ": "
  460. << directive.get_value() << std::endl;
  461. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  462. return false; // by default we never skip any directives
  463. }
  464. ///////////////////////////////////////////////////////////////////////////
  465. //
  466. // The function 'evaluated_conditional_expression' is called, whenever a
  467. // conditional preprocessing expression was evaluated (the expression
  468. // given to a #if, #elif, #ifdef or #ifndef directive)
  469. //
  470. // The parameter 'ctx' is a reference to the context object used for
  471. // instantiating the preprocessing iterators by the user.
  472. //
  473. // The parameter 'directive' is a reference to the token holding the
  474. // corresponding preprocessing directive.
  475. //
  476. // The parameter 'expression' holds the non-expanded token sequence
  477. // comprising the evaluated expression.
  478. //
  479. // The parameter expression_value contains the result of the evaluation of
  480. // the expression in the current preprocessing context.
  481. //
  482. // The return value defines, whether the given expression has to be
  483. // evaluated again, allowing to decide which of the conditional branches
  484. // should be expanded. You need to return 'true' from this hook function
  485. // to force the expression to be re-evaluated.
  486. //
  487. ///////////////////////////////////////////////////////////////////////////
  488. template <typename Context, typename Container>
  489. bool
  490. evaluated_conditional_expression(Context const& ctx,
  491. Token const& directive, Container const& expression,
  492. bool expression_value)
  493. {
  494. BOOST_WAVETEST_OSSTREAM strm;
  495. strm << "11: " << repr(directive.get_position()) << ": "
  496. << directive.get_value() << " "
  497. << boost::wave::util::impl::as_string(expression) << ": "
  498. << expression_value << std::endl;
  499. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  500. return false; // ok to continue, do not re-evaluate expression
  501. }
  502. ///////////////////////////////////////////////////////////////////////////
  503. //
  504. // The function 'skipped_token' is called, whenever a token is about to be
  505. // skipped due to a false preprocessor condition (code fragments to be
  506. // skipped inside the not evaluated conditional #if/#else/#endif branches).
  507. //
  508. // The parameter 'ctx' is a reference to the context object used for
  509. // instantiating the preprocessing iterators by the user.
  510. //
  511. // The parameter 'token' refers to the token to be skipped.
  512. //
  513. ///////////////////////////////////////////////////////////////////////////
  514. template <typename Context>
  515. void
  516. skipped_token(Context const& ctx, Token const& token)
  517. {
  518. // this normally generates a lot of noise
  519. if (skipped_token_hooks) {
  520. BOOST_WAVETEST_OSSTREAM strm;
  521. strm << "12: " << repr(token.get_position()) << ": >"
  522. << repr(token.get_value()) << "<" << std::endl;
  523. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  524. }
  525. }
  526. ///////////////////////////////////////////////////////////////////////////
  527. //
  528. // The function 'generated_token' will be called by the library whenever a
  529. // token is about to be returned from the library.
  530. //
  531. // The parameter 'ctx' is a reference to the context object used for
  532. // instantiating the preprocessing iterators by the user.
  533. //
  534. // The parameter 't' is the token about to be returned from the library.
  535. // This function may alter the token, but in this case it must be
  536. // implemented with a corresponding signature:
  537. //
  538. // Token const&
  539. // generated_token(Context const& ctx, Token& t);
  540. //
  541. // which makes it possible to modify the token in place.
  542. //
  543. // The default behavior is to return the token passed as the parameter
  544. // without modification.
  545. //
  546. ///////////////////////////////////////////////////////////////////////////
  547. template <typename Context>
  548. Token const&
  549. generated_token(Context const& ctx, Token const& t)
  550. {
  551. // this generates a lot of noise
  552. // BOOST_WAVETEST_OSSTREAM strm;
  553. // strm << "13: " << std::endl;
  554. // hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  555. return t;
  556. }
  557. ///////////////////////////////////////////////////////////////////////////
  558. //
  559. // The function 'may_skip_whitespace' will be called by the
  560. // library, whenever it must be tested whether a specific token refers to
  561. // whitespace and this whitespace has to be skipped.
  562. //
  563. // The parameter 'ctx' is a reference to the context object used for
  564. // instantiating the preprocessing iterators by the user.
  565. //
  566. // The 'token' parameter holds a reference to the current token. The policy
  567. // is free to change this token if needed.
  568. //
  569. // The 'skipped_newline' parameter holds a reference to a boolean value
  570. // which should be set to true by the policy function whenever a newline
  571. // is going to be skipped.
  572. //
  573. // If the return value is true, the given token is skipped and the
  574. // preprocessing continues to the next token. If the return value is
  575. // false, the given token is returned to the calling application.
  576. //
  577. // ATTENTION!
  578. // Caution has to be used, because by returning true the policy function
  579. // is able to force skipping even significant tokens, not only whitespace.
  580. //
  581. ///////////////////////////////////////////////////////////////////////////
  582. template <typename Context>
  583. bool
  584. may_skip_whitespace(Context const& ctx, Token& token, bool& skipped_newline)
  585. {
  586. // this generates a lot of noise
  587. // BOOST_WAVETEST_OSSTREAM strm;
  588. // strm << "14: " << std::endl;
  589. // hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  590. return this->base_type::may_skip_whitespace(ctx, token, skipped_newline);
  591. }
  592. #if BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE != 0
  593. ///////////////////////////////////////////////////////////////////////////
  594. //
  595. // The function 'found_warning_directive' will be called by the library
  596. // whenever a #warning directive is found.
  597. //
  598. // The parameter 'ctx' is a reference to the context object used for
  599. // instantiating the preprocessing iterators by the user.
  600. //
  601. // The parameter 'message' references the argument token sequence of the
  602. // encountered #warning directive.
  603. //
  604. // If the return value is false, the library throws a preprocessor
  605. // exception of the type 'warning_directive', if the return value is true
  606. // the execution continues as if no #warning directive has been found.
  607. //
  608. ///////////////////////////////////////////////////////////////////////////
  609. template <typename Context, typename Container>
  610. bool
  611. found_warning_directive(Context const& ctx, Container const& message)
  612. {
  613. BOOST_WAVETEST_OSSTREAM strm;
  614. strm << "15: " << boost::wave::util::impl::as_string(message)
  615. << std::endl;
  616. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  617. return false;
  618. }
  619. #endif
  620. ///////////////////////////////////////////////////////////////////////////
  621. //
  622. // The function 'found_error_directive' will be called by the library
  623. // whenever a #error directive is found.
  624. //
  625. // The parameter 'ctx' is a reference to the context object used for
  626. // instantiating the preprocessing iterators by the user.
  627. //
  628. // The parameter 'message' references the argument token sequence of the
  629. // encountered #error directive.
  630. //
  631. // If the return value is false, the library throws a preprocessor
  632. // exception of the type 'error_directive', if the return value is true
  633. // the execution continues as if no #error directive has been found.
  634. //
  635. ///////////////////////////////////////////////////////////////////////////
  636. template <typename Context, typename Container>
  637. bool
  638. found_error_directive(Context const& ctx, Container const& message)
  639. {
  640. BOOST_WAVETEST_OSSTREAM strm;
  641. strm << "16: " << boost::wave::util::impl::as_string(message)
  642. << std::endl;
  643. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  644. return false;
  645. }
  646. ///////////////////////////////////////////////////////////////////////////
  647. //
  648. // The function 'found_line_directive' will be called by the library
  649. // whenever a #line directive is found.
  650. //
  651. // The parameter 'ctx' is a reference to the context object used for
  652. // instantiating the preprocessing iterators by the user.
  653. //
  654. // The parameter 'arguments' references the argument token sequence of the
  655. // encountered #line directive.
  656. //
  657. // The parameter 'line' contains the recognized line number from the #line
  658. // directive.
  659. //
  660. // The parameter 'filename' references the recognized file name from the
  661. // #line directive (if there was one given).
  662. //
  663. ///////////////////////////////////////////////////////////////////////////
  664. template <typename Context, typename Container>
  665. void
  666. found_line_directive(Context const& ctx, Container const& arguments,
  667. unsigned int line, std::string const& filename)
  668. {
  669. BOOST_WAVETEST_OSSTREAM strm;
  670. strm << "17: " << boost::wave::util::impl::as_string(arguments)
  671. << " (" << line << ", \"" << filename << "\")" << std::endl;
  672. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  673. }
  674. ///////////////////////////////////////////////////////////////////////////
  675. //
  676. // The function 'throw_exception' will be called by the library whenever a
  677. // preprocessing exception occurs.
  678. //
  679. // The parameter 'ctx' is a reference to the context object used for
  680. // instantiating the preprocessing iterators by the user.
  681. //
  682. // The parameter 'e' is the exception object containing detailed error
  683. // information.
  684. //
  685. // The default behavior is to call the function boost::throw_exception.
  686. //
  687. ///////////////////////////////////////////////////////////////////////////
  688. template <typename Context, typename Exception>
  689. void
  690. throw_exception(Context const& ctx, Exception const& e)
  691. {
  692. BOOST_WAVETEST_OSSTREAM strm;
  693. strm << "18: " << e.what() << std::endl;
  694. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  695. return this->base_type::throw_exception(ctx, e);
  696. }
  697. #if BOOST_WAVE_SUPPORT_PRAGMA_ONCE != 0
  698. ///////////////////////////////////////////////////////////////////////////
  699. //
  700. // The function 'detected_include_guard' is called whenever either a
  701. // include file is about to be added to the list of #pragma once headers.
  702. // That means this header file will not be opened and parsed again even
  703. // if it is specified in a later #include directive.
  704. // This function is called as the result of a detected include guard
  705. // scheme.
  706. //
  707. // The implemented heuristics for include guards detects two forms of
  708. // include guards:
  709. //
  710. // #ifndef INCLUDE_GUARD_MACRO
  711. // #define INCLUDE_GUARD_MACRO
  712. // ...
  713. // #endif
  714. //
  715. // or
  716. //
  717. // if !defined(INCLUDE_GUARD_MACRO)
  718. // #define INCLUDE_GUARD_MACRO
  719. // ...
  720. // #endif
  721. //
  722. // note, that the parenthesis are optional (i.e. !defined INCLUDE_GUARD_MACRO
  723. // will work as well). The code allows for any whitespace, newline and single
  724. // '#' tokens before the #if/#ifndef and after the final #endif.
  725. //
  726. // The parameter 'ctx' is a reference to the context object used for
  727. // instantiating the preprocessing iterators by the user.
  728. //
  729. // The parameter 'filename' contains the file system path of the
  730. // opened file (this is relative to the directory of the currently
  731. // processed file or a absolute path depending on the paths given as the
  732. // include search paths).
  733. //
  734. // The parameter contains the name of the detected include guard.
  735. //
  736. ///////////////////////////////////////////////////////////////////////////
  737. template <typename ContextT>
  738. void
  739. detected_include_guard(ContextT const& ctx, std::string filename,
  740. std::string const& include_guard)
  741. {
  742. using boost::wave::util::impl::escape_lit;
  743. #if defined(BOOST_WINDOWS)
  744. filename = replace_slashes(filename);
  745. #endif
  746. BOOST_WAVETEST_OSSTREAM strm;
  747. strm << "19: " << escape_lit(filename) << ": "
  748. << include_guard << std::endl;
  749. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  750. }
  751. ///////////////////////////////////////////////////////////////////////////
  752. //
  753. // The function 'detected_pragma_once' is called whenever either a
  754. // include file is about to be added to the list of #pragma once headers.
  755. // That means this header file will not be opened and parsed again even
  756. // if it is specified in a later #include directive.
  757. // This function is called as the result of a detected directive
  758. // #pragma once.
  759. //
  760. // The parameter 'ctx' is a reference to the context object used for
  761. // instantiating the preprocessing iterators by the user.
  762. //
  763. // The parameter pragma_token refers to the token "#pragma" triggering
  764. // this preprocessing hook.
  765. //
  766. // The parameter 'filename' contains the file system path of the
  767. // opened file (this is relative to the directory of the currently
  768. // processed file or a absolute path depending on the paths given as the
  769. // include search paths).
  770. //
  771. ///////////////////////////////////////////////////////////////////////////
  772. template <typename ContextT, typename TokenT>
  773. void
  774. detected_pragma_once(ContextT const& ctx, TokenT const& pragma_token,
  775. std::string filename)
  776. {
  777. using boost::wave::util::impl::escape_lit;
  778. #if defined(BOOST_WINDOWS)
  779. filename = replace_slashes(filename);
  780. #endif
  781. BOOST_WAVETEST_OSSTREAM strm;
  782. strm << "20: " << repr(pragma_token.get_position()) << ": "
  783. << pragma_token.get_value() << ": "
  784. << escape_lit(filename) << std::endl;
  785. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  786. }
  787. #endif
  788. ///////////////////////////////////////////////////////////////////////////
  789. //
  790. // The function 'found_unknown_directive' is called, whenever an unknown
  791. // preprocessor directive was encountered.
  792. //
  793. // The parameter 'ctx' is a reference to the context object used for
  794. // instantiating the preprocessing iterators by the user.
  795. //
  796. // The parameter 'line' holds the tokens of the entire source line
  797. // containing the unknown directive.
  798. //
  799. // The parameter 'pending' may be used to push tokens back into the input
  800. // stream, which are to be used as the replacement text for the whole
  801. // line containing the unknown directive.
  802. //
  803. // The return value defines, whether the given expression has been
  804. // properly interpreted by the hook function or not. If this function
  805. // returns 'false', the library will raise an 'ill_formed_directive'
  806. // preprocess_exception. Otherwise the tokens pushed back into 'pending'
  807. // are passed on to the user program.
  808. //
  809. ///////////////////////////////////////////////////////////////////////////
  810. template <typename ContextT, typename ContainerT>
  811. bool
  812. found_unknown_directive(ContextT const& ctx, ContainerT const& line,
  813. ContainerT& pending)
  814. {
  815. BOOST_WAVETEST_OSSTREAM strm;
  816. strm << "21: " << repr((*line.begin()).get_position()) << ": "
  817. << boost::wave::util::impl::as_string(line) << std::endl;
  818. hooks_trace += BOOST_WAVETEST_GETSTRING(strm);
  819. return false;
  820. }
  821. private:
  822. std::string& hooks_trace;
  823. bool skipped_token_hooks;
  824. };
  825. #endif