@@ -2174,24 +2174,34 @@ namespace simplecpp {
21742174 return &it->second ;
21752175 }
21762176
2177- const Token *recursiveExpandToken (TokenList &output, TokenList &temp, const Location &loc, const Token *tok, const MacroMap ¯os, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) const {
2178- // Expand while the expansion result ends with the name of a function-like
2179- // macro whose arguments are supplied by the tokens that follow it. Each round
2180- // consumes that macro call from the token stream, so tok always advances.
2177+ /* * Expand while the expansion result in @p temp ends with the name of a
2178+ * function-like macro whose arguments are supplied by the tokens after @p tok.
2179+ * Each round consumes that macro call from the token stream, so tok always
2180+ * advances. The @p gatherCall callback copies the "( ... )" tokens that follow
2181+ * @p lpar into its output list and returns the matching ')', or nullptr when no
2182+ * complete call is available. Returns the last consumed token. */
2183+ template <class GatherCall >
2184+ const Token *expandTrailingCalls (TokenList &output, TokenList &temp, const Location &loc, const Token *tok, const MacroMap ¯os, const std::set<TokenString> &expandedmacros, GatherCall gatherCall) const {
21812185 while (const Macro * const calledMacro = rescanMacro (temp, tok, macros, expandedmacros)) {
21822186 TokenList temp2 (files);
2183- temp2.push_back (new Token (temp.cback ()->str (), tok->location ));
2187+ temp2.push_back (new Token (temp.cback ()->str (), tok->next -> location ));
21842188
2185- const Token * const tok2 = appendTokens (temp2, loc, tok->next , macros, expandedmacros, parametertokens );
2186- if (!tok2 )
2189+ const Token * const closingPar = gatherCall (temp2, tok->next );
2190+ if (!closingPar )
21872191 break ;
21882192 output.takeTokens (temp);
21892193 output.deleteToken (output.back ());
21902194 calledMacro->expand (temp, loc, temp2.cfront (), macros, expandedmacros);
2191- tok = tok2 ;
2195+ tok = closingPar ;
21922196 }
21932197 output.takeTokens (temp);
2194- return tok->next ;
2198+ return tok;
2199+ }
2200+
2201+ const Token *recursiveExpandToken (TokenList &output, TokenList &temp, const Location &loc, const Token *tok, const MacroMap ¯os, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) const {
2202+ return expandTrailingCalls (output, temp, loc, tok, macros, expandedmacros, [&](TokenList &temp2, const Token *lpar) {
2203+ return appendTokens (temp2, loc, lpar, macros, expandedmacros, parametertokens);
2204+ })->next ;
21952205 }
21962206
21972207 const Token *expandToken (TokenList &output, const Location &loc, const Token *tok, const MacroMap ¯os, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) const {
@@ -2317,36 +2327,28 @@ namespace simplecpp {
23172327 std::set<TokenString> expandedmacros2 (expandedmacros); // temporary amnesia to allow reexpansion of currently expanding macros during argument evaluation
23182328 expandedmacros2.erase (name ());
23192329 TokenList temp (files);
2320- partok = it->second .expand (temp, loc, partok, macros, expandedmacros2);
2321- // Expand while the expansion result ends with the name of a
2322- // function-like macro whose arguments are supplied by the
2323- // remaining argument tokens
2324- while (partok && partok->previous ) {
2325- const Macro * const calledMacro = rescanMacro (temp, partok->previous , macros, expandedmacros2);
2326- if (!calledMacro)
2327- break ;
2328- TokenList temp2 (files);
2329- temp2.push_back (new Token (temp.cback ()->str (), partok->location ));
2330- unsigned int par = 0 ;
2331- const Token *tok2 = partok;
2332- for (; tok2 && tok2 != argEnd; tok2 = tok2->next ) {
2333- temp2.push_back (new Token (*tok2));
2334- if (tok2->op == ' (' )
2335- ++par;
2336- else if (tok2->op == ' )' ) {
2337- --par;
2338- if (par == 0U )
2339- break ;
2330+ partok = it->second .expand (temp, loc, partok, macros, std::move (expandedmacros2));
2331+ if (partok->op == ' (' && temp.cback () && temp.cback ()->name ) {
2332+ // the expansion result may end with the name of a function-like
2333+ // macro whose arguments are supplied by the remaining argument tokens
2334+ std::set<TokenString> expandedmacros3 (expandedmacros);
2335+ expandedmacros3.erase (name ());
2336+ partok = expandTrailingCalls (output, temp, loc, partok->previous , macros, expandedmacros3, [&](TokenList &temp2, const Token *lpar) -> const Token * {
2337+ unsigned int par = 0 ;
2338+ for (const Token *tok2 = lpar; tok2 != argEnd; tok2 = tok2->next ) {
2339+ temp2.push_back (new Token (*tok2));
2340+ if (tok2->op == ' (' )
2341+ ++par;
2342+ else if (tok2->op == ' )' ) {
2343+ if (--par == 0U )
2344+ return tok2;
2345+ }
23402346 }
2341- }
2342- if (!tok2 || tok2 == argEnd)
2343- break ;
2347+ return nullptr ;
2348+ })-> next ;
2349+ } else {
23442350 output.takeTokens (temp);
2345- output.deleteToken (output.back ());
2346- calledMacro->expand (temp, loc, temp2.cfront (), macros, expandedmacros2);
2347- partok = tok2->next ;
23482351 }
2349- output.takeTokens (temp);
23502352 } else {
23512353 output.push_back (newMacroToken (partok->str (), loc, isReplaced (expandedmacros), partok));
23522354 output.back ()->macro = partok->macro ;
0 commit comments