cpp_macromap.hpp 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. Macro expansion engine
  4. http://www.boost.org/
  5. Copyright (c) 2001-2012 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. #if !defined(BOOST_CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)
  10. #define BOOST_CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED
  11. #include <cstdlib>
  12. #include <cstdio>
  13. #include <ctime>
  14. #include <list>
  15. #include <map>
  16. #include <set>
  17. #include <vector>
  18. #include <iterator>
  19. #include <algorithm>
  20. #include <boost/assert.hpp>
  21. #include <boost/wave/wave_config.hpp>
  22. #if BOOST_WAVE_SERIALIZATION != 0
  23. #include <boost/serialization/serialization.hpp>
  24. #include <boost/serialization/shared_ptr.hpp>
  25. #endif
  26. #include <boost/filesystem/path.hpp>
  27. #include <boost/lexical_cast.hpp>
  28. #include <boost/optional.hpp>
  29. #include <boost/wave/util/time_conversion_helper.hpp>
  30. #include <boost/wave/util/unput_queue_iterator.hpp>
  31. #include <boost/wave/util/macro_helpers.hpp>
  32. #include <boost/wave/util/macro_definition.hpp>
  33. #include <boost/wave/util/symbol_table.hpp>
  34. #include <boost/wave/util/cpp_macromap_utils.hpp>
  35. #include <boost/wave/util/cpp_macromap_predef.hpp>
  36. #include <boost/wave/util/filesystem_compatibility.hpp>
  37. #include <boost/wave/grammars/cpp_defined_grammar_gen.hpp>
  38. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  39. #include <boost/wave/grammars/cpp_has_include_grammar_gen.hpp>
  40. #endif
  41. #include <boost/wave/wave_version.hpp>
  42. #include <boost/wave/cpp_exceptions.hpp>
  43. #include <boost/wave/language_support.hpp>
  44. // this must occur after all of the includes and before any code appears
  45. #ifdef BOOST_HAS_ABI_HEADERS
  46. #include BOOST_ABI_PREFIX
  47. #endif
  48. ///////////////////////////////////////////////////////////////////////////////
  49. namespace boost { namespace wave { namespace util {
  50. ///////////////////////////////////////////////////////////////////////////////
  51. //
  52. // macromap
  53. //
  54. // This class holds all currently defined macros and on demand expands
  55. // those macro definitions
  56. //
  57. ///////////////////////////////////////////////////////////////////////////////
  58. template <typename ContextT>
  59. class macromap {
  60. typedef macromap<ContextT> self_type;
  61. typedef typename ContextT::token_type token_type;
  62. typedef typename token_type::string_type string_type;
  63. typedef typename token_type::position_type position_type;
  64. typedef typename ContextT::token_sequence_type definition_container_type;
  65. typedef std::vector<token_type> parameter_container_type;
  66. typedef macro_definition<token_type, definition_container_type>
  67. macro_definition_type;
  68. typedef symbol_table<string_type, macro_definition_type>
  69. defined_macros_type;
  70. typedef typename defined_macros_type::value_type::second_type
  71. macro_ref_type;
  72. public:
  73. macromap(ContextT &ctx_)
  74. : current_macros(0), defined_macros(new defined_macros_type(1)),
  75. main_pos("", 0), ctx(ctx_), macro_uid(1)
  76. {
  77. current_macros = defined_macros.get();
  78. }
  79. ~macromap() {}
  80. // Add a new macro to the given macro scope
  81. bool add_macro(token_type const &name, bool has_parameters,
  82. parameter_container_type &parameters,
  83. definition_container_type &definition, bool is_predefined = false,
  84. defined_macros_type *scope = 0);
  85. // Tests, whether the given macro name is defined in the given macro scope
  86. bool is_defined(string_type const &name,
  87. typename defined_macros_type::iterator &it,
  88. defined_macros_type *scope = 0) const;
  89. // expects a token sequence as its parameters
  90. template <typename IteratorT>
  91. bool is_defined(IteratorT const &begin, IteratorT const &end) const;
  92. // expects an arbitrary string as its parameter
  93. bool is_defined(string_type const &str) const;
  94. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  95. // expects a token sequence as its parameters
  96. template <typename IteratorT>
  97. bool has_include(IteratorT const &begin, IteratorT const &end,
  98. bool is_quoted_filename, bool is_system) const;
  99. #endif
  100. // Get the macro definition for the given macro scope
  101. bool get_macro(string_type const &name, bool &has_parameters,
  102. bool &is_predefined, position_type &pos,
  103. parameter_container_type &parameters,
  104. definition_container_type &definition,
  105. defined_macros_type *scope = 0) const;
  106. // Remove a macro name from the given macro scope
  107. bool remove_macro(string_type const &name, position_type const& pos,
  108. bool even_predefined = false);
  109. template <typename IteratorT, typename ContainerT>
  110. token_type const &expand_tokensequence(IteratorT &first,
  111. IteratorT const &last, ContainerT &pending, ContainerT &expanded,
  112. bool& seen_newline, bool expand_operator_defined,
  113. bool expand_operator_has_include);
  114. // Expand all macros inside the given token sequence
  115. template <typename IteratorT, typename ContainerT>
  116. void expand_whole_tokensequence(ContainerT &expanded,
  117. IteratorT &first, IteratorT const &last,
  118. bool expand_operator_defined,
  119. bool expand_operator_has_include);
  120. // Init the predefined macros (add them to the given scope)
  121. void init_predefined_macros(char const *fname = "<Unknown>",
  122. defined_macros_type *scope = 0, bool at_global_scope = true);
  123. void predefine_macro(defined_macros_type *scope, string_type const &name,
  124. token_type const &t);
  125. // Init the internal macro symbol namespace
  126. void reset_macromap();
  127. position_type &get_main_pos() { return main_pos; }
  128. position_type const& get_main_pos() const { return main_pos; }
  129. // interface for macro name introspection
  130. typedef typename defined_macros_type::name_iterator name_iterator;
  131. typedef typename defined_macros_type::const_name_iterator const_name_iterator;
  132. name_iterator begin()
  133. { return defined_macros_type::make_iterator(current_macros->begin()); }
  134. name_iterator end()
  135. { return defined_macros_type::make_iterator(current_macros->end()); }
  136. const_name_iterator begin() const
  137. { return defined_macros_type::make_iterator(current_macros->begin()); }
  138. const_name_iterator end() const
  139. { return defined_macros_type::make_iterator(current_macros->end()); }
  140. protected:
  141. // Helper functions for expanding all macros in token sequences
  142. template <typename IteratorT, typename ContainerT>
  143. token_type const &expand_tokensequence_worker(ContainerT &pending,
  144. unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
  145. unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
  146. bool& seen_newline, bool expand_operator_defined,
  147. bool expand_operator_has_include,
  148. boost::optional<position_type> expanding_pos);
  149. // Collect all arguments supplied to a macro invocation
  150. template <typename IteratorT, typename ContainerT, typename SizeT>
  151. typename std::vector<ContainerT>::size_type collect_arguments (
  152. token_type const curr_token, std::vector<ContainerT> &arguments,
  153. IteratorT &next, IteratorT &endparen, IteratorT const &end,
  154. SizeT const &parameter_count, bool& seen_newline);
  155. // Expand a single macro name
  156. template <typename IteratorT, typename ContainerT>
  157. bool expand_macro(ContainerT &pending, token_type const &name,
  158. typename defined_macros_type::iterator it,
  159. IteratorT &first, IteratorT const &last,
  160. bool& seen_newline, bool expand_operator_defined,
  161. bool expand_operator_has_include,
  162. boost::optional<position_type> expanding_pos,
  163. defined_macros_type *scope = 0, ContainerT *queue_symbol = 0);
  164. // Expand a predefined macro (__LINE__, __FILE__ and __INCLUDE_LEVEL__)
  165. template <typename ContainerT>
  166. bool expand_predefined_macro(token_type const &curr_token,
  167. ContainerT &expanded);
  168. // Expand a single macro argument
  169. template <typename ContainerT>
  170. void expand_argument (typename std::vector<ContainerT>::size_type arg,
  171. std::vector<ContainerT> &arguments,
  172. std::vector<ContainerT> &expanded_args, bool expand_operator_defined,
  173. bool expand_operator_has_include,
  174. std::vector<bool> &has_expanded_args);
  175. // Expand the replacement list (replaces parameters with arguments)
  176. template <typename ContainerT>
  177. void expand_replacement_list(
  178. typename macro_definition_type::const_definition_iterator_t cbeg,
  179. typename macro_definition_type::const_definition_iterator_t cend,
  180. std::vector<ContainerT> &arguments,
  181. bool expand_operator_defined,
  182. bool expand_operator_has_include,
  183. ContainerT &expanded);
  184. // Rescans the replacement list for macro expansion
  185. template <typename IteratorT, typename ContainerT>
  186. void rescan_replacement_list(token_type const &curr_token,
  187. macro_definition_type &macrodef, ContainerT &replacement_list,
  188. ContainerT &expanded, bool expand_operator_defined,
  189. bool expand_operator_has_include,
  190. IteratorT &nfirst, IteratorT const &nlast);
  191. // Resolves the operator defined() and replaces the token with "0" or "1"
  192. template <typename IteratorT, typename ContainerT>
  193. token_type const &resolve_defined(IteratorT &first, IteratorT const &last,
  194. ContainerT &expanded);
  195. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  196. // Resolves the operator __has_include() and replaces the token with "0" or "1"
  197. template <typename IteratorT, typename ContainerT>
  198. token_type const &resolve_has_include(IteratorT &first, IteratorT const &last,
  199. ContainerT &expanded);
  200. #endif
  201. // Resolve operator _Pragma or the #pragma directive
  202. template <typename IteratorT, typename ContainerT>
  203. bool resolve_operator_pragma(IteratorT &first,
  204. IteratorT const &last, ContainerT &expanded, bool& seen_newline);
  205. // Handle the concatenation operator '##'
  206. template <typename ContainerT>
  207. bool concat_tokensequence(ContainerT &expanded);
  208. template <typename ContainerT>
  209. bool is_valid_concat(string_type new_value,
  210. position_type const &pos, ContainerT &rescanned);
  211. static bool is_space(char);
  212. // batch update tokens with a single expand position
  213. template <typename ContainerT>
  214. static void set_expand_positions(ContainerT &tokens, position_type pos);
  215. #if BOOST_WAVE_SERIALIZATION != 0
  216. public:
  217. BOOST_STATIC_CONSTANT(unsigned int, version = 0x10);
  218. BOOST_STATIC_CONSTANT(unsigned int, version_mask = 0x0f);
  219. private:
  220. friend class boost::serialization::access;
  221. template<typename Archive>
  222. void save(Archive &ar, const unsigned int version) const
  223. {
  224. using namespace boost::serialization;
  225. ar & make_nvp("defined_macros", defined_macros);
  226. }
  227. template<typename Archive>
  228. void load(Archive &ar, const unsigned int loaded_version)
  229. {
  230. using namespace boost::serialization;
  231. if (version != (loaded_version & ~version_mask)) {
  232. BOOST_WAVE_THROW(preprocess_exception, incompatible_config,
  233. "cpp_context state version", get_main_pos());
  234. }
  235. ar & make_nvp("defined_macros", defined_macros);
  236. current_macros = defined_macros.get();
  237. }
  238. BOOST_SERIALIZATION_SPLIT_MEMBER()
  239. #endif
  240. private:
  241. defined_macros_type *current_macros; // current symbol table
  242. boost::shared_ptr<defined_macros_type> defined_macros; // global symbol table
  243. token_type act_token; // current token
  244. position_type main_pos; // last token position in the pp_iterator
  245. string_type base_name; // the name to be expanded by __BASE_FILE__
  246. ContextT &ctx; // context object associated with the macromap
  247. long macro_uid;
  248. predefined_macros predef; // predefined macro support
  249. };
  250. ///////////////////////////////////////////////////////////////////////////////
  251. ///////////////////////////////////////////////////////////////////////////////
  252. //
  253. // add_macro(): adds a new macro to the macromap
  254. //
  255. ///////////////////////////////////////////////////////////////////////////////
  256. template <typename ContextT>
  257. inline bool
  258. macromap<ContextT>::add_macro(token_type const &name, bool has_parameters,
  259. parameter_container_type &parameters, definition_container_type &definition,
  260. bool is_predefined, defined_macros_type *scope)
  261. {
  262. if (!is_predefined && impl::is_special_macroname (ctx, name.get_value())) {
  263. // exclude special macro names
  264. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  265. illegal_redefinition, name.get_value().c_str(), main_pos,
  266. name.get_value().c_str());
  267. return false;
  268. }
  269. if (boost::wave::need_variadics(ctx.get_language()) &&
  270. "__VA_ARGS__" == name.get_value())
  271. {
  272. // can't use __VA_ARGS__ as a macro name
  273. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  274. bad_define_statement_va_args, name.get_value().c_str(), main_pos,
  275. name.get_value().c_str());
  276. return false;
  277. }
  278. if (boost::wave::need_variadics(ctx.get_language()) &&
  279. "__VA_OPT__" == name.get_value())
  280. {
  281. // can't use __VA_OPT__ as a macro name
  282. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  283. bad_define_statement_va_opt, name.get_value().c_str(), main_pos,
  284. name.get_value().c_str());
  285. return false;
  286. }
  287. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  288. if (boost::wave::need_has_include(ctx.get_language()) &&
  289. "__has_include" == name.get_value())
  290. {
  291. // can't use __has_include as a macro name
  292. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  293. bad_define_statement_va_opt, name.get_value().c_str(), main_pos,
  294. name.get_value().c_str());
  295. return false;
  296. }
  297. #endif
  298. if (AltExtTokenType == (token_id(name) & ExtTokenOnlyMask)) {
  299. // exclude special operator names
  300. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  301. illegal_operator_redefinition, name.get_value().c_str(), main_pos,
  302. name.get_value().c_str());
  303. return false;
  304. }
  305. // try to define the new macro
  306. defined_macros_type* current_scope = scope ? scope : current_macros;
  307. typename defined_macros_type::iterator it = current_scope->find(name.get_value());
  308. if (it != current_scope->end()) {
  309. // redefinition, should not be different
  310. macro_definition_type* macrodef = (*it).second.get();
  311. if (macrodef->is_functionlike != has_parameters ||
  312. !impl::parameters_equal(macrodef->macroparameters, parameters) ||
  313. !impl::definition_equals(macrodef->macrodefinition, definition))
  314. {
  315. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  316. macro_redefinition, name.get_value().c_str(), main_pos,
  317. name.get_value().c_str());
  318. }
  319. return false;
  320. }
  321. // test the validity of the parameter names
  322. if (has_parameters) {
  323. std::set<typename token_type::string_type> names;
  324. typedef typename parameter_container_type::iterator
  325. parameter_iterator_type;
  326. typedef typename std::set<typename token_type::string_type>::iterator
  327. name_iterator_type;
  328. parameter_iterator_type end = parameters.end();
  329. for (parameter_iterator_type itp = parameters.begin(); itp != end; ++itp)
  330. {
  331. name_iterator_type pit = names.find((*itp).get_value());
  332. if (pit != names.end()) {
  333. // duplicate parameter name
  334. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  335. duplicate_parameter_name, (*pit).c_str(), main_pos,
  336. name.get_value().c_str());
  337. return false;
  338. }
  339. names.insert((*itp).get_value());
  340. }
  341. }
  342. #if BOOST_WAVE_SUPPORT_VA_OPT != 0
  343. // check that __VA_OPT__ is used as a function macro
  344. if (boost::wave::need_va_opt(ctx.get_language())) {
  345. // __VA_OPT__, if present, must be followed by an lparen
  346. typedef typename macro_definition_type::const_definition_iterator_t iter_t;
  347. iter_t mdit = definition.begin();
  348. iter_t mdend = definition.end();
  349. for (; mdit != mdend; ++mdit) {
  350. // is this va_opt?
  351. if ((IS_EXTCATEGORY((*mdit), OptParameterTokenType)) || // if params replaced
  352. ("__VA_OPT__" == (*mdit).get_value())) { // if not
  353. iter_t va_opt_it = mdit;
  354. // next must be lparen
  355. if ((++mdit == mdend) || // no further tokens
  356. (T_LEFTPAREN != token_id(*mdit))) { // not lparen
  357. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  358. bad_define_statement_va_opt_parens,
  359. name.get_value().c_str(), main_pos,
  360. name.get_value().c_str());
  361. return false;
  362. }
  363. // check that no __VA_OPT__ appears inside
  364. iter_t va_opt_end = va_opt_it;
  365. if (!impl::find_va_opt_args(va_opt_end, mdend)) {
  366. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  367. improperly_terminated_macro, "missing ')' in __VA_OPT__",
  368. main_pos);
  369. return false;
  370. }
  371. // skip initial __VA_OPT__ and lparen
  372. ++va_opt_it; ++va_opt_it;
  373. for (;va_opt_it != va_opt_end; ++va_opt_it) {
  374. if ((IS_EXTCATEGORY((*va_opt_it), OptParameterTokenType)) ||
  375. ("__VA_OPT__" == (*va_opt_it).get_value())) {
  376. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  377. bad_define_statement_va_opt_recurse,
  378. name.get_value().c_str(), (*va_opt_it).get_position(),
  379. name.get_value().c_str());
  380. }
  381. }
  382. }
  383. }
  384. }
  385. #endif
  386. // insert a new macro node
  387. std::pair<typename defined_macros_type::iterator, bool> p =
  388. current_scope->insert(
  389. typename defined_macros_type::value_type(
  390. name.get_value(),
  391. macro_ref_type(new macro_definition_type(name,
  392. has_parameters, is_predefined, ++macro_uid)
  393. )
  394. )
  395. );
  396. if (!p.second) {
  397. BOOST_WAVE_THROW_NAME_CTX(ctx, macro_handling_exception,
  398. macro_insertion_error, name.get_value().c_str(), main_pos,
  399. name.get_value().c_str());
  400. return false;
  401. }
  402. // add the parameters and the definition
  403. std::swap((*p.first).second->macroparameters, parameters);
  404. std::swap((*p.first).second->macrodefinition, definition);
  405. // call the context supplied preprocessing hook
  406. ctx.get_hooks().defined_macro(ctx.derived(), name, has_parameters,
  407. (*p.first).second->macroparameters,
  408. (*p.first).second->macrodefinition, is_predefined);
  409. return true;
  410. }
  411. ///////////////////////////////////////////////////////////////////////////////
  412. //
  413. // is_defined(): returns, whether a given macro is already defined
  414. //
  415. ///////////////////////////////////////////////////////////////////////////////
  416. template <typename ContextT>
  417. inline bool
  418. macromap<ContextT>::is_defined(typename token_type::string_type const &name,
  419. typename defined_macros_type::iterator &it,
  420. defined_macros_type *scope) const
  421. {
  422. if (0 == scope) scope = current_macros;
  423. if ((it = scope->find(name)) != scope->end())
  424. return true; // found in symbol table
  425. // quick pre-check
  426. if (name.size() < 8 || '_' != name[0] || '_' != name[1])
  427. return false; // quick check failed
  428. if (name == "__LINE__" || name == "__FILE__" ||
  429. name == "__INCLUDE_LEVEL__")
  430. return true;
  431. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  432. return (boost::wave::need_has_include(ctx.get_language()) &&
  433. (name == "__has_include"));
  434. #else
  435. return false;
  436. #endif
  437. }
  438. template <typename ContextT>
  439. template <typename IteratorT>
  440. inline bool
  441. macromap<ContextT>::is_defined(IteratorT const &begin,
  442. IteratorT const &end) const
  443. {
  444. // in normal mode the name under inspection should consist of an identifier
  445. // only
  446. token_id id = token_id(*begin);
  447. if (T_IDENTIFIER != id &&
  448. !IS_CATEGORY(id, KeywordTokenType) &&
  449. !IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) &&
  450. !IS_CATEGORY(id, BoolLiteralTokenType))
  451. {
  452. std::string msg(impl::get_full_name(begin, end));
  453. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname,
  454. msg.c_str(), main_pos);
  455. return false;
  456. }
  457. IteratorT it = begin;
  458. string_type name((*it).get_value());
  459. typename defined_macros_type::iterator cit;
  460. if (++it != end) {
  461. // there should be only one token as the inspected name
  462. std::string msg(impl::get_full_name(begin, end));
  463. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_macroname,
  464. msg.c_str(), main_pos);
  465. return false;
  466. }
  467. return is_defined(name, cit, 0);
  468. }
  469. ///////////////////////////////////////////////////////////////////////////////
  470. // same as above, only takes an arbitrary string type as its parameter
  471. template <typename ContextT>
  472. inline bool
  473. macromap<ContextT>::is_defined(string_type const &str) const
  474. {
  475. typename defined_macros_type::iterator cit;
  476. return is_defined(str, cit, 0);
  477. }
  478. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  479. ///////////////////////////////////////////////////////////////////////////////
  480. //
  481. // has_include(): returns whether a path expression is an valid include file
  482. //
  483. ///////////////////////////////////////////////////////////////////////////////
  484. template <typename ContextT>
  485. template <typename IteratorT>
  486. inline bool
  487. macromap<ContextT>::has_include(
  488. IteratorT const &begin, IteratorT const &end,
  489. bool is_quoted_filename, bool is_system) const
  490. {
  491. typename ContextT::token_sequence_type filetoks;
  492. if (is_quoted_filename) {
  493. filetoks = typename ContextT::token_sequence_type(begin, end);
  494. } else {
  495. IteratorT first = begin;
  496. IteratorT last = end;
  497. ctx.expand_whole_tokensequence(first, last, filetoks);
  498. }
  499. // extract tokens into string and trim whitespace
  500. using namespace boost::wave::util::impl;
  501. std::string fn(trim_whitespace(as_string(filetoks)).c_str());
  502. // verify and remove initial and final delimiters
  503. if (!((fn.size() >= 3) &&
  504. (((fn[0] == '"') && (*fn.rbegin() == '"')) ||
  505. ((fn[0] == '<') && (*fn.rbegin() == '>')))))
  506. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_has_include_expression,
  507. fn.c_str(), ctx.get_main_pos());
  508. fn = fn.substr(1, fn.size() - 2);
  509. // test header existence
  510. std::string dir_path;
  511. std::string native_path;
  512. return ctx.get_hooks().locate_include_file(
  513. ctx, fn, is_system, 0, dir_path, native_path);
  514. }
  515. #endif
  516. ///////////////////////////////////////////////////////////////////////////////
  517. //
  518. // Get the macro definition for the given macro scope
  519. //
  520. ///////////////////////////////////////////////////////////////////////////////
  521. template <typename ContextT>
  522. inline bool
  523. macromap<ContextT>::get_macro(string_type const &name, bool &has_parameters,
  524. bool &is_predefined, position_type &pos,
  525. parameter_container_type &parameters,
  526. definition_container_type &definition,
  527. defined_macros_type *scope) const
  528. {
  529. typename defined_macros_type::iterator it;
  530. if (!is_defined(name, it, scope))
  531. return false;
  532. macro_definition_type& macro_def = *(*it).second.get();
  533. has_parameters = macro_def.is_functionlike;
  534. is_predefined = macro_def.is_predefined;
  535. pos = macro_def.macroname.get_position();
  536. parameters = macro_def.macroparameters;
  537. definition = macro_def.macrodefinition;
  538. return true;
  539. }
  540. ///////////////////////////////////////////////////////////////////////////////
  541. //
  542. // remove_macro(): remove a macro from the macromap
  543. //
  544. ///////////////////////////////////////////////////////////////////////////////
  545. template <typename ContextT>
  546. inline bool
  547. macromap<ContextT>::remove_macro(string_type const &name,
  548. position_type const& pos, bool even_predefined)
  549. {
  550. typename defined_macros_type::iterator it = current_macros->find(name);
  551. if (it != current_macros->end()) {
  552. if ((*it).second->is_predefined) {
  553. if (!even_predefined || impl::is_special_macroname(ctx, name)) {
  554. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  555. bad_undefine_statement, name.c_str(), main_pos);
  556. return false;
  557. }
  558. }
  559. current_macros->erase(it);
  560. // call the context supplied preprocessing hook function
  561. token_type tok(T_IDENTIFIER, name, pos);
  562. ctx.get_hooks().undefined_macro(ctx.derived(), tok);
  563. return true;
  564. }
  565. else if (impl::is_special_macroname(ctx, name)) {
  566. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, bad_undefine_statement,
  567. name.c_str(), pos);
  568. }
  569. return false; // macro was not defined
  570. }
  571. ///////////////////////////////////////////////////////////////////////////////
  572. //
  573. // expand_tokensequence
  574. //
  575. // This function is a helper function which wraps the given iterator
  576. // range into corresponding unput_iterator's and calls the main workhorse
  577. // of the macro expansion engine (the function expand_tokensequence_worker)
  578. //
  579. // This is the top level macro expansion function called from the
  580. // preprocessing iterator component only.
  581. //
  582. ///////////////////////////////////////////////////////////////////////////////
  583. template <typename ContextT>
  584. template <typename IteratorT, typename ContainerT>
  585. inline typename ContextT::token_type const &
  586. macromap<ContextT>::expand_tokensequence(IteratorT &first,
  587. IteratorT const &last, ContainerT &pending, ContainerT &expanded,
  588. bool& seen_newline, bool expand_operator_defined,
  589. bool expand_operator_has_include)
  590. {
  591. typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
  592. gen_type;
  593. typedef typename gen_type::return_type iterator_type;
  594. iterator_type first_it = gen_type::generate(expanded, first);
  595. iterator_type last_it = gen_type::generate(last);
  596. on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
  597. return expand_tokensequence_worker(pending, first_it, last_it,
  598. seen_newline, expand_operator_defined, expand_operator_has_include,
  599. boost::none);
  600. }
  601. ///////////////////////////////////////////////////////////////////////////////
  602. //
  603. // expand_tokensequence_worker
  604. //
  605. // This function is the main workhorse of the macro expansion engine. It
  606. // expands as much tokens as needed to identify the next preprocessed
  607. // token to return to the caller.
  608. // It returns the next preprocessed token.
  609. //
  610. // The iterator 'first' is adjusted accordingly.
  611. //
  612. ///////////////////////////////////////////////////////////////////////////////
  613. template <typename ContextT>
  614. template <typename IteratorT, typename ContainerT>
  615. inline typename ContextT::token_type const &
  616. macromap<ContextT>::expand_tokensequence_worker(
  617. ContainerT &pending,
  618. unput_queue_iterator<IteratorT, token_type, ContainerT> &first,
  619. unput_queue_iterator<IteratorT, token_type, ContainerT> const &last,
  620. bool& seen_newline, bool expand_operator_defined,
  621. bool expand_operator_has_include,
  622. boost::optional<position_type> expanding_pos)
  623. {
  624. // if there exist pending tokens (tokens, which are already preprocessed), then
  625. // return the next one from there
  626. if (!pending.empty()) {
  627. on_exit::pop_front<definition_container_type> pop_front_token(pending);
  628. return act_token = pending.front();
  629. }
  630. // analyze the next element of the given sequence, if it is an
  631. // T_IDENTIFIER token, try to replace this as a macro etc.
  632. using namespace boost::wave;
  633. if (first != last) {
  634. token_id id = token_id(*first);
  635. // ignore placeholder tokens
  636. if (T_PLACEHOLDER == id) {
  637. token_type placeholder = *first;
  638. ++first;
  639. if (first == last)
  640. return act_token = placeholder;
  641. id = token_id(*first);
  642. }
  643. if (T_IDENTIFIER == id || IS_CATEGORY(id, KeywordTokenType) ||
  644. IS_EXTCATEGORY(id, OperatorTokenType|AltExtTokenType) ||
  645. IS_CATEGORY(id, BoolLiteralTokenType))
  646. {
  647. // try to replace this identifier as a macro
  648. if (expand_operator_defined && (*first).get_value() == "defined") {
  649. // resolve operator defined()
  650. return resolve_defined(first, last, pending);
  651. }
  652. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  653. else if (boost::wave::need_has_include(ctx.get_language()) &&
  654. expand_operator_has_include &&
  655. (*first).get_value() == "__has_include") {
  656. // resolve operator __has_include()
  657. return resolve_has_include(first, last, pending);
  658. }
  659. #endif
  660. else if (boost::wave::need_variadics(ctx.get_language()) &&
  661. (*first).get_value() == "_Pragma")
  662. {
  663. // in C99 mode only: resolve the operator _Pragma
  664. token_type curr_token = *first;
  665. if (!resolve_operator_pragma(first, last, pending, seen_newline) ||
  666. pending.size() > 0)
  667. {
  668. // unknown to us pragma or supplied replacement, return the
  669. // next token
  670. on_exit::pop_front<definition_container_type> pop_token(pending);
  671. return act_token = pending.front();
  672. }
  673. // the operator _Pragma() was eaten completely, continue
  674. return act_token = token_type(T_PLACEHOLDER, "_",
  675. curr_token.get_position());
  676. }
  677. token_type name_token(*first);
  678. typename defined_macros_type::iterator it;
  679. if (is_defined(name_token.get_value(), it)) {
  680. // the current token contains an identifier, which is currently
  681. // defined as a macro
  682. if (expand_macro(pending, name_token, it, first, last,
  683. seen_newline, expand_operator_defined,
  684. expand_operator_has_include,
  685. expanding_pos))
  686. {
  687. // the tokens returned by expand_macro should be rescanned
  688. // beginning at the last token of the returned replacement list
  689. if (first != last) {
  690. // splice the last token back into the input queue
  691. typename ContainerT::reverse_iterator rit = pending.rbegin();
  692. first.get_unput_queue().splice(
  693. first.get_unput_queue().begin(), pending,
  694. (++rit).base(), pending.end());
  695. }
  696. // fall through ...
  697. }
  698. else if (!pending.empty()) {
  699. // return the first token from the pending queue
  700. on_exit::pop_front<definition_container_type> pop_queue(pending);
  701. return act_token = pending.front();
  702. }
  703. else {
  704. // macro expansion reached the eoi
  705. return act_token = token_type();
  706. }
  707. // return the next preprocessed token
  708. if (!expanding_pos)
  709. expanding_pos = name_token.get_expand_position();
  710. typename ContextT::token_type const & result =
  711. expand_tokensequence_worker(
  712. pending, first, last,
  713. seen_newline, expand_operator_defined,
  714. expand_operator_has_include,
  715. expanding_pos);
  716. return result;
  717. }
  718. else {
  719. act_token = name_token;
  720. ++first;
  721. return act_token;
  722. }
  723. }
  724. else if (expand_operator_defined && IS_CATEGORY(*first, BoolLiteralTokenType)) {
  725. // expanding a constant expression inside #if/#elif, special handling
  726. // of 'true' and 'false'
  727. // all remaining identifiers and keywords, except for true and false,
  728. // are replaced with the pp-number 0 (C++ standard 16.1.4, [cpp.cond])
  729. return act_token = token_type(T_INTLIT, T_TRUE != id ? "0" : "1",
  730. (*first++).get_position());
  731. }
  732. else {
  733. act_token = *first;
  734. ++first;
  735. return act_token;
  736. }
  737. }
  738. return act_token = token_type(); // eoi
  739. }
  740. ///////////////////////////////////////////////////////////////////////////////
  741. //
  742. // collect_arguments(): collect the actual arguments of a macro invocation
  743. //
  744. // return the number of successfully detected non-empty arguments
  745. //
  746. ///////////////////////////////////////////////////////////////////////////////
  747. template <typename ContextT>
  748. template <typename IteratorT, typename ContainerT, typename SizeT>
  749. inline typename std::vector<ContainerT>::size_type
  750. macromap<ContextT>::collect_arguments (token_type const curr_token,
  751. std::vector<ContainerT> &arguments, IteratorT &next, IteratorT &endparen,
  752. IteratorT const &end, SizeT const &parameter_count, bool& seen_newline)
  753. {
  754. using namespace boost::wave;
  755. arguments.push_back(ContainerT());
  756. // collect the actual arguments
  757. typename std::vector<ContainerT>::size_type count_arguments = 0;
  758. int nested_parenthesis_level = 1;
  759. ContainerT* argument = &arguments[0];
  760. bool was_whitespace = false;
  761. token_type startof_argument_list = *next;
  762. while (++next != end && nested_parenthesis_level) {
  763. token_id id = token_id(*next);
  764. if (0 == parameter_count &&
  765. !IS_CATEGORY((*next), WhiteSpaceTokenType) && id != T_NEWLINE &&
  766. id != T_RIGHTPAREN && id != T_LEFTPAREN)
  767. {
  768. // there shouldn't be any arguments
  769. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  770. too_many_macroarguments, curr_token.get_value().c_str(),
  771. main_pos);
  772. return 0;
  773. }
  774. switch (id) {
  775. case T_LEFTPAREN:
  776. ++nested_parenthesis_level;
  777. argument->push_back(*next);
  778. was_whitespace = false;
  779. break;
  780. case T_RIGHTPAREN:
  781. {
  782. if (--nested_parenthesis_level >= 1)
  783. argument->push_back(*next);
  784. else {
  785. // found closing parenthesis
  786. // trim_sequence(argument);
  787. endparen = next;
  788. if (parameter_count > 0) {
  789. if (argument->empty() ||
  790. impl::is_whitespace_only(*argument))
  791. {
  792. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  793. if (boost::wave::need_variadics(ctx.get_language())) {
  794. // store a placemarker as the argument
  795. argument->push_back(token_type(T_PLACEMARKER, "\xA7",
  796. (*next).get_position()));
  797. ++count_arguments;
  798. }
  799. #endif
  800. }
  801. else {
  802. ++count_arguments;
  803. }
  804. }
  805. }
  806. was_whitespace = false;
  807. }
  808. break;
  809. case T_COMMA:
  810. if (1 == nested_parenthesis_level) {
  811. // next parameter
  812. // trim_sequence(argument);
  813. if (argument->empty() ||
  814. impl::is_whitespace_only(*argument))
  815. {
  816. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  817. if (boost::wave::need_variadics(ctx.get_language())) {
  818. // store a placemarker as the argument
  819. argument->push_back(token_type(T_PLACEMARKER, "\xA7",
  820. (*next).get_position()));
  821. ++count_arguments;
  822. }
  823. #endif
  824. }
  825. else {
  826. ++count_arguments;
  827. }
  828. arguments.push_back(ContainerT()); // add new arg
  829. argument = &arguments[arguments.size()-1];
  830. }
  831. else {
  832. // surrounded by parenthesises, so store to current argument
  833. argument->push_back(*next);
  834. }
  835. was_whitespace = false;
  836. break;
  837. case T_NEWLINE:
  838. seen_newline = true;
  839. /* fall through */
  840. case T_SPACE:
  841. case T_SPACE2:
  842. case T_CCOMMENT:
  843. if (!was_whitespace)
  844. argument->push_back(token_type(T_SPACE, " ", (*next).get_position()));
  845. was_whitespace = true;
  846. break; // skip whitespace
  847. case T_PLACEHOLDER:
  848. break; // ignore placeholder
  849. default:
  850. argument->push_back(*next);
  851. was_whitespace = false;
  852. break;
  853. }
  854. }
  855. if (nested_parenthesis_level >= 1) {
  856. // missing ')': improperly terminated macro invocation
  857. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  858. improperly_terminated_macro, "missing ')'", main_pos);
  859. return 0;
  860. }
  861. // if no argument was expected and we didn't find any, than remove the empty
  862. // element
  863. if (0 == parameter_count && 0 == count_arguments) {
  864. BOOST_ASSERT(1 == arguments.size());
  865. arguments.clear();
  866. }
  867. return count_arguments;
  868. }
  869. ///////////////////////////////////////////////////////////////////////////////
  870. //
  871. // expand_whole_tokensequence
  872. //
  873. // fully expands a given token sequence
  874. //
  875. ///////////////////////////////////////////////////////////////////////////////
  876. template <typename ContextT>
  877. template <typename IteratorT, typename ContainerT>
  878. inline void
  879. macromap<ContextT>::expand_whole_tokensequence(ContainerT &expanded,
  880. IteratorT &first, IteratorT const &last,
  881. bool expand_operator_defined,
  882. bool expand_operator_has_include)
  883. {
  884. typedef impl::gen_unput_queue_iterator<IteratorT, token_type, ContainerT>
  885. gen_type;
  886. typedef typename gen_type::return_type iterator_type;
  887. ContainerT empty;
  888. iterator_type first_it = gen_type::generate(empty, first);
  889. iterator_type last_it = gen_type::generate(last);
  890. on_exit::assign<IteratorT, iterator_type> on_exit(first, first_it);
  891. ContainerT pending_queue;
  892. bool seen_newline;
  893. while (!pending_queue.empty() || first_it != last_it) {
  894. expanded.push_back(
  895. expand_tokensequence_worker(
  896. pending_queue, first_it,
  897. last_it, seen_newline, expand_operator_defined,
  898. expand_operator_has_include,
  899. boost::none)
  900. );
  901. }
  902. // should have returned all expanded tokens
  903. BOOST_ASSERT(pending_queue.empty()/* && unput_queue.empty()*/);
  904. }
  905. ///////////////////////////////////////////////////////////////////////////////
  906. //
  907. // expand_argument
  908. //
  909. // fully expands the given argument of a macro call
  910. //
  911. ///////////////////////////////////////////////////////////////////////////////
  912. template <typename ContextT>
  913. template <typename ContainerT>
  914. inline void
  915. macromap<ContextT>::expand_argument (
  916. typename std::vector<ContainerT>::size_type arg,
  917. std::vector<ContainerT> &arguments, std::vector<ContainerT> &expanded_args,
  918. bool expand_operator_defined, bool expand_operator_has_include,
  919. std::vector<bool> &has_expanded_args)
  920. {
  921. if (!has_expanded_args[arg]) {
  922. // expand the argument only once
  923. typedef typename std::vector<ContainerT>::value_type::iterator
  924. argument_iterator_type;
  925. argument_iterator_type begin_it = arguments[arg].begin();
  926. argument_iterator_type end_it = arguments[arg].end();
  927. expand_whole_tokensequence(
  928. expanded_args[arg], begin_it, end_it,
  929. expand_operator_defined, expand_operator_has_include);
  930. impl::remove_placeholders(expanded_args[arg]);
  931. has_expanded_args[arg] = true;
  932. }
  933. }
  934. ///////////////////////////////////////////////////////////////////////////////
  935. //
  936. // expand_replacement_list
  937. //
  938. // fully expands the replacement list of a given macro with the
  939. // actual arguments/expanded arguments
  940. // handles the '#' [cpp.stringize] and the '##' [cpp.concat] operator
  941. //
  942. ///////////////////////////////////////////////////////////////////////////////
  943. template <typename ContextT>
  944. template <typename ContainerT>
  945. inline void
  946. macromap<ContextT>::expand_replacement_list(
  947. typename macro_definition_type::const_definition_iterator_t cit,
  948. typename macro_definition_type::const_definition_iterator_t cend,
  949. std::vector<ContainerT> &arguments, bool expand_operator_defined,
  950. bool expand_operator_has_include,
  951. ContainerT &expanded)
  952. {
  953. using namespace boost::wave;
  954. typedef typename macro_definition_type::const_definition_iterator_t
  955. macro_definition_iter_t;
  956. std::vector<ContainerT> expanded_args(arguments.size());
  957. std::vector<bool> has_expanded_args(arguments.size());
  958. bool seen_concat = false;
  959. bool adjacent_concat = false;
  960. bool adjacent_stringize = false;
  961. for (;cit != cend; ++cit)
  962. {
  963. bool use_replaced_arg = true;
  964. token_id base_id = BASE_TOKEN(token_id(*cit));
  965. if (T_POUND_POUND == base_id) {
  966. // concatenation operator
  967. adjacent_concat = true;
  968. seen_concat = true;
  969. }
  970. else if (T_POUND == base_id) {
  971. // stringize operator
  972. adjacent_stringize = true;
  973. }
  974. else {
  975. if (adjacent_stringize || adjacent_concat ||
  976. T_POUND_POUND == impl::next_token<macro_definition_iter_t>
  977. ::peek(cit, cend))
  978. {
  979. use_replaced_arg = false;
  980. }
  981. if (adjacent_concat) // spaces after '##' ?
  982. adjacent_concat = IS_CATEGORY(*cit, WhiteSpaceTokenType);
  983. }
  984. if (IS_CATEGORY((*cit), ParameterTokenType)) {
  985. // copy argument 'i' instead of the parameter token i
  986. typename ContainerT::size_type i;
  987. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  988. bool is_ellipsis = false;
  989. #if BOOST_WAVE_SUPPORT_VA_OPT != 0
  990. bool is_va_opt = false;
  991. #endif
  992. if (IS_EXTCATEGORY((*cit), ExtParameterTokenType)) {
  993. BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
  994. i = token_id(*cit) - T_EXTPARAMETERBASE;
  995. is_ellipsis = true;
  996. }
  997. else
  998. #if BOOST_WAVE_SUPPORT_VA_OPT != 0
  999. if (IS_EXTCATEGORY((*cit), OptParameterTokenType)) {
  1000. BOOST_ASSERT(boost::wave::need_va_opt(ctx.get_language()));
  1001. i = token_id(*cit) - T_OPTPARAMETERBASE;
  1002. is_va_opt = true;
  1003. }
  1004. else
  1005. #endif
  1006. #endif
  1007. {
  1008. i = token_id(*cit) - T_PARAMETERBASE;
  1009. }
  1010. BOOST_ASSERT(i <= arguments.size());
  1011. if (use_replaced_arg) {
  1012. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1013. if (is_ellipsis) {
  1014. position_type const& pos = (*cit).get_position();
  1015. BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
  1016. // ensure all variadic arguments to be expanded
  1017. for (typename vector<ContainerT>::size_type arg = i;
  1018. arg < expanded_args.size(); ++arg)
  1019. {
  1020. expand_argument(
  1021. arg, arguments, expanded_args,
  1022. expand_operator_defined, expand_operator_has_include,
  1023. has_expanded_args);
  1024. }
  1025. impl::replace_ellipsis(expanded_args, i, expanded, pos);
  1026. }
  1027. else
  1028. #if BOOST_WAVE_SUPPORT_VA_OPT != 0
  1029. if (is_va_opt) {
  1030. position_type const &pos = (*cit).get_position();
  1031. BOOST_ASSERT(boost::wave::need_va_opt(ctx.get_language()));
  1032. // ensure all variadic arguments to be expanded
  1033. for (typename vector<ContainerT>::size_type arg = i;
  1034. arg < expanded_args.size(); ++arg)
  1035. {
  1036. expand_argument(
  1037. arg, arguments, expanded_args,
  1038. expand_operator_defined, expand_operator_has_include,
  1039. has_expanded_args);
  1040. }
  1041. // locate the end of the __VA_OPT__ call
  1042. typename macro_definition_type::const_definition_iterator_t cstart = cit;
  1043. if (!impl::find_va_opt_args(cit, cend)) {
  1044. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1045. improperly_terminated_macro, "missing '(' or ')' in __VA_OPT__",
  1046. pos);
  1047. }
  1048. // cstart still points to __VA_OPT__; cit now points to the last rparen
  1049. // locate the __VA_OPT__ arguments
  1050. typename macro_definition_type::const_definition_iterator_t arg_start = cstart;
  1051. ++arg_start; // skip __VA_OPT__
  1052. ++arg_start; // skip lparen
  1053. // create a synthetic macro definition for use with hooks
  1054. token_type macroname(T_IDENTIFIER, "__VA_OPT__", position_type("<built-in>"));
  1055. parameter_container_type macroparameters;
  1056. macroparameters.push_back(token_type(T_ELLIPSIS, "...", position_type("<built-in>")));
  1057. definition_container_type macrodefinition;
  1058. bool suppress_expand = false;
  1059. // __VA_OPT__ treats its arguments as an undifferentiated stream of tokens
  1060. // for our purposes we can consider it as a single argument
  1061. typename std::vector<ContainerT> va_opt_args(1, ContainerT(arg_start, cit));
  1062. suppress_expand = ctx.get_hooks().expanding_function_like_macro(
  1063. ctx.derived(),
  1064. macroname, macroparameters, macrodefinition,
  1065. *cstart, va_opt_args,
  1066. cstart, cit);
  1067. if (suppress_expand) {
  1068. // leave the whole expression in place
  1069. std::copy(cstart, cit, std::back_inserter(expanded));
  1070. expanded.push_back(*cit); // include the rparen
  1071. } else {
  1072. ContainerT va_expanded;
  1073. if ((i == arguments.size()) || // no variadic argument
  1074. impl::is_whitespace_only(arguments[i])) { // no visible tokens
  1075. // no args; insert placemarker
  1076. va_expanded.push_back(
  1077. typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
  1078. } else if (!impl::is_blank_only(arguments[i])) {
  1079. // [cstart, cit) is now the args to va_opt
  1080. // recursively process them
  1081. expand_replacement_list(arg_start, cit, arguments,
  1082. expand_operator_defined,
  1083. expand_operator_has_include,
  1084. va_expanded);
  1085. }
  1086. // run final hooks
  1087. ctx.get_hooks().expanded_macro(ctx.derived(), va_expanded);
  1088. // updated overall expansion with va_opt results
  1089. expanded.splice(expanded.end(), va_expanded);
  1090. }
  1091. // continue from rparen
  1092. }
  1093. else
  1094. #endif
  1095. #endif
  1096. {
  1097. BOOST_ASSERT(i < arguments.size());
  1098. // ensure argument i to be expanded
  1099. expand_argument(
  1100. i, arguments, expanded_args,
  1101. expand_operator_defined, expand_operator_has_include,
  1102. has_expanded_args);
  1103. // replace argument
  1104. BOOST_ASSERT(i < expanded_args.size());
  1105. ContainerT const& arg = expanded_args[i];
  1106. std::copy(arg.begin(), arg.end(),
  1107. std::inserter(expanded, expanded.end()));
  1108. }
  1109. }
  1110. else if (adjacent_stringize &&
  1111. !IS_CATEGORY(*cit, WhiteSpaceTokenType))
  1112. {
  1113. // stringize the current argument
  1114. BOOST_ASSERT(!arguments[i].empty());
  1115. // safe a copy of the first tokens position (not a reference!)
  1116. position_type pos((*arguments[i].begin()).get_position());
  1117. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1118. if (is_ellipsis && boost::wave::need_variadics(ctx.get_language())) {
  1119. impl::trim_sequence_left(arguments[i]);
  1120. impl::trim_sequence_right(arguments.back());
  1121. expanded.push_back(token_type(T_STRINGLIT,
  1122. impl::as_stringlit(arguments, i, pos), pos));
  1123. }
  1124. else
  1125. #endif
  1126. {
  1127. impl::trim_sequence(arguments[i]);
  1128. expanded.push_back(token_type(T_STRINGLIT,
  1129. impl::as_stringlit(arguments[i], pos), pos));
  1130. }
  1131. adjacent_stringize = false;
  1132. }
  1133. else {
  1134. // simply copy the original argument (adjacent '##' or '#')
  1135. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1136. if (is_ellipsis) {
  1137. position_type const& pos = (*cit).get_position();
  1138. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1139. if (i < arguments.size())
  1140. #endif
  1141. {
  1142. impl::trim_sequence_left(arguments[i]);
  1143. impl::trim_sequence_right(arguments.back());
  1144. BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
  1145. impl::replace_ellipsis(arguments, i, expanded, pos);
  1146. }
  1147. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1148. else if (boost::wave::need_cpp2a(ctx.get_language())) {
  1149. BOOST_ASSERT(i == arguments.size());
  1150. // no argument supplied; insert placemarker
  1151. expanded.push_back(
  1152. typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
  1153. }
  1154. #endif
  1155. }
  1156. else
  1157. #endif
  1158. {
  1159. ContainerT& arg = arguments[i];
  1160. impl::trim_sequence(arg);
  1161. std::copy(arg.begin(), arg.end(),
  1162. std::inserter(expanded, expanded.end()));
  1163. }
  1164. }
  1165. }
  1166. else if (!adjacent_stringize || T_POUND != base_id) {
  1167. // insert the actual replacement token (if it is not the '#' operator)
  1168. expanded.push_back(*cit);
  1169. }
  1170. }
  1171. if (adjacent_stringize) {
  1172. // error, '#' should not be the last token
  1173. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator,
  1174. "stringize ('#')", main_pos);
  1175. return;
  1176. }
  1177. // handle the cpp.concat operator
  1178. if (seen_concat)
  1179. concat_tokensequence(expanded);
  1180. }
  1181. ///////////////////////////////////////////////////////////////////////////////
  1182. //
  1183. // rescan_replacement_list
  1184. //
  1185. // As the name implies, this function is used to rescan the replacement list
  1186. // after the first macro substitution phase.
  1187. //
  1188. ///////////////////////////////////////////////////////////////////////////////
  1189. template <typename ContextT>
  1190. template <typename IteratorT, typename ContainerT>
  1191. inline void
  1192. macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
  1193. macro_definition_type &macro_def, ContainerT &replacement_list,
  1194. ContainerT &expanded,
  1195. bool expand_operator_defined,
  1196. bool expand_operator_has_include,
  1197. IteratorT &nfirst, IteratorT const &nlast)
  1198. {
  1199. if (!replacement_list.empty()) {
  1200. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1201. // remove the placemarkers
  1202. if (boost::wave::need_variadics(ctx.get_language())) {
  1203. typename ContainerT::iterator end = replacement_list.end();
  1204. typename ContainerT::iterator it = replacement_list.begin();
  1205. while (it != end) {
  1206. using namespace boost::wave;
  1207. if (T_PLACEMARKER == token_id(*it)) {
  1208. typename ContainerT::iterator placemarker = it;
  1209. ++it;
  1210. replacement_list.erase(placemarker);
  1211. }
  1212. else {
  1213. ++it;
  1214. }
  1215. }
  1216. }
  1217. #endif
  1218. // rescan the replacement list, during this rescan the current macro under
  1219. // expansion isn't available as an expandable macro
  1220. on_exit::reset<bool> on_exit(macro_def.is_available_for_replacement, false);
  1221. typename ContainerT::iterator begin_it = replacement_list.begin();
  1222. typename ContainerT::iterator end_it = replacement_list.end();
  1223. expand_whole_tokensequence(
  1224. expanded, begin_it, end_it,
  1225. expand_operator_defined, expand_operator_has_include);
  1226. // trim replacement list, leave placeholder tokens untouched
  1227. impl::trim_replacement_list(expanded);
  1228. }
  1229. if (expanded.empty()) {
  1230. // the resulting replacement list should contain at least a placeholder
  1231. // token
  1232. expanded.push_back(token_type(T_PLACEHOLDER, "_", curr_token.get_position()));
  1233. }
  1234. }
  1235. ///////////////////////////////////////////////////////////////////////////////
  1236. //
  1237. // expand_macro(): expands a defined macro
  1238. //
  1239. // This functions tries to expand the macro, to which points the 'first'
  1240. // iterator. The functions eats up more tokens, if the macro to expand is
  1241. // a function-like macro.
  1242. //
  1243. ///////////////////////////////////////////////////////////////////////////////
  1244. template <typename ContextT>
  1245. template <typename IteratorT, typename ContainerT>
  1246. inline bool
  1247. macromap<ContextT>::expand_macro(ContainerT &expanded,
  1248. token_type const &curr_token, typename defined_macros_type::iterator it,
  1249. IteratorT &first, IteratorT const &last,
  1250. bool& seen_newline, bool expand_operator_defined,
  1251. bool expand_operator_has_include,
  1252. boost::optional<position_type> expanding_pos,
  1253. defined_macros_type *scope, ContainerT *queue_symbol)
  1254. {
  1255. using namespace boost::wave;
  1256. if (0 == scope) scope = current_macros;
  1257. BOOST_ASSERT(T_IDENTIFIER == token_id(curr_token) ||
  1258. IS_CATEGORY(token_id(curr_token), KeywordTokenType) ||
  1259. IS_EXTCATEGORY(token_id(curr_token), OperatorTokenType|AltExtTokenType) ||
  1260. IS_CATEGORY(token_id(curr_token), BoolLiteralTokenType));
  1261. if (it == scope->end()) {
  1262. ++first; // advance
  1263. // try to expand a predefined macro (__FILE__, __LINE__ or __INCLUDE_LEVEL__)
  1264. if (expand_predefined_macro(curr_token, expanded))
  1265. return false;
  1266. // not defined as a macro
  1267. if (0 != queue_symbol) {
  1268. expanded.splice(expanded.end(), *queue_symbol);
  1269. }
  1270. else {
  1271. expanded.push_back(curr_token);
  1272. }
  1273. return false;
  1274. }
  1275. // ensure the parameters to be replaced with special parameter tokens
  1276. macro_definition_type& macro_def = *(*it).second.get();
  1277. macro_def.replace_parameters(ctx);
  1278. // test if this macro is currently available for replacement
  1279. if (!macro_def.is_available_for_replacement) {
  1280. // this macro is marked as non-replaceable
  1281. // copy the macro name itself
  1282. if (0 != queue_symbol) {
  1283. queue_symbol->push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
  1284. curr_token.get_value(), curr_token.get_position()));
  1285. expanded.splice(expanded.end(), *queue_symbol);
  1286. }
  1287. else {
  1288. expanded.push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
  1289. curr_token.get_value(), curr_token.get_position()));
  1290. }
  1291. ++first;
  1292. return false;
  1293. }
  1294. // try to replace the current identifier as a function-like macro
  1295. ContainerT replacement_list;
  1296. if (T_LEFTPAREN == impl::next_token<IteratorT>::peek(first, last)) {
  1297. // called as a function-like macro
  1298. impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline);
  1299. IteratorT seqstart = first;
  1300. IteratorT seqend = first;
  1301. if (macro_def.is_functionlike) {
  1302. // defined as a function-like macro
  1303. // collect the arguments
  1304. std::vector<ContainerT> arguments;
  1305. typename std::vector<ContainerT>::size_type count_args =
  1306. collect_arguments(curr_token, arguments, first, seqend, last,
  1307. macro_def.macroparameters.size(), seen_newline);
  1308. std::size_t parm_count_required = macro_def.macroparameters.size();
  1309. #if BOOST_WAVE_SUPPORT_CPP2A
  1310. if (boost::wave::need_cpp2a(ctx.get_language())) {
  1311. // Starting with C++20, variable arguments may be left out
  1312. // entirely, so reduce the mandatory argument count by one
  1313. // if the last parameter is ellipsis:
  1314. if ((parm_count_required > 0) &&
  1315. (T_ELLIPSIS == token_id(macro_def.macroparameters.back()))) {
  1316. --parm_count_required;
  1317. }
  1318. }
  1319. #endif
  1320. // verify the parameter count
  1321. if (count_args < parm_count_required ||
  1322. arguments.size() < parm_count_required)
  1323. {
  1324. if (count_args != arguments.size()) {
  1325. // must been at least one empty argument in C++ mode
  1326. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1327. empty_macroarguments, curr_token.get_value().c_str(),
  1328. main_pos);
  1329. }
  1330. else {
  1331. // too few macro arguments
  1332. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1333. too_few_macroarguments, curr_token.get_value().c_str(),
  1334. main_pos);
  1335. }
  1336. return false;
  1337. }
  1338. if (count_args > macro_def.macroparameters.size() ||
  1339. arguments.size() > macro_def.macroparameters.size())
  1340. {
  1341. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1342. if (!macro_def.has_ellipsis)
  1343. #endif
  1344. {
  1345. // too many macro arguments
  1346. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1347. too_many_macroarguments,
  1348. curr_token.get_value().c_str(), main_pos);
  1349. return false;
  1350. }
  1351. }
  1352. // inject tracing support
  1353. if (ctx.get_hooks().expanding_function_like_macro(ctx.derived(),
  1354. macro_def.macroname, macro_def.macroparameters,
  1355. macro_def.macrodefinition, curr_token, arguments,
  1356. seqstart, seqend))
  1357. {
  1358. // // do not expand this macro, just copy the whole sequence
  1359. // expanded.push_back(curr_token);
  1360. // std::copy(seqstart, first,
  1361. // std::inserter(expanded, expanded.end()));
  1362. // do not expand macro, just copy macro name and parenthesis
  1363. expanded.push_back(curr_token);
  1364. expanded.push_back(*seqstart);
  1365. first = ++seqstart;
  1366. return false; // no further preprocessing required
  1367. }
  1368. // expand the replacement list of this macro
  1369. expand_replacement_list(macro_def.macrodefinition.begin(),
  1370. macro_def.macrodefinition.end(),
  1371. arguments, expand_operator_defined,
  1372. expand_operator_has_include,
  1373. replacement_list);
  1374. if (!expanding_pos)
  1375. expanding_pos = curr_token.get_expand_position();
  1376. set_expand_positions(replacement_list, *expanding_pos);
  1377. }
  1378. else {
  1379. // defined as an object-like macro
  1380. if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
  1381. macro_def.macroname, macro_def.macrodefinition, curr_token))
  1382. {
  1383. // do not expand this macro, just copy the whole sequence
  1384. expanded.push_back(curr_token);
  1385. return false; // no further preprocessing required
  1386. }
  1387. bool found = false;
  1388. impl::find_concat_operator concat_tag(found);
  1389. std::remove_copy_if(macro_def.macrodefinition.begin(),
  1390. macro_def.macrodefinition.end(),
  1391. std::inserter(replacement_list, replacement_list.end()),
  1392. concat_tag);
  1393. // handle concatenation operators
  1394. if (found && !concat_tokensequence(replacement_list))
  1395. return false;
  1396. }
  1397. }
  1398. else {
  1399. // called as an object like macro
  1400. if ((*it).second->is_functionlike) {
  1401. // defined as a function-like macro
  1402. if (0 != queue_symbol) {
  1403. queue_symbol->push_back(curr_token);
  1404. expanded.splice(expanded.end(), *queue_symbol);
  1405. }
  1406. else {
  1407. expanded.push_back(curr_token);
  1408. }
  1409. ++first; // skip macro name
  1410. return false; // no further preprocessing required
  1411. }
  1412. else {
  1413. // defined as an object-like macro (expand it)
  1414. if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
  1415. macro_def.macroname, macro_def.macrodefinition, curr_token))
  1416. {
  1417. // do not expand this macro, just copy the whole sequence
  1418. expanded.push_back(curr_token);
  1419. ++first; // skip macro name
  1420. return false; // no further preprocessing required
  1421. }
  1422. bool found = false;
  1423. impl::find_concat_operator concat_tag(found);
  1424. std::remove_copy_if(macro_def.macrodefinition.begin(),
  1425. macro_def.macrodefinition.end(),
  1426. std::inserter(replacement_list, replacement_list.end()),
  1427. concat_tag);
  1428. // handle concatenation operators
  1429. if (found && !concat_tokensequence(replacement_list))
  1430. return false;
  1431. ++first; // skip macro name
  1432. }
  1433. }
  1434. // rescan the replacement list
  1435. ContainerT expanded_list;
  1436. ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
  1437. rescan_replacement_list(
  1438. curr_token, macro_def, replacement_list,
  1439. expanded_list, expand_operator_defined,
  1440. expand_operator_has_include, first, last);
  1441. ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list);
  1442. if (!expanding_pos)
  1443. // set the expanding position for rescan
  1444. expanding_pos = curr_token.get_expand_position();
  1445. // record the location where all the tokens were expanded from
  1446. set_expand_positions(expanded_list, *expanding_pos);
  1447. expanded.splice(expanded.end(), expanded_list);
  1448. return true; // rescan is required
  1449. }
  1450. ///////////////////////////////////////////////////////////////////////////////
  1451. //
  1452. // If the token under inspection points to a certain predefined macro it will
  1453. // be expanded, otherwise false is returned.
  1454. // (only __FILE__, __LINE__ and __INCLUDE_LEVEL__ macros are expanded here)
  1455. //
  1456. ///////////////////////////////////////////////////////////////////////////////
  1457. template <typename ContextT>
  1458. template <typename ContainerT>
  1459. inline bool
  1460. macromap<ContextT>::expand_predefined_macro(token_type const &curr_token,
  1461. ContainerT &expanded)
  1462. {
  1463. using namespace boost::wave;
  1464. string_type const& value = curr_token.get_value();
  1465. if ((value != "__LINE__") && (value != "__FILE__") && (value != "__INCLUDE_LEVEL__"))
  1466. return false;
  1467. // construct a fake token for the macro's definition point
  1468. token_type deftoken(T_IDENTIFIER, value, position_type("<built-in>"));
  1469. if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
  1470. deftoken, ContainerT(), curr_token))
  1471. {
  1472. // do not expand this macro, just copy the whole sequence
  1473. expanded.push_back(curr_token);
  1474. return false; // no further preprocessing required
  1475. }
  1476. token_type replacement;
  1477. if (value == "__LINE__") {
  1478. // expand the __LINE__ macro
  1479. std::string buffer = lexical_cast<std::string>(curr_token.get_expand_position().get_line());
  1480. replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
  1481. }
  1482. else if (value == "__FILE__") {
  1483. // expand the __FILE__ macro
  1484. namespace fs = boost::filesystem;
  1485. std::string file("\"");
  1486. fs::path filename(
  1487. wave::util::create_path(curr_token.get_expand_position().get_file().c_str()));
  1488. using boost::wave::util::impl::escape_lit;
  1489. file += escape_lit(wave::util::native_file_string(filename)) + "\"";
  1490. replacement = token_type(T_STRINGLIT, file.c_str(),
  1491. curr_token.get_position());
  1492. }
  1493. else if (value == "__INCLUDE_LEVEL__") {
  1494. // expand the __INCLUDE_LEVEL__ macro
  1495. char buffer[22]; // 21 bytes holds all NUL-terminated unsigned 64-bit numbers
  1496. using namespace std; // for some systems sprintf is in namespace std
  1497. sprintf(buffer, "%d", (int)ctx.get_iteration_depth());
  1498. replacement = token_type(T_INTLIT, buffer, curr_token.get_position());
  1499. }
  1500. // post-expansion hooks
  1501. ContainerT replacement_list;
  1502. replacement_list.push_back(replacement);
  1503. ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
  1504. expanded.push_back(replacement);
  1505. ctx.get_hooks().rescanned_macro(ctx.derived(), expanded);
  1506. return true;
  1507. }
  1508. ///////////////////////////////////////////////////////////////////////////////
  1509. //
  1510. // resolve_defined(): resolve the operator defined() and replace it with the
  1511. // correct T_INTLIT token
  1512. //
  1513. ///////////////////////////////////////////////////////////////////////////////
  1514. template <typename ContextT>
  1515. template <typename IteratorT, typename ContainerT>
  1516. inline typename ContextT::token_type const &
  1517. macromap<ContextT>::resolve_defined(IteratorT &first,
  1518. IteratorT const &last, ContainerT &pending)
  1519. {
  1520. using namespace boost::wave;
  1521. using namespace boost::wave::grammars;
  1522. ContainerT result;
  1523. IteratorT start = first;
  1524. boost::spirit::classic::parse_info<IteratorT> hit =
  1525. defined_grammar_gen<typename ContextT::lexer_type>::
  1526. parse_operator_defined(start, last, result);
  1527. if (!hit.hit) {
  1528. string_type msg ("defined(): ");
  1529. msg = msg + util::impl::as_string<string_type>(first, last);
  1530. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
  1531. msg.c_str(), main_pos);
  1532. // insert a dummy token
  1533. pending.push_back(token_type(T_INTLIT, "0", main_pos));
  1534. }
  1535. else {
  1536. impl::assign_iterator<IteratorT>::do_(first, hit.stop);
  1537. // insert a token, which reflects the outcome
  1538. pending.push_back(token_type(T_INTLIT,
  1539. is_defined(result.begin(), result.end()) ? "1" : "0",
  1540. main_pos));
  1541. }
  1542. on_exit::pop_front<definition_container_type> pop_front_token(pending);
  1543. return act_token = pending.front();
  1544. }
  1545. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  1546. ///////////////////////////////////////////////////////////////////////////////
  1547. //
  1548. // resolve_has_include(): resolve the operator __has_include() and replace
  1549. // it with the correct T_INTLIT token
  1550. //
  1551. ///////////////////////////////////////////////////////////////////////////////
  1552. template <typename ContextT>
  1553. template <typename IteratorT, typename ContainerT>
  1554. inline typename ContextT::token_type const &
  1555. macromap<ContextT>::resolve_has_include(IteratorT &first,
  1556. IteratorT const &last, ContainerT &pending)
  1557. {
  1558. using namespace boost::wave;
  1559. using namespace boost::wave::grammars;
  1560. ContainerT result;
  1561. bool is_quoted_filename;
  1562. bool is_system;
  1563. // to simplify the parser we check for the trailing right paren first
  1564. // scan from the beginning because unput_queue_iterator is Forward
  1565. IteratorT end_find_it = first;
  1566. ++end_find_it;
  1567. IteratorT rparen_it = first;
  1568. while (end_find_it != last) {
  1569. ++end_find_it;
  1570. ++rparen_it;
  1571. }
  1572. boost::spirit::classic::parse_info<IteratorT> hit(first);
  1573. if ((rparen_it != first) && (T_RIGHTPAREN == *rparen_it)) {
  1574. IteratorT start = first;
  1575. hit = has_include_grammar_gen<typename ContextT::lexer_type>::
  1576. parse_operator_has_include(start, rparen_it, result, is_quoted_filename, is_system);
  1577. }
  1578. if (!hit.hit) {
  1579. string_type msg ("__has_include(): ");
  1580. msg = msg + util::impl::as_string<string_type>(first, last);
  1581. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
  1582. msg.c_str(), main_pos);
  1583. // insert a dummy token
  1584. pending.push_back(token_type(T_INTLIT, "0", main_pos));
  1585. }
  1586. else {
  1587. impl::assign_iterator<IteratorT>::do_(first, last);
  1588. // insert a token, which reflects the outcome
  1589. pending.push_back(
  1590. token_type(T_INTLIT,
  1591. has_include(result.begin(), result.end(),
  1592. is_quoted_filename, is_system) ? "1" : "0",
  1593. main_pos));
  1594. }
  1595. on_exit::pop_front<definition_container_type> pop_front_token(pending);
  1596. return act_token = pending.front();
  1597. }
  1598. #endif
  1599. ///////////////////////////////////////////////////////////////////////////////
  1600. //
  1601. // resolve_operator_pragma(): resolve the operator _Pragma() and dispatch to
  1602. // the associated action
  1603. //
  1604. // This function returns true, if the pragma was correctly interpreted.
  1605. // The iterator 'first' is positioned behind the closing ')'.
  1606. // This function returns false, if the _Pragma was not known, the
  1607. // preprocessed token sequence is pushed back to the 'pending' sequence.
  1608. //
  1609. ///////////////////////////////////////////////////////////////////////////////
  1610. template <typename ContextT>
  1611. template <typename IteratorT, typename ContainerT>
  1612. inline bool
  1613. macromap<ContextT>::resolve_operator_pragma(IteratorT &first,
  1614. IteratorT const &last, ContainerT &pending, bool& seen_newline)
  1615. {
  1616. // isolate the parameter of the operator _Pragma
  1617. token_type pragma_token = *first;
  1618. if (!impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline)) {
  1619. // illformed operator _Pragma
  1620. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
  1621. "operator _Pragma()", pragma_token.get_position());
  1622. return false;
  1623. }
  1624. std::vector<ContainerT> arguments;
  1625. IteratorT endparen = first;
  1626. typename std::vector<ContainerT>::size_type count_args =
  1627. collect_arguments (pragma_token, arguments, first, endparen, last, 1,
  1628. seen_newline);
  1629. // verify the parameter count
  1630. if (pragma_token.get_position().get_file().empty())
  1631. pragma_token.set_position(act_token.get_position());
  1632. if (count_args < 1 || arguments.size() < 1) {
  1633. // too few macro arguments
  1634. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_few_macroarguments,
  1635. pragma_token.get_value().c_str(), pragma_token.get_position());
  1636. return false;
  1637. }
  1638. if (count_args > 1 || arguments.size() > 1) {
  1639. // too many macro arguments
  1640. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_many_macroarguments,
  1641. pragma_token.get_value().c_str(), pragma_token.get_position());
  1642. return false;
  1643. }
  1644. // preprocess the pragma token body
  1645. typedef typename std::vector<ContainerT>::value_type::iterator
  1646. argument_iterator_type;
  1647. ContainerT expanded;
  1648. argument_iterator_type begin_it = arguments[0].begin();
  1649. argument_iterator_type end_it = arguments[0].end();
  1650. expand_whole_tokensequence(expanded, begin_it, end_it, false, false);
  1651. // un-escape the parameter of the operator _Pragma
  1652. typedef typename token_type::string_type string_type;
  1653. string_type pragma_cmd;
  1654. typename ContainerT::const_iterator end_exp = expanded.end();
  1655. for (typename ContainerT::const_iterator it_exp = expanded.begin();
  1656. it_exp != end_exp; ++it_exp)
  1657. {
  1658. if (T_EOF == token_id(*it_exp))
  1659. break;
  1660. if (IS_CATEGORY(*it_exp, WhiteSpaceTokenType))
  1661. continue;
  1662. if (T_STRINGLIT != token_id(*it_exp)) {
  1663. // ill formed operator _Pragma
  1664. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1665. ill_formed_pragma_option, "_Pragma",
  1666. pragma_token.get_position());
  1667. return false;
  1668. }
  1669. if (pragma_cmd.size() > 0) {
  1670. // there should be exactly one string literal (string literals are to
  1671. // be concatenated at translation phase 6, but _Pragma operators are
  1672. // to be executed at translation phase 4)
  1673. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1674. ill_formed_pragma_option, "_Pragma",
  1675. pragma_token.get_position());
  1676. return false;
  1677. }
  1678. // remove the '\"' and concat all given string literal-values
  1679. string_type token_str = (*it_exp).get_value();
  1680. pragma_cmd += token_str.substr(1, token_str.size() - 2);
  1681. }
  1682. string_type pragma_cmd_unesc = impl::unescape_lit(pragma_cmd);
  1683. // tokenize the pragma body
  1684. typedef typename ContextT::lexer_type lexer_type;
  1685. ContainerT pragma;
  1686. std::string pragma_cmd_str(pragma_cmd_unesc.c_str());
  1687. lexer_type it = lexer_type(pragma_cmd_str.begin(), pragma_cmd_str.end(),
  1688. pragma_token.get_position(), ctx.get_language());
  1689. lexer_type end = lexer_type();
  1690. for (/**/; it != end; ++it)
  1691. pragma.push_back(*it);
  1692. // analyze the preprocessed token sequence and eventually dispatch to the
  1693. // associated action
  1694. if (interpret_pragma(ctx, pragma_token, pragma.begin(), pragma.end(),
  1695. pending))
  1696. {
  1697. return true; // successfully recognized a wave specific pragma
  1698. }
  1699. // unknown pragma token sequence, push it back and return to the caller
  1700. pending.push_front(token_type(T_SPACE, " ", pragma_token.get_position()));
  1701. pending.push_front(token_type(T_RIGHTPAREN, ")", pragma_token.get_position()));
  1702. pending.push_front(token_type(T_STRINGLIT, string_type("\"") + pragma_cmd + "\"",
  1703. pragma_token.get_position()));
  1704. pending.push_front(token_type(T_LEFTPAREN, "(", pragma_token.get_position()));
  1705. pending.push_front(pragma_token);
  1706. return false;
  1707. }
  1708. ///////////////////////////////////////////////////////////////////////////////
  1709. //
  1710. // Test, whether the result of a concat operator is well formed or not.
  1711. //
  1712. // This is done by re-scanning (re-tokenizing) the resulting token sequence,
  1713. // which should give back exactly one token.
  1714. //
  1715. ///////////////////////////////////////////////////////////////////////////////
  1716. template <typename ContextT>
  1717. template <typename ContainerT>
  1718. inline bool
  1719. macromap<ContextT>::is_valid_concat(string_type new_value,
  1720. position_type const &pos, ContainerT &rescanned)
  1721. {
  1722. // re-tokenize the newly generated string
  1723. typedef typename ContextT::lexer_type lexer_type;
  1724. std::string value_to_test(new_value.c_str());
  1725. boost::wave::language_support lang =
  1726. boost::wave::enable_prefer_pp_numbers(ctx.get_language());
  1727. lang = boost::wave::enable_single_line(lang);
  1728. lexer_type it = lexer_type(value_to_test.begin(), value_to_test.end(), pos,
  1729. lang);
  1730. lexer_type end = lexer_type();
  1731. for (/**/; it != end && T_EOF != token_id(*it); ++it)
  1732. {
  1733. // as of Wave V2.0.7 pasting of tokens is valid only if the resulting
  1734. // tokens are pp_tokens (as mandated by C++11)
  1735. if (!is_pp_token(*it))
  1736. return false;
  1737. rescanned.push_back(*it);
  1738. }
  1739. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1740. if (boost::wave::need_variadics(ctx.get_language()))
  1741. return true; // in variadics mode token pasting is well defined
  1742. #endif
  1743. // test if the newly generated token sequence contains more than 1 token
  1744. return 1 == rescanned.size();
  1745. }
  1746. ///////////////////////////////////////////////////////////////////////////////
  1747. //
  1748. // Bulk update expand positions
  1749. //
  1750. ///////////////////////////////////////////////////////////////////////////////
  1751. // batch update tokens with a single expand position
  1752. template <typename ContextT>
  1753. template <typename ContainerT>
  1754. void macromap<ContextT>::set_expand_positions(ContainerT &tokens, position_type pos)
  1755. {
  1756. typename ContainerT::iterator ex_end = tokens.end();
  1757. for (typename ContainerT::iterator it = tokens.begin();
  1758. it != ex_end; ++it) {
  1759. // expand positions are only used for __LINE__, __FILE__, and macro names
  1760. if (token_id(*it) == T_IDENTIFIER)
  1761. it->set_expand_position(pos);
  1762. }
  1763. }
  1764. ///////////////////////////////////////////////////////////////////////////////
  1765. //
  1766. // Handle all occurrences of the concatenation operator '##' inside the given
  1767. // token sequence.
  1768. //
  1769. ///////////////////////////////////////////////////////////////////////////////
  1770. template <typename Context>
  1771. inline void report_invalid_concatenation(Context& ctx,
  1772. typename Context::token_type const& prev,
  1773. typename Context::token_type const& next,
  1774. typename Context::position_type const& main_pos)
  1775. {
  1776. typename Context::string_type error_string("\"");
  1777. error_string += prev.get_value();
  1778. error_string += "\" and \"";
  1779. error_string += next.get_value();
  1780. error_string += "\"";
  1781. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_concat,
  1782. error_string.c_str(), main_pos);
  1783. }
  1784. template <typename ContextT>
  1785. template <typename ContainerT>
  1786. inline bool
  1787. macromap<ContextT>::concat_tokensequence(ContainerT &expanded)
  1788. {
  1789. using namespace boost::wave;
  1790. typedef typename ContainerT::iterator iterator_type;
  1791. iterator_type end = expanded.end();
  1792. iterator_type prev = end;
  1793. for (iterator_type it = expanded.begin(); it != end; /**/)
  1794. {
  1795. if (T_POUND_POUND == BASE_TOKEN(token_id(*it))) {
  1796. iterator_type next = it;
  1797. ++next;
  1798. if (prev == end || next == end) {
  1799. // error, '##' should be in between two tokens
  1800. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1801. ill_formed_operator, "concat ('##')", main_pos);
  1802. return false;
  1803. }
  1804. // replace prev##next with the concatenated value, skip whitespace
  1805. // before and after the '##' operator
  1806. while (IS_CATEGORY(*next, WhiteSpaceTokenType)) {
  1807. ++next;
  1808. if (next == end) {
  1809. // error, '##' should be in between two tokens
  1810. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1811. ill_formed_operator, "concat ('##')", main_pos);
  1812. return false;
  1813. }
  1814. }
  1815. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1816. if (boost::wave::need_variadics(ctx.get_language())) {
  1817. if (T_PLACEMARKER == token_id(*next)) {
  1818. // remove the '##' and the next tokens from the sequence
  1819. iterator_type first_to_delete = prev;
  1820. expanded.erase(++first_to_delete, ++next);
  1821. it = next;
  1822. continue;
  1823. }
  1824. else if (T_PLACEMARKER == token_id(*prev)) {
  1825. // remove the '##' and the next tokens from the sequence
  1826. iterator_type first_to_delete = prev;
  1827. *prev = *next;
  1828. expanded.erase(++first_to_delete, ++next);
  1829. it = next;
  1830. continue;
  1831. }
  1832. }
  1833. #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1834. // test if the concat operator has to concatenate two unrelated
  1835. // tokens i.e. the result yields more then one token
  1836. string_type concat_result;
  1837. ContainerT rescanned;
  1838. concat_result = ((*prev).get_value() + (*next).get_value());
  1839. // analyze the validity of the concatenation result
  1840. if (!is_valid_concat(concat_result, (*prev).get_position(),
  1841. rescanned) &&
  1842. !IS_CATEGORY(*prev, WhiteSpaceTokenType) &&
  1843. !IS_CATEGORY(*next, WhiteSpaceTokenType))
  1844. {
  1845. report_invalid_concatenation(ctx, *prev, *next, main_pos);
  1846. return false;
  1847. }
  1848. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1849. if (boost::wave::need_variadics(ctx.get_language())) {
  1850. // remove the prev, '##' and the next tokens from the sequence
  1851. expanded.erase(prev, ++next); // remove not needed tokens
  1852. // some stl implementations clear() the container if we erased all
  1853. // the elements, which orphans all iterators. we re-initialize these
  1854. // here
  1855. if (expanded.empty())
  1856. end = next = expanded.end();
  1857. // replace the old token (pointed to by *prev) with the re-tokenized
  1858. // sequence
  1859. expanded.splice(next, rescanned);
  1860. // the last token of the inserted sequence is the new previous
  1861. prev = next;
  1862. if (next != expanded.end())
  1863. --prev;
  1864. }
  1865. else
  1866. #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1867. {
  1868. // we leave the token_id unchanged, but unmark the token as
  1869. // disabled, if appropriate
  1870. (*prev).set_value(concat_result);
  1871. if (T_NONREPLACABLE_IDENTIFIER == token_id(*prev))
  1872. (*prev).set_token_id(T_IDENTIFIER);
  1873. // remove the '##' and the next tokens from the sequence
  1874. iterator_type first_to_delete = prev;
  1875. expanded.erase(++first_to_delete, ++next);
  1876. }
  1877. it = next;
  1878. continue;
  1879. }
  1880. // save last non-whitespace token position
  1881. if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
  1882. prev = it;
  1883. ++it; // next token, please
  1884. }
  1885. return true;
  1886. }
  1887. ///////////////////////////////////////////////////////////////////////////////
  1888. //
  1889. // predefine_macro(): predefine a single macro
  1890. //
  1891. ///////////////////////////////////////////////////////////////////////////////
  1892. template <typename ContextT>
  1893. inline void
  1894. macromap<ContextT>::predefine_macro(defined_macros_type *scope,
  1895. string_type const &name, token_type const &t)
  1896. {
  1897. definition_container_type macrodefinition;
  1898. std::vector<token_type> param;
  1899. macrodefinition.push_back(t);
  1900. add_macro(token_type(T_IDENTIFIER, name, t.get_position()),
  1901. false, param, macrodefinition, true, scope);
  1902. }
  1903. ///////////////////////////////////////////////////////////////////////////////
  1904. //
  1905. // init_predefined_macros(): init the predefined macros
  1906. //
  1907. ///////////////////////////////////////////////////////////////////////////////
  1908. template <typename ContextT>
  1909. inline void
  1910. macromap<ContextT>::init_predefined_macros(char const *fname,
  1911. defined_macros_type *scope, bool at_global_scope)
  1912. {
  1913. // if no scope is given, use the current one
  1914. defined_macros_type* current_scope = scope ? scope : current_macros;
  1915. // first, add the static macros
  1916. position_type pos("<built-in>");
  1917. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1918. if (boost::wave::need_c99(ctx.get_language())) {
  1919. // define C99 specifics
  1920. for (int i = 0; 0 != predef.static_data_c99(i).name; ++i) {
  1921. predefined_macros::static_macros const& m = predef.static_data_c99(i);
  1922. predefine_macro(current_scope, m.name,
  1923. token_type(m.token_id, m.value, pos));
  1924. }
  1925. }
  1926. else
  1927. #endif
  1928. {
  1929. #if BOOST_WAVE_SUPPORT_CPP0X != 0
  1930. if (boost::wave::need_cpp0x(ctx.get_language())) {
  1931. // define C++11 specifics
  1932. for (int i = 0; 0 != predef.static_data_cpp0x(i).name; ++i) {
  1933. predefined_macros::static_macros const& m = predef.static_data_cpp0x(i);
  1934. predefine_macro(current_scope, m.name,
  1935. token_type(m.token_id, m.value, pos));
  1936. }
  1937. }
  1938. else
  1939. #endif
  1940. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1941. if (boost::wave::need_cpp2a(ctx.get_language())) {
  1942. // define C++20 specifics
  1943. for (int i = 0; 0 != predef.static_data_cpp2a(i).name; ++i) {
  1944. predefined_macros::static_macros const& m = predef.static_data_cpp2a(i);
  1945. predefine_macro(current_scope, m.name,
  1946. token_type(m.token_id, m.value, pos));
  1947. }
  1948. }
  1949. else
  1950. #endif
  1951. {
  1952. // define C++ specifics
  1953. for (int i = 0; 0 != predef.static_data_cpp(i).name; ++i) {
  1954. predefined_macros::static_macros const& m = predef.static_data_cpp(i);
  1955. predefine_macro(current_scope, m.name,
  1956. token_type(m.token_id, m.value, pos));
  1957. }
  1958. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1959. // define __WAVE_HAS_VARIADICS__, if appropriate
  1960. if (boost::wave::need_variadics(ctx.get_language())) {
  1961. predefine_macro(current_scope, "__WAVE_HAS_VARIADICS__",
  1962. token_type(T_INTLIT, "1", pos));
  1963. }
  1964. #endif
  1965. }
  1966. }
  1967. // predefine the __BASE_FILE__ macro which contains the main file name
  1968. namespace fs = boost::filesystem;
  1969. if (string_type(fname) != "<Unknown>") {
  1970. fs::path filename(create_path(fname));
  1971. using boost::wave::util::impl::escape_lit;
  1972. predefine_macro(current_scope, "__BASE_FILE__",
  1973. token_type(T_STRINGLIT, string_type("\"") +
  1974. escape_lit(native_file_string(filename)).c_str() + "\"", pos));
  1975. base_name = fname;
  1976. }
  1977. else if (!base_name.empty()) {
  1978. fs::path filename(create_path(base_name.c_str()));
  1979. using boost::wave::util::impl::escape_lit;
  1980. predefine_macro(current_scope, "__BASE_FILE__",
  1981. token_type(T_STRINGLIT, string_type("\"") +
  1982. escape_lit(native_file_string(filename)).c_str() + "\"", pos));
  1983. }
  1984. // now add the dynamic macros
  1985. for (int j = 0; 0 != predef.dynamic_data(j).name; ++j) {
  1986. predefined_macros::dynamic_macros const& m = predef.dynamic_data(j);
  1987. predefine_macro(current_scope, m.name,
  1988. token_type(m.token_id, (predef.* m.generator)(), pos));
  1989. }
  1990. }
  1991. ///////////////////////////////////////////////////////////////////////////////
  1992. //
  1993. // reset_macromap(): initialize the internal macro symbol namespace
  1994. //
  1995. ///////////////////////////////////////////////////////////////////////////////
  1996. template <typename ContextT>
  1997. inline void
  1998. macromap<ContextT>::reset_macromap()
  1999. {
  2000. current_macros->clear();
  2001. predef.reset();
  2002. act_token = token_type();
  2003. }
  2004. ///////////////////////////////////////////////////////////////////////////////
  2005. }}} // namespace boost::wave::util
  2006. #if BOOST_WAVE_SERIALIZATION != 0
  2007. namespace boost { namespace serialization {
  2008. template<typename ContextT>
  2009. struct version<boost::wave::util::macromap<ContextT> >
  2010. {
  2011. typedef boost::wave::util::macromap<ContextT> target_type;
  2012. typedef mpl::int_<target_type::version> type;
  2013. typedef mpl::integral_c_tag tag;
  2014. BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
  2015. };
  2016. }} // namespace boost::serialization
  2017. #endif
  2018. // the suffix header occurs after all of the code
  2019. #ifdef BOOST_HAS_ABI_HEADERS
  2020. #include BOOST_ABI_SUFFIX
  2021. #endif
  2022. #endif // !defined(BOOST_CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)