cpp_macromap.hpp 88 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309
  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 <ctime>
  13. #include <list>
  14. #include <map>
  15. #include <set>
  16. #include <vector>
  17. #include <iterator>
  18. #include <algorithm>
  19. #include <string>
  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. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1114. if (i >= arguments.size()) {
  1115. // no argument supplied; do nothing (only c20 should reach here)
  1116. BOOST_ASSERT(boost::wave::need_cpp2a(ctx.get_language()));
  1117. position_type last_valid(arguments.back().back().get_position());
  1118. // insert a empty string
  1119. expanded.push_back(token_type(T_STRINGLIT, "\"\"", last_valid));
  1120. }
  1121. else
  1122. #endif
  1123. {
  1124. // shouldn't be oob (w.o. cpp20)
  1125. BOOST_ASSERT(i < arguments.size() && !arguments[i].empty());
  1126. // safe a copy of the first tokens position (not a reference!)
  1127. position_type pos((*arguments[i].begin()).get_position());
  1128. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1129. if (is_ellipsis && boost::wave::need_variadics(ctx.get_language())) {
  1130. impl::trim_sequence_left(arguments[i]);
  1131. impl::trim_sequence_right(arguments.back());
  1132. expanded.push_back(token_type(T_STRINGLIT,
  1133. impl::as_stringlit(arguments, i, pos), pos));
  1134. }
  1135. else
  1136. #endif
  1137. {
  1138. impl::trim_sequence(arguments[i]);
  1139. expanded.push_back(token_type(T_STRINGLIT,
  1140. impl::as_stringlit(arguments[i], pos), pos));
  1141. }
  1142. }
  1143. adjacent_stringize = false;
  1144. }
  1145. else {
  1146. // simply copy the original argument (adjacent '##' or '#')
  1147. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1148. if (is_ellipsis) {
  1149. position_type const& pos = (*cit).get_position();
  1150. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1151. if (i < arguments.size())
  1152. #endif
  1153. {
  1154. impl::trim_sequence_left(arguments[i]);
  1155. impl::trim_sequence_right(arguments.back());
  1156. BOOST_ASSERT(boost::wave::need_variadics(ctx.get_language()));
  1157. impl::replace_ellipsis(arguments, i, expanded, pos);
  1158. }
  1159. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1160. else if (boost::wave::need_cpp2a(ctx.get_language())) {
  1161. BOOST_ASSERT(i == arguments.size());
  1162. // no argument supplied; insert placemarker
  1163. expanded.push_back(
  1164. typename ContainerT::value_type(T_PLACEMARKER, "\xA7", pos));
  1165. }
  1166. #endif
  1167. }
  1168. else
  1169. #endif
  1170. {
  1171. ContainerT& arg = arguments[i];
  1172. impl::trim_sequence(arg);
  1173. std::copy(arg.begin(), arg.end(),
  1174. std::inserter(expanded, expanded.end()));
  1175. }
  1176. }
  1177. }
  1178. else if (!adjacent_stringize || T_POUND != base_id) {
  1179. // insert the actual replacement token (if it is not the '#' operator)
  1180. expanded.push_back(*cit);
  1181. }
  1182. }
  1183. if (adjacent_stringize) {
  1184. // error, '#' should not be the last token
  1185. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_operator,
  1186. "stringize ('#')", main_pos);
  1187. return;
  1188. }
  1189. // handle the cpp.concat operator
  1190. if (seen_concat)
  1191. concat_tokensequence(expanded);
  1192. }
  1193. ///////////////////////////////////////////////////////////////////////////////
  1194. //
  1195. // rescan_replacement_list
  1196. //
  1197. // As the name implies, this function is used to rescan the replacement list
  1198. // after the first macro substitution phase.
  1199. //
  1200. ///////////////////////////////////////////////////////////////////////////////
  1201. template <typename ContextT>
  1202. template <typename IteratorT, typename ContainerT>
  1203. inline void
  1204. macromap<ContextT>::rescan_replacement_list(token_type const &curr_token,
  1205. macro_definition_type &macro_def, ContainerT &replacement_list,
  1206. ContainerT &expanded,
  1207. bool expand_operator_defined,
  1208. bool expand_operator_has_include,
  1209. IteratorT &nfirst, IteratorT const &nlast)
  1210. {
  1211. if (!replacement_list.empty()) {
  1212. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1213. // remove the placemarkers
  1214. if (boost::wave::need_variadics(ctx.get_language())) {
  1215. typename ContainerT::iterator end = replacement_list.end();
  1216. typename ContainerT::iterator it = replacement_list.begin();
  1217. while (it != end) {
  1218. using namespace boost::wave;
  1219. if (T_PLACEMARKER == token_id(*it)) {
  1220. typename ContainerT::iterator placemarker = it;
  1221. ++it;
  1222. replacement_list.erase(placemarker);
  1223. }
  1224. else {
  1225. ++it;
  1226. }
  1227. }
  1228. }
  1229. #endif
  1230. // rescan the replacement list, during this rescan the current macro under
  1231. // expansion isn't available as an expandable macro
  1232. on_exit::reset<bool> on_exit(macro_def.is_available_for_replacement, false);
  1233. typename ContainerT::iterator begin_it = replacement_list.begin();
  1234. typename ContainerT::iterator end_it = replacement_list.end();
  1235. expand_whole_tokensequence(
  1236. expanded, begin_it, end_it,
  1237. expand_operator_defined, expand_operator_has_include);
  1238. // trim replacement list, leave placeholder tokens untouched
  1239. impl::trim_replacement_list(expanded);
  1240. }
  1241. if (expanded.empty()) {
  1242. // the resulting replacement list should contain at least a placeholder
  1243. // token
  1244. expanded.push_back(token_type(T_PLACEHOLDER, "_", curr_token.get_position()));
  1245. }
  1246. }
  1247. ///////////////////////////////////////////////////////////////////////////////
  1248. //
  1249. // expand_macro(): expands a defined macro
  1250. //
  1251. // This functions tries to expand the macro, to which points the 'first'
  1252. // iterator. The functions eats up more tokens, if the macro to expand is
  1253. // a function-like macro.
  1254. //
  1255. ///////////////////////////////////////////////////////////////////////////////
  1256. template <typename ContextT>
  1257. template <typename IteratorT, typename ContainerT>
  1258. inline bool
  1259. macromap<ContextT>::expand_macro(ContainerT &expanded,
  1260. token_type const &curr_token, typename defined_macros_type::iterator it,
  1261. IteratorT &first, IteratorT const &last,
  1262. bool& seen_newline, bool expand_operator_defined,
  1263. bool expand_operator_has_include,
  1264. boost::optional<position_type> expanding_pos,
  1265. defined_macros_type *scope, ContainerT *queue_symbol)
  1266. {
  1267. using namespace boost::wave;
  1268. if (0 == scope) scope = current_macros;
  1269. BOOST_ASSERT(T_IDENTIFIER == token_id(curr_token) ||
  1270. IS_CATEGORY(token_id(curr_token), KeywordTokenType) ||
  1271. IS_EXTCATEGORY(token_id(curr_token), OperatorTokenType|AltExtTokenType) ||
  1272. IS_CATEGORY(token_id(curr_token), BoolLiteralTokenType));
  1273. if (it == scope->end()) {
  1274. ++first; // advance
  1275. // try to expand a predefined macro (__FILE__, __LINE__ or __INCLUDE_LEVEL__)
  1276. if (expand_predefined_macro(curr_token, expanded))
  1277. return false;
  1278. // not defined as a macro
  1279. if (0 != queue_symbol) {
  1280. expanded.splice(expanded.end(), *queue_symbol);
  1281. }
  1282. else {
  1283. expanded.push_back(curr_token);
  1284. }
  1285. return false;
  1286. }
  1287. // ensure the parameters to be replaced with special parameter tokens
  1288. macro_definition_type& macro_def = *(*it).second.get();
  1289. macro_def.replace_parameters(ctx);
  1290. // test if this macro is currently available for replacement
  1291. if (!macro_def.is_available_for_replacement) {
  1292. // this macro is marked as non-replaceable
  1293. // copy the macro name itself
  1294. if (0 != queue_symbol) {
  1295. queue_symbol->push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
  1296. curr_token.get_value(), curr_token.get_position()));
  1297. expanded.splice(expanded.end(), *queue_symbol);
  1298. }
  1299. else {
  1300. expanded.push_back(token_type(T_NONREPLACABLE_IDENTIFIER,
  1301. curr_token.get_value(), curr_token.get_position()));
  1302. }
  1303. ++first;
  1304. return false;
  1305. }
  1306. // try to replace the current identifier as a function-like macro
  1307. ContainerT replacement_list;
  1308. if (T_LEFTPAREN == impl::next_token<IteratorT>::peek(first, last)) {
  1309. // called as a function-like macro
  1310. impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline);
  1311. IteratorT seqstart = first;
  1312. IteratorT seqend = first;
  1313. if (macro_def.is_functionlike) {
  1314. // defined as a function-like macro
  1315. // collect the arguments
  1316. std::vector<ContainerT> arguments;
  1317. typename std::vector<ContainerT>::size_type count_args =
  1318. collect_arguments(curr_token, arguments, first, seqend, last,
  1319. macro_def.macroparameters.size(), seen_newline);
  1320. std::size_t parm_count_required = macro_def.macroparameters.size();
  1321. #if BOOST_WAVE_SUPPORT_CPP2A
  1322. if (boost::wave::need_cpp2a(ctx.get_language())) {
  1323. // Starting with C++20, variable arguments may be left out
  1324. // entirely, so reduce the mandatory argument count by one
  1325. // if the last parameter is ellipsis:
  1326. if ((parm_count_required > 0) &&
  1327. (T_ELLIPSIS == token_id(macro_def.macroparameters.back()))) {
  1328. --parm_count_required;
  1329. }
  1330. }
  1331. #endif
  1332. // verify the parameter count
  1333. if (count_args < parm_count_required ||
  1334. arguments.size() < parm_count_required)
  1335. {
  1336. if (count_args != arguments.size()) {
  1337. // must been at least one empty argument in C++ mode
  1338. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1339. empty_macroarguments, curr_token.get_value().c_str(),
  1340. main_pos);
  1341. }
  1342. else {
  1343. // too few macro arguments
  1344. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1345. too_few_macroarguments, curr_token.get_value().c_str(),
  1346. main_pos);
  1347. }
  1348. return false;
  1349. }
  1350. if (count_args > macro_def.macroparameters.size() ||
  1351. arguments.size() > macro_def.macroparameters.size())
  1352. {
  1353. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1354. if (!macro_def.has_ellipsis)
  1355. #endif
  1356. {
  1357. // too many macro arguments
  1358. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1359. too_many_macroarguments,
  1360. curr_token.get_value().c_str(), main_pos);
  1361. return false;
  1362. }
  1363. }
  1364. // inject tracing support
  1365. if (ctx.get_hooks().expanding_function_like_macro(ctx.derived(),
  1366. macro_def.macroname, macro_def.macroparameters,
  1367. macro_def.macrodefinition, curr_token, arguments,
  1368. seqstart, seqend))
  1369. {
  1370. // // do not expand this macro, just copy the whole sequence
  1371. // expanded.push_back(curr_token);
  1372. // std::copy(seqstart, first,
  1373. // std::inserter(expanded, expanded.end()));
  1374. // do not expand macro, just copy macro name and parenthesis
  1375. expanded.push_back(curr_token);
  1376. expanded.push_back(*seqstart);
  1377. first = ++seqstart;
  1378. return false; // no further preprocessing required
  1379. }
  1380. // expand the replacement list of this macro
  1381. expand_replacement_list(macro_def.macrodefinition.begin(),
  1382. macro_def.macrodefinition.end(),
  1383. arguments, expand_operator_defined,
  1384. expand_operator_has_include,
  1385. replacement_list);
  1386. if (!expanding_pos)
  1387. expanding_pos = curr_token.get_expand_position();
  1388. set_expand_positions(replacement_list, *expanding_pos);
  1389. }
  1390. else {
  1391. // defined as an object-like macro
  1392. if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
  1393. macro_def.macroname, macro_def.macrodefinition, curr_token))
  1394. {
  1395. // do not expand this macro, just copy the whole sequence
  1396. expanded.push_back(curr_token);
  1397. return false; // no further preprocessing required
  1398. }
  1399. bool found = false;
  1400. impl::find_concat_operator concat_tag(found);
  1401. std::remove_copy_if(macro_def.macrodefinition.begin(),
  1402. macro_def.macrodefinition.end(),
  1403. std::inserter(replacement_list, replacement_list.end()),
  1404. concat_tag);
  1405. // handle concatenation operators
  1406. if (found && !concat_tokensequence(replacement_list))
  1407. return false;
  1408. }
  1409. }
  1410. else {
  1411. // called as an object like macro
  1412. if ((*it).second->is_functionlike) {
  1413. // defined as a function-like macro
  1414. if (0 != queue_symbol) {
  1415. queue_symbol->push_back(curr_token);
  1416. expanded.splice(expanded.end(), *queue_symbol);
  1417. }
  1418. else {
  1419. expanded.push_back(curr_token);
  1420. }
  1421. ++first; // skip macro name
  1422. return false; // no further preprocessing required
  1423. }
  1424. else {
  1425. // defined as an object-like macro (expand it)
  1426. if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
  1427. macro_def.macroname, macro_def.macrodefinition, curr_token))
  1428. {
  1429. // do not expand this macro, just copy the whole sequence
  1430. expanded.push_back(curr_token);
  1431. ++first; // skip macro name
  1432. return false; // no further preprocessing required
  1433. }
  1434. bool found = false;
  1435. impl::find_concat_operator concat_tag(found);
  1436. std::remove_copy_if(macro_def.macrodefinition.begin(),
  1437. macro_def.macrodefinition.end(),
  1438. std::inserter(replacement_list, replacement_list.end()),
  1439. concat_tag);
  1440. // handle concatenation operators
  1441. if (found && !concat_tokensequence(replacement_list))
  1442. return false;
  1443. ++first; // skip macro name
  1444. }
  1445. }
  1446. // rescan the replacement list
  1447. ContainerT expanded_list;
  1448. ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
  1449. rescan_replacement_list(
  1450. curr_token, macro_def, replacement_list,
  1451. expanded_list, expand_operator_defined,
  1452. expand_operator_has_include, first, last);
  1453. ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list);
  1454. if (!expanding_pos)
  1455. // set the expanding position for rescan
  1456. expanding_pos = curr_token.get_expand_position();
  1457. // record the location where all the tokens were expanded from
  1458. set_expand_positions(expanded_list, *expanding_pos);
  1459. expanded.splice(expanded.end(), expanded_list);
  1460. return true; // rescan is required
  1461. }
  1462. ///////////////////////////////////////////////////////////////////////////////
  1463. //
  1464. // If the token under inspection points to a certain predefined macro it will
  1465. // be expanded, otherwise false is returned.
  1466. // (only __FILE__, __LINE__ and __INCLUDE_LEVEL__ macros are expanded here)
  1467. //
  1468. ///////////////////////////////////////////////////////////////////////////////
  1469. template <typename ContextT>
  1470. template <typename ContainerT>
  1471. inline bool
  1472. macromap<ContextT>::expand_predefined_macro(token_type const &curr_token,
  1473. ContainerT &expanded)
  1474. {
  1475. using namespace boost::wave;
  1476. string_type const& value = curr_token.get_value();
  1477. if ((value != "__LINE__") && (value != "__FILE__") && (value != "__INCLUDE_LEVEL__"))
  1478. return false;
  1479. // construct a fake token for the macro's definition point
  1480. token_type deftoken(T_IDENTIFIER, value, position_type("<built-in>"));
  1481. if (ctx.get_hooks().expanding_object_like_macro(ctx.derived(),
  1482. deftoken, ContainerT(), curr_token))
  1483. {
  1484. // do not expand this macro, just copy the whole sequence
  1485. expanded.push_back(curr_token);
  1486. return false; // no further preprocessing required
  1487. }
  1488. token_type replacement;
  1489. if (value == "__LINE__") {
  1490. // expand the __LINE__ macro
  1491. std::string buffer = lexical_cast<std::string>(curr_token.get_expand_position().get_line());
  1492. replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
  1493. }
  1494. else if (value == "__FILE__") {
  1495. // expand the __FILE__ macro
  1496. namespace fs = boost::filesystem;
  1497. std::string file("\"");
  1498. fs::path filename(
  1499. wave::util::create_path(curr_token.get_expand_position().get_file().c_str()));
  1500. using boost::wave::util::impl::escape_lit;
  1501. file += escape_lit(wave::util::native_file_string(filename)) + "\"";
  1502. replacement = token_type(T_STRINGLIT, file.c_str(),
  1503. curr_token.get_position());
  1504. }
  1505. else if (value == "__INCLUDE_LEVEL__") {
  1506. // expand the __INCLUDE_LEVEL__ macro
  1507. std::string buffer = std::to_string(ctx.get_iteration_depth());
  1508. replacement = token_type(T_INTLIT, buffer.c_str(), curr_token.get_position());
  1509. }
  1510. // post-expansion hooks
  1511. ContainerT replacement_list;
  1512. replacement_list.push_back(replacement);
  1513. ctx.get_hooks().expanded_macro(ctx.derived(), replacement_list);
  1514. expanded.push_back(replacement);
  1515. ctx.get_hooks().rescanned_macro(ctx.derived(), expanded);
  1516. return true;
  1517. }
  1518. ///////////////////////////////////////////////////////////////////////////////
  1519. //
  1520. // resolve_defined(): resolve the operator defined() and replace it with the
  1521. // correct T_INTLIT token
  1522. //
  1523. ///////////////////////////////////////////////////////////////////////////////
  1524. template <typename ContextT>
  1525. template <typename IteratorT, typename ContainerT>
  1526. inline typename ContextT::token_type const &
  1527. macromap<ContextT>::resolve_defined(IteratorT &first,
  1528. IteratorT const &last, ContainerT &pending)
  1529. {
  1530. using namespace boost::wave;
  1531. using namespace boost::wave::grammars;
  1532. ContainerT result;
  1533. IteratorT start = first;
  1534. boost::spirit::classic::parse_info<IteratorT> hit =
  1535. defined_grammar_gen<typename ContextT::lexer_type>::
  1536. parse_operator_defined(start, last, result);
  1537. if (!hit.hit) {
  1538. string_type msg ("defined(): ");
  1539. msg = msg + util::impl::as_string<string_type>(first, last);
  1540. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
  1541. msg.c_str(), main_pos);
  1542. // insert a dummy token
  1543. pending.push_back(token_type(T_INTLIT, "0", main_pos));
  1544. }
  1545. else {
  1546. impl::assign_iterator<IteratorT>::do_(first, hit.stop);
  1547. // insert a token, which reflects the outcome
  1548. pending.push_back(token_type(T_INTLIT,
  1549. is_defined(result.begin(), result.end()) ? "1" : "0",
  1550. main_pos));
  1551. }
  1552. on_exit::pop_front<definition_container_type> pop_front_token(pending);
  1553. return act_token = pending.front();
  1554. }
  1555. #if BOOST_WAVE_SUPPORT_HAS_INCLUDE != 0
  1556. ///////////////////////////////////////////////////////////////////////////////
  1557. //
  1558. // resolve_has_include(): resolve the operator __has_include() and replace
  1559. // it with the correct T_INTLIT token
  1560. //
  1561. ///////////////////////////////////////////////////////////////////////////////
  1562. template <typename ContextT>
  1563. template <typename IteratorT, typename ContainerT>
  1564. inline typename ContextT::token_type const &
  1565. macromap<ContextT>::resolve_has_include(IteratorT &first,
  1566. IteratorT const &last, ContainerT &pending)
  1567. {
  1568. using namespace boost::wave;
  1569. using namespace boost::wave::grammars;
  1570. ContainerT result;
  1571. bool is_quoted_filename;
  1572. bool is_system;
  1573. IteratorT start = first;
  1574. boost::spirit::classic::parse_info<IteratorT> hit =
  1575. has_include_grammar_gen<typename ContextT::lexer_type>::
  1576. parse_operator_has_include(start, last, result, is_quoted_filename, is_system);
  1577. if (!hit.hit) {
  1578. string_type msg ("__has_include(): ");
  1579. msg = msg + util::impl::as_string<string_type>(first, last);
  1580. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
  1581. msg.c_str(), main_pos);
  1582. // insert a dummy token
  1583. pending.push_back(token_type(T_INTLIT, "0", main_pos));
  1584. }
  1585. else {
  1586. impl::assign_iterator<IteratorT>::do_(first, hit.stop);
  1587. // insert a token, which reflects the outcome
  1588. pending.push_back(
  1589. token_type(T_INTLIT,
  1590. has_include(result.begin(), result.end(),
  1591. is_quoted_filename, is_system) ? "1" : "0",
  1592. main_pos));
  1593. }
  1594. on_exit::pop_front<definition_container_type> pop_front_token(pending);
  1595. return act_token = pending.front();
  1596. }
  1597. #endif
  1598. ///////////////////////////////////////////////////////////////////////////////
  1599. //
  1600. // resolve_operator_pragma(): resolve the operator _Pragma() and dispatch to
  1601. // the associated action
  1602. //
  1603. // This function returns true, if the pragma was correctly interpreted.
  1604. // The iterator 'first' is positioned behind the closing ')'.
  1605. // This function returns false, if the _Pragma was not known, the
  1606. // preprocessed token sequence is pushed back to the 'pending' sequence.
  1607. //
  1608. ///////////////////////////////////////////////////////////////////////////////
  1609. template <typename ContextT>
  1610. template <typename IteratorT, typename ContainerT>
  1611. inline bool
  1612. macromap<ContextT>::resolve_operator_pragma(IteratorT &first,
  1613. IteratorT const &last, ContainerT &pending, bool& seen_newline)
  1614. {
  1615. // isolate the parameter of the operator _Pragma
  1616. token_type pragma_token = *first;
  1617. if (!impl::skip_to_token(ctx, first, last, T_LEFTPAREN, seen_newline)) {
  1618. // illformed operator _Pragma
  1619. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, ill_formed_expression,
  1620. "operator _Pragma()", pragma_token.get_position());
  1621. return false;
  1622. }
  1623. std::vector<ContainerT> arguments;
  1624. IteratorT endparen = first;
  1625. typename std::vector<ContainerT>::size_type count_args =
  1626. collect_arguments (pragma_token, arguments, first, endparen, last, 1,
  1627. seen_newline);
  1628. // verify the parameter count
  1629. if (pragma_token.get_position().get_file().empty())
  1630. pragma_token.set_position(act_token.get_position());
  1631. if (count_args < 1 || arguments.size() < 1) {
  1632. // too few macro arguments
  1633. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_few_macroarguments,
  1634. pragma_token.get_value().c_str(), pragma_token.get_position());
  1635. return false;
  1636. }
  1637. if (count_args > 1 || arguments.size() > 1) {
  1638. // too many macro arguments
  1639. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, too_many_macroarguments,
  1640. pragma_token.get_value().c_str(), pragma_token.get_position());
  1641. return false;
  1642. }
  1643. // preprocess the pragma token body
  1644. typedef typename std::vector<ContainerT>::value_type::iterator
  1645. argument_iterator_type;
  1646. ContainerT expanded;
  1647. argument_iterator_type begin_it = arguments[0].begin();
  1648. argument_iterator_type end_it = arguments[0].end();
  1649. expand_whole_tokensequence(expanded, begin_it, end_it, false, false);
  1650. // un-escape the parameter of the operator _Pragma
  1651. typedef typename token_type::string_type string_type;
  1652. string_type pragma_cmd;
  1653. typename ContainerT::const_iterator end_exp = expanded.end();
  1654. for (typename ContainerT::const_iterator it_exp = expanded.begin();
  1655. it_exp != end_exp; ++it_exp)
  1656. {
  1657. if (T_EOF == token_id(*it_exp))
  1658. break;
  1659. if (IS_CATEGORY(*it_exp, WhiteSpaceTokenType))
  1660. continue;
  1661. if (T_STRINGLIT != token_id(*it_exp)) {
  1662. // ill formed operator _Pragma
  1663. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1664. ill_formed_pragma_option, "_Pragma",
  1665. pragma_token.get_position());
  1666. return false;
  1667. }
  1668. if (pragma_cmd.size() > 0) {
  1669. // there should be exactly one string literal (string literals are to
  1670. // be concatenated at translation phase 6, but _Pragma operators are
  1671. // to be executed at translation phase 4)
  1672. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1673. ill_formed_pragma_option, "_Pragma",
  1674. pragma_token.get_position());
  1675. return false;
  1676. }
  1677. // remove the '\"' and concat all given string literal-values
  1678. string_type token_str = (*it_exp).get_value();
  1679. pragma_cmd += token_str.substr(1, token_str.size() - 2);
  1680. }
  1681. string_type pragma_cmd_unesc = impl::unescape_lit(pragma_cmd);
  1682. // tokenize the pragma body
  1683. typedef typename ContextT::lexer_type lexer_type;
  1684. ContainerT pragma;
  1685. std::string pragma_cmd_str(pragma_cmd_unesc.c_str());
  1686. lexer_type it = lexer_type(pragma_cmd_str.begin(), pragma_cmd_str.end(),
  1687. pragma_token.get_position(), ctx.get_language());
  1688. lexer_type end = lexer_type();
  1689. for (/**/; it != end; ++it)
  1690. pragma.push_back(*it);
  1691. // analyze the preprocessed token sequence and eventually dispatch to the
  1692. // associated action
  1693. if (interpret_pragma(ctx, pragma_token, pragma.begin(), pragma.end(),
  1694. pending))
  1695. {
  1696. return true; // successfully recognized a wave specific pragma
  1697. }
  1698. // unknown pragma token sequence, push it back and return to the caller
  1699. pending.push_front(token_type(T_SPACE, " ", pragma_token.get_position()));
  1700. pending.push_front(token_type(T_RIGHTPAREN, ")", pragma_token.get_position()));
  1701. pending.push_front(token_type(T_STRINGLIT, string_type("\"") + pragma_cmd + "\"",
  1702. pragma_token.get_position()));
  1703. pending.push_front(token_type(T_LEFTPAREN, "(", pragma_token.get_position()));
  1704. pending.push_front(pragma_token);
  1705. return false;
  1706. }
  1707. ///////////////////////////////////////////////////////////////////////////////
  1708. //
  1709. // Test, whether the result of a concat operator is well formed or not.
  1710. //
  1711. // This is done by re-scanning (re-tokenizing) the resulting token sequence,
  1712. // which should give back exactly one token.
  1713. //
  1714. ///////////////////////////////////////////////////////////////////////////////
  1715. template <typename ContextT>
  1716. template <typename ContainerT>
  1717. inline bool
  1718. macromap<ContextT>::is_valid_concat(string_type new_value,
  1719. position_type const &pos, ContainerT &rescanned)
  1720. {
  1721. // re-tokenize the newly generated string
  1722. typedef typename ContextT::lexer_type lexer_type;
  1723. std::string value_to_test(new_value.c_str());
  1724. boost::wave::language_support lang =
  1725. boost::wave::enable_prefer_pp_numbers(ctx.get_language());
  1726. lang = boost::wave::enable_single_line(lang);
  1727. lexer_type it = lexer_type(value_to_test.begin(), value_to_test.end(), pos,
  1728. lang);
  1729. lexer_type end = lexer_type();
  1730. for (/**/; it != end && T_EOF != token_id(*it); ++it)
  1731. {
  1732. // as of Wave V2.0.7 pasting of tokens is valid only if the resulting
  1733. // tokens are pp_tokens (as mandated by C++11)
  1734. if (!is_pp_token(*it))
  1735. return false;
  1736. rescanned.push_back(*it);
  1737. }
  1738. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1739. if (boost::wave::need_variadics(ctx.get_language()))
  1740. return true; // in variadics mode token pasting is well defined
  1741. #endif
  1742. // test if the newly generated token sequence contains more than 1 token
  1743. return 1 == rescanned.size();
  1744. }
  1745. ///////////////////////////////////////////////////////////////////////////////
  1746. //
  1747. // Bulk update expand positions
  1748. //
  1749. ///////////////////////////////////////////////////////////////////////////////
  1750. // batch update tokens with a single expand position
  1751. template <typename ContextT>
  1752. template <typename ContainerT>
  1753. void macromap<ContextT>::set_expand_positions(ContainerT &tokens, position_type pos)
  1754. {
  1755. typename ContainerT::iterator ex_end = tokens.end();
  1756. for (typename ContainerT::iterator it = tokens.begin();
  1757. it != ex_end; ++it) {
  1758. // expand positions are only used for __LINE__, __FILE__, and macro names
  1759. if (token_id(*it) == T_IDENTIFIER)
  1760. it->set_expand_position(pos);
  1761. }
  1762. }
  1763. ///////////////////////////////////////////////////////////////////////////////
  1764. //
  1765. // Handle all occurrences of the concatenation operator '##' inside the given
  1766. // token sequence.
  1767. //
  1768. ///////////////////////////////////////////////////////////////////////////////
  1769. template <typename Context>
  1770. inline void report_invalid_concatenation(Context& ctx,
  1771. typename Context::token_type const& prev,
  1772. typename Context::token_type const& next,
  1773. typename Context::position_type const& main_pos)
  1774. {
  1775. typename Context::string_type error_string("\"");
  1776. error_string += prev.get_value();
  1777. error_string += "\" and \"";
  1778. error_string += next.get_value();
  1779. error_string += "\"";
  1780. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception, invalid_concat,
  1781. error_string.c_str(), main_pos);
  1782. }
  1783. template <typename ContextT>
  1784. template <typename ContainerT>
  1785. inline bool
  1786. macromap<ContextT>::concat_tokensequence(ContainerT &expanded)
  1787. {
  1788. using namespace boost::wave;
  1789. typedef typename ContainerT::iterator iterator_type;
  1790. iterator_type end = expanded.end();
  1791. iterator_type prev = end;
  1792. for (iterator_type it = expanded.begin(); it != end; /**/)
  1793. {
  1794. if (T_POUND_POUND == BASE_TOKEN(token_id(*it))) {
  1795. iterator_type next = it;
  1796. ++next;
  1797. if (prev == end || next == end) {
  1798. // error, '##' should be in between two tokens
  1799. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1800. ill_formed_operator, "concat ('##')", main_pos);
  1801. return false;
  1802. }
  1803. // replace prev##next with the concatenated value, skip whitespace
  1804. // before and after the '##' operator
  1805. while (IS_CATEGORY(*next, WhiteSpaceTokenType)) {
  1806. ++next;
  1807. if (next == end) {
  1808. // error, '##' should be in between two tokens
  1809. BOOST_WAVE_THROW_CTX(ctx, preprocess_exception,
  1810. ill_formed_operator, "concat ('##')", main_pos);
  1811. return false;
  1812. }
  1813. }
  1814. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1815. if (boost::wave::need_variadics(ctx.get_language())) {
  1816. if (T_PLACEMARKER == token_id(*next)) {
  1817. // remove the '##' and the next tokens from the sequence
  1818. iterator_type first_to_delete = prev;
  1819. expanded.erase(++first_to_delete, ++next);
  1820. it = next;
  1821. continue;
  1822. }
  1823. else if (T_PLACEMARKER == token_id(*prev)) {
  1824. // remove the '##' and the next tokens from the sequence
  1825. iterator_type first_to_delete = prev;
  1826. *prev = *next;
  1827. expanded.erase(++first_to_delete, ++next);
  1828. it = next;
  1829. continue;
  1830. }
  1831. }
  1832. #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1833. // test if the concat operator has to concatenate two unrelated
  1834. // tokens i.e. the result yields more then one token
  1835. string_type concat_result;
  1836. ContainerT rescanned;
  1837. concat_result = ((*prev).get_value() + (*next).get_value());
  1838. // analyze the validity of the concatenation result
  1839. if (!is_valid_concat(concat_result, (*prev).get_position(),
  1840. rescanned) &&
  1841. !IS_CATEGORY(*prev, WhiteSpaceTokenType) &&
  1842. !IS_CATEGORY(*next, WhiteSpaceTokenType))
  1843. {
  1844. report_invalid_concatenation(ctx, *prev, *next, main_pos);
  1845. return false;
  1846. }
  1847. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1848. if (boost::wave::need_variadics(ctx.get_language())) {
  1849. // remove the prev, '##' and the next tokens from the sequence
  1850. expanded.erase(prev, ++next); // remove not needed tokens
  1851. // some stl implementations clear() the container if we erased all
  1852. // the elements, which orphans all iterators. we re-initialize these
  1853. // here
  1854. if (expanded.empty())
  1855. end = next = expanded.end();
  1856. // replace the old token (pointed to by *prev) with the re-tokenized
  1857. // sequence
  1858. expanded.splice(next, rescanned);
  1859. // the last token of the inserted sequence is the new previous
  1860. prev = next;
  1861. if (next != expanded.end())
  1862. --prev;
  1863. }
  1864. else
  1865. #endif // BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1866. {
  1867. // we leave the token_id unchanged, but unmark the token as
  1868. // disabled, if appropriate
  1869. (*prev).set_value(concat_result);
  1870. if (T_NONREPLACABLE_IDENTIFIER == token_id(*prev))
  1871. (*prev).set_token_id(T_IDENTIFIER);
  1872. // remove the '##' and the next tokens from the sequence
  1873. iterator_type first_to_delete = prev;
  1874. expanded.erase(++first_to_delete, ++next);
  1875. }
  1876. it = next;
  1877. continue;
  1878. }
  1879. // save last non-whitespace token position
  1880. if (!IS_CATEGORY(*it, WhiteSpaceTokenType))
  1881. prev = it;
  1882. ++it; // next token, please
  1883. }
  1884. return true;
  1885. }
  1886. ///////////////////////////////////////////////////////////////////////////////
  1887. //
  1888. // predefine_macro(): predefine a single macro
  1889. //
  1890. ///////////////////////////////////////////////////////////////////////////////
  1891. template <typename ContextT>
  1892. inline void
  1893. macromap<ContextT>::predefine_macro(defined_macros_type *scope,
  1894. string_type const &name, token_type const &t)
  1895. {
  1896. definition_container_type macrodefinition;
  1897. std::vector<token_type> param;
  1898. macrodefinition.push_back(t);
  1899. add_macro(token_type(T_IDENTIFIER, name, t.get_position()),
  1900. false, param, macrodefinition, true, scope);
  1901. }
  1902. ///////////////////////////////////////////////////////////////////////////////
  1903. //
  1904. // init_predefined_macros(): init the predefined macros
  1905. //
  1906. ///////////////////////////////////////////////////////////////////////////////
  1907. template <typename ContextT>
  1908. inline void
  1909. macromap<ContextT>::init_predefined_macros(char const *fname,
  1910. defined_macros_type *scope, bool at_global_scope)
  1911. {
  1912. // if no scope is given, use the current one
  1913. defined_macros_type* current_scope = scope ? scope : current_macros;
  1914. // first, add the static macros
  1915. position_type pos("<built-in>");
  1916. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1917. if (boost::wave::need_c99(ctx.get_language())) {
  1918. // define C99 specifics
  1919. for (int i = 0; 0 != predef.static_data_c99(i).name; ++i) {
  1920. predefined_macros::static_macros const& m = predef.static_data_c99(i);
  1921. predefine_macro(current_scope, m.name,
  1922. token_type(m.token_id, m.value, pos));
  1923. }
  1924. }
  1925. else
  1926. #endif
  1927. {
  1928. #if BOOST_WAVE_SUPPORT_CPP0X != 0
  1929. if (boost::wave::need_cpp0x(ctx.get_language())) {
  1930. // define C++11 specifics
  1931. for (int i = 0; 0 != predef.static_data_cpp0x(i).name; ++i) {
  1932. predefined_macros::static_macros const& m = predef.static_data_cpp0x(i);
  1933. predefine_macro(current_scope, m.name,
  1934. token_type(m.token_id, m.value, pos));
  1935. }
  1936. }
  1937. else
  1938. #endif
  1939. #if BOOST_WAVE_SUPPORT_CPP2A != 0
  1940. if (boost::wave::need_cpp2a(ctx.get_language())) {
  1941. // define C++20 specifics
  1942. for (int i = 0; 0 != predef.static_data_cpp2a(i).name; ++i) {
  1943. predefined_macros::static_macros const& m = predef.static_data_cpp2a(i);
  1944. predefine_macro(current_scope, m.name,
  1945. token_type(m.token_id, m.value, pos));
  1946. }
  1947. }
  1948. else
  1949. #endif
  1950. {
  1951. // define C++ specifics
  1952. for (int i = 0; 0 != predef.static_data_cpp(i).name; ++i) {
  1953. predefined_macros::static_macros const& m = predef.static_data_cpp(i);
  1954. predefine_macro(current_scope, m.name,
  1955. token_type(m.token_id, m.value, pos));
  1956. }
  1957. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  1958. // define __WAVE_HAS_VARIADICS__, if appropriate
  1959. if (boost::wave::need_variadics(ctx.get_language())) {
  1960. predefine_macro(current_scope, "__WAVE_HAS_VARIADICS__",
  1961. token_type(T_INTLIT, "1", pos));
  1962. }
  1963. #endif
  1964. }
  1965. }
  1966. // predefine the __BASE_FILE__ macro which contains the main file name
  1967. namespace fs = boost::filesystem;
  1968. if (string_type(fname) != "<Unknown>") {
  1969. fs::path filename(create_path(fname));
  1970. using boost::wave::util::impl::escape_lit;
  1971. predefine_macro(current_scope, "__BASE_FILE__",
  1972. token_type(T_STRINGLIT, string_type("\"") +
  1973. escape_lit(native_file_string(filename)).c_str() + "\"", pos));
  1974. base_name = fname;
  1975. }
  1976. else if (!base_name.empty()) {
  1977. fs::path filename(create_path(base_name.c_str()));
  1978. using boost::wave::util::impl::escape_lit;
  1979. predefine_macro(current_scope, "__BASE_FILE__",
  1980. token_type(T_STRINGLIT, string_type("\"") +
  1981. escape_lit(native_file_string(filename)).c_str() + "\"", pos));
  1982. }
  1983. // now add the dynamic macros
  1984. for (int j = 0; 0 != predef.dynamic_data(j).name; ++j) {
  1985. predefined_macros::dynamic_macros const& m = predef.dynamic_data(j);
  1986. predefine_macro(current_scope, m.name,
  1987. token_type(m.token_id, (predef.* m.generator)(), pos));
  1988. }
  1989. }
  1990. ///////////////////////////////////////////////////////////////////////////////
  1991. //
  1992. // reset_macromap(): initialize the internal macro symbol namespace
  1993. //
  1994. ///////////////////////////////////////////////////////////////////////////////
  1995. template <typename ContextT>
  1996. inline void
  1997. macromap<ContextT>::reset_macromap()
  1998. {
  1999. current_macros->clear();
  2000. predef.reset();
  2001. act_token = token_type();
  2002. }
  2003. ///////////////////////////////////////////////////////////////////////////////
  2004. }}} // namespace boost::wave::util
  2005. #if BOOST_WAVE_SERIALIZATION != 0
  2006. namespace boost { namespace serialization {
  2007. template<typename ContextT>
  2008. struct version<boost::wave::util::macromap<ContextT> >
  2009. {
  2010. typedef boost::wave::util::macromap<ContextT> target_type;
  2011. typedef mpl::int_<target_type::version> type;
  2012. typedef mpl::integral_c_tag tag;
  2013. BOOST_STATIC_CONSTANT(unsigned int, value = version::type::value);
  2014. };
  2015. }} // namespace boost::serialization
  2016. #endif
  2017. // the suffix header occurs after all of the code
  2018. #ifdef BOOST_HAS_ABI_HEADERS
  2019. #include BOOST_ABI_SUFFIX
  2020. #endif
  2021. #endif // !defined(BOOST_CPP_MACROMAP_HPP_CB8F51B0_A3F0_411C_AEF4_6FF631B8B414_INCLUDED)