@@ -102,8 +102,6 @@ static const simplecpp::TokenString ONCE("once");
102102
103103static const simplecpp::TokenString HAS_INCLUDE (" __has_include" );
104104
105- static const simplecpp::TokenString INNER_COMMA (" ,," );
106-
107105template <class T > static std::string toString (T t)
108106{
109107 // NOLINTNEXTLINE(misc-const-correctness) - false positive
@@ -888,7 +886,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
888886 }
889887
890888 if (prefix.empty ())
891- push_back (new Token (s, location)); // push string without newlines
889+ push_back (new Token (s, location, isspace (stream. peekChar ()) )); // push string without newlines
892890 else
893891 back ()->setstr (prefix + s);
894892
@@ -918,7 +916,7 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
918916 }
919917 }
920918
921- push_back (new Token (currentToken, location));
919+ push_back (new Token (currentToken, location, isspace (stream. peekChar ()) ));
922920
923921 if (multiline)
924922 location.col += currentToken.size ();
@@ -1548,9 +1546,9 @@ namespace simplecpp {
15481546 // Copy macro call to a new tokenlist with no linebreaks
15491547 const Token * const rawtok1 = rawtok;
15501548 TokenList rawtokens2 (inputFiles);
1551- rawtokens2.push_back (new Token (rawtok->str (), rawtok1->location ));
1549+ rawtokens2.push_back (new Token (rawtok->str (), rawtok1->location , rawtok-> whitespaceahead ));
15521550 rawtok = rawtok->next ;
1553- rawtokens2.push_back (new Token (rawtok->str (), rawtok1->location ));
1551+ rawtokens2.push_back (new Token (rawtok->str (), rawtok1->location , rawtok-> whitespaceahead ));
15541552 rawtok = rawtok->next ;
15551553 int par = 1 ;
15561554 while (rawtok && par > 0 ) {
@@ -1560,13 +1558,10 @@ namespace simplecpp {
15601558 --par;
15611559 else if (rawtok->op == ' #' && !sameline (rawtok->previous , rawtok))
15621560 throw Error (rawtok->location , " it is invalid to use a preprocessor directive as macro parameter" );
1563- rawtokens2.push_back (new Token (rawtok->str (), rawtok1->location ));
1561+ rawtokens2.push_back (new Token (rawtok->str (), rawtok1->location , rawtok-> whitespaceahead ));
15641562 rawtok = rawtok->next ;
15651563 }
1566- bool first = true ;
1567- if (valueToken && valueToken->str () == rawtok1->str ())
1568- first = false ;
1569- if (expand (&output2, rawtok1->location , rawtokens2.cfront (), macros, expandedmacros, first))
1564+ if (expand (&output2, rawtok1->location , rawtokens2.cfront (), macros, expandedmacros))
15701565 rawtok = rawtok1->next ;
15711566 } else {
15721567 rawtok = expand (&output2, rawtok->location , rawtok, macros, expandedmacros);
@@ -1622,10 +1617,6 @@ namespace simplecpp {
16221617 rawtok = rawtok2->next ;
16231618 }
16241619 output->takeTokens (output2);
1625- for (Token* tok = output->front (); tok; tok = tok->next ) {
1626- if (tok->str () == INNER_COMMA)
1627- tok->setstr (" ," );
1628- }
16291620 return rawtok;
16301621 }
16311622
@@ -1792,28 +1783,12 @@ namespace simplecpp {
17921783 // A##B => AB
17931784 tok = expandHashHash (tokens, rawloc, tok, macros, expandedmacros, parametertokens);
17941785 } else if (tok->op == ' #' && sameline (tok, tok->next ) && tok->next ->op != ' #' ) {
1795- tok = expandHash (tokens, rawloc, tok, macros, expandedmacros, parametertokens);
1786+ tok = expandHash (tokens, rawloc, tok, expandedmacros, parametertokens);
17961787 } else {
17971788 if (!expandArg (tokens, tok, rawloc, macros, expandedmacros, parametertokens)) {
1798- bool expanded = false ;
1799- const MacroMap::const_iterator it = macros.find (tok->str ());
1800- if (it != macros.end () && expandedmacros.find (tok->str ()) == expandedmacros.end ()) {
1801- const Macro &m = it->second ;
1802- if (!m.functionLike ()) {
1803- Token* mtok = tokens->back ();
1804- m.expand (tokens, rawloc, tok, macros, expandedmacros);
1805- for (mtok = mtok->next ; mtok; mtok = mtok->next ) {
1806- if (mtok->op == ' ,' )
1807- mtok->setstr (INNER_COMMA);
1808- }
1809- expanded = true ;
1810- }
1811- }
1812- if (!expanded) {
1813- tokens->push_back (new Token (*tok));
1814- if (tok->macro .empty () && (par > 0 || tok->str () != " (" ))
1815- tokens->back ()->macro = name ();
1816- }
1789+ tokens->push_back (new Token (*tok));
1790+ if (tok->macro .empty () && (par > 0 || tok->str () != " (" ))
1791+ tokens->back ()->macro = name ();
18171792 }
18181793
18191794 if (tok->op == ' (' )
@@ -1831,10 +1806,8 @@ namespace simplecpp {
18311806 return sameline (lpar,tok) ? tok : nullptr ;
18321807 }
18331808
1834- const Token * expand (TokenList * const output, const Location &loc, const Token * const nameTokInst, const MacroMap ¯os, std::set<TokenString> expandedmacros, bool first=false ) const {
1835-
1836- if (!first)
1837- expandedmacros.insert (nameTokInst->str ());
1809+ const Token * expand (TokenList * const output, const Location &loc, const Token * const nameTokInst, const MacroMap ¯os, std::set<TokenString> expandedmacros) const {
1810+ expandedmacros.insert (nameTokInst->str ());
18381811
18391812 usageList.push_back (loc);
18401813
@@ -1917,6 +1890,14 @@ namespace simplecpp {
19171890 if (sameline (tok, tok->next ) && tok->next && tok->next ->op == ' #' && tok->next ->next && tok->next ->next ->op == ' #' ) {
19181891 if (!sameline (tok, tok->next ->next ->next ))
19191892 throw invalidHashHash::unexpectedNewline (tok->location , name ());
1893+ if (variadic && tok->op == ' ,' && tok->next ->next ->next ->str () == args.back ()) {
1894+ Token *const comma = newMacroToken (tok->str (), loc, isReplaced (expandedmacros), tok);
1895+ output->push_back (comma);
1896+ tok = expandToken (output, loc, tok->next ->next ->next , macros, expandedmacros, parametertokens2);
1897+ if (output->back () == comma)
1898+ output->deleteToken (comma);
1899+ continue ;
1900+ }
19201901 TokenList new_output (files);
19211902 if (!expandArg (&new_output, tok, parametertokens2))
19221903 output->push_back (newMacroToken (tok->str (), loc, isReplaced (expandedmacros), tok));
@@ -1961,7 +1942,7 @@ namespace simplecpp {
19611942 tok = expandHashHash (output, loc, tok->previous , macros, expandedmacros, parametertokens2);
19621943 } else {
19631944 // #123 => "123"
1964- tok = expandHash (output, loc, tok->previous , macros, expandedmacros, parametertokens2);
1945+ tok = expandHash (output, loc, tok->previous , expandedmacros, parametertokens2);
19651946 }
19661947 }
19671948
@@ -2138,14 +2119,17 @@ namespace simplecpp {
21382119 return true ;
21392120 for (const Token *partok = parametertokens[argnr]->next ; partok != parametertokens[argnr + 1U ];) {
21402121 const MacroMap::const_iterator it = macros.find (partok->str ());
2141- if (it != macros.end () && !partok->isExpandedFrom (&it->second ) && (partok->str () == name () || expandedmacros.find (partok->str ()) == expandedmacros.end ()))
2142- partok = it->second .expand (output, loc, partok, macros, expandedmacros);
2143- else {
2122+ if (it != macros.end () && !partok->isExpandedFrom (&it->second ) && (partok->str () == name () || expandedmacros.find (partok->str ()) == expandedmacros.end ())) {
2123+ const std::set<TokenString> expandedmacros2; // temporary amnesia to allow reexpansion of currently expanding macros during argument evaluation
2124+ partok = it->second .expand (output, loc, partok, macros, expandedmacros2);
2125+ } else {
21442126 output->push_back (newMacroToken (partok->str (), loc, isReplaced (expandedmacros), partok));
21452127 output->back ()->macro = partok->macro ;
21462128 partok = partok->next ;
21472129 }
21482130 }
2131+ if (tok->whitespaceahead && output->back ())
2132+ output->back ()->whitespaceahead = true ;
21492133 return true ;
21502134 }
21512135
@@ -2154,18 +2138,22 @@ namespace simplecpp {
21542138 * @param output destination tokenlist
21552139 * @param loc location for expanded token
21562140 * @param tok The # token
2157- * @param macros all macros
21582141 * @param expandedmacros set with expanded macros, with this macro
21592142 * @param parametertokens parameters given when expanding this macro
21602143 * @return token after the X
21612144 */
2162- const Token *expandHash (TokenList *output, const Location &loc, const Token *tok, const MacroMap ¯os, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) const {
2145+ const Token *expandHash (TokenList *output, const Location &loc, const Token *tok, const std::set<TokenString> &expandedmacros, const std::vector<const Token*> ¶metertokens) const {
21632146 TokenList tokenListHash (files);
2164- tok = expandToken (&tokenListHash, loc, tok->next , macros, expandedmacros, parametertokens);
2147+ const MacroMap macros2; // temporarily bypass macro expansion
2148+ tok = expandToken (&tokenListHash, loc, tok->next , macros2, expandedmacros, parametertokens);
21652149 std::ostringstream ostr;
21662150 ostr << ' \" ' ;
2167- for (const Token *hashtok = tokenListHash.cfront (); hashtok; hashtok = hashtok->next )
2151+ for (const Token *hashtok = tokenListHash.cfront (), *next; hashtok; hashtok = next) {
2152+ next = hashtok->next ;
21682153 ostr << hashtok->str ();
2154+ if (next && hashtok->whitespaceahead )
2155+ ostr << ' ' ;
2156+ }
21692157 ostr << ' \" ' ;
21702158 output->push_back (newMacroToken (escapeString (ostr.str ()), loc, isReplaced (expandedmacros)));
21712159 return tok;
0 commit comments