@@ -1462,7 +1462,7 @@ namespace simplecpp {
14621462
14631463 class Macro {
14641464 public:
1465- explicit Macro (std::vector<std::string> &f) : nameTokDef(nullptr ), valueToken(nullptr ), endToken(nullptr ), files(f), tokenListDefine(f), variadic(false ), valueDefinedInCode_(false ) {}
1465+ explicit Macro (std::vector<std::string> &f) : nameTokDef(nullptr ), valueToken(nullptr ), endToken(nullptr ), files(f), tokenListDefine(f), variadic(false ), variadicOpt( false ), optExpandValue( nullptr ), optNoExpandValue( nullptr ), valueDefinedInCode_(false ) {}
14661466
14671467 Macro (const Token *tok, std::vector<std::string> &f) : nameTokDef(nullptr ), files(f), tokenListDefine(f), valueDefinedInCode_(true ) {
14681468 if (sameline (tok->previousSkipComments (), tok))
@@ -1492,6 +1492,11 @@ namespace simplecpp {
14921492 *this = other;
14931493 }
14941494
1495+ ~Macro () {
1496+ delete optExpandValue;
1497+ delete optNoExpandValue;
1498+ }
1499+
14951500 Macro &operator =(const Macro &other) {
14961501 if (this != &other) {
14971502 files = other.files ;
@@ -1684,6 +1689,9 @@ namespace simplecpp {
16841689 bool parseDefine (const Token *nametoken) {
16851690 nameTokDef = nametoken;
16861691 variadic = false ;
1692+ variadicOpt = false ;
1693+ optExpandValue = nullptr ;
1694+ optNoExpandValue = nullptr ;
16871695 if (!nameTokDef) {
16881696 valueToken = endToken = nullptr ;
16891697 args.clear ();
@@ -1721,8 +1729,49 @@ namespace simplecpp {
17211729 if (!sameline (valueToken, nameTokDef))
17221730 valueToken = nullptr ;
17231731 endToken = valueToken;
1724- while (sameline (endToken, nameTokDef))
1732+ while (sameline (endToken, nameTokDef)) {
1733+ if (variadic && endToken->str () == " __VA_OPT__" )
1734+ variadicOpt = true ;
17251735 endToken = endToken->next ;
1736+ }
1737+
1738+ if (variadicOpt) {
1739+ TokenList expandValue (files);
1740+ TokenList noExpandValue (files);
1741+ for (const Token *tok = valueToken; tok && tok != endToken;) {
1742+ if (tok->str () == " __VA_OPT__" ) {
1743+ if (!sameline (tok, tok->next ) || tok->next ->op != ' (' )
1744+ throw Error (tok->location , " In definition of '" + nameTokDef->str () + " ': Missing opening parenthesis for __VA_OPT__" );
1745+ tok = tok->next ->next ;
1746+ int par = 1 ;
1747+ while (tok && tok != endToken) {
1748+ if (tok->op == ' (' )
1749+ par++;
1750+ else if (tok->op == ' )' )
1751+ par--;
1752+ else if (tok->str () == " __VA_OPT__" )
1753+ throw Error (tok->location , " In definition of '" + nameTokDef->str () + " ': __VA_OPT__ cannot be nested" );
1754+ if (par == 0 ) {
1755+ tok = tok->next ;
1756+ break ;
1757+ }
1758+ expandValue.push_back (new Token (*tok));
1759+ tok = tok->next ;
1760+ }
1761+ if (par != 0 ) {
1762+ const Token *const lastTok = expandValue.back () ? expandValue.back () : valueToken->next ;
1763+ throw Error (lastTok->location , " In definition of '" + nameTokDef->str () + " ': Missing closing parenthesis for __VA_OPT__" );
1764+ }
1765+ } else {
1766+ expandValue.push_back (new Token (*tok));
1767+ noExpandValue.push_back (new Token (*tok));
1768+ tok = tok->next ;
1769+ }
1770+ }
1771+ optExpandValue = new TokenList (std::move (expandValue));
1772+ optNoExpandValue = new TokenList (std::move (noExpandValue));
1773+ }
1774+
17261775 return true ;
17271776 }
17281777
@@ -1877,8 +1926,22 @@ namespace simplecpp {
18771926
18781927 Token * const output_end_1 = output->back ();
18791928
1929+ const Token *valueToken2;
1930+ const Token *endToken2;
1931+
1932+ if (variadicOpt) {
1933+ if (parametertokens2.size () > args.size () && parametertokens2[args.size () - 1 ]->next ->op != ' )' )
1934+ valueToken2 = optExpandValue->cfront ();
1935+ else
1936+ valueToken2 = optNoExpandValue->cfront ();
1937+ endToken2 = nullptr ;
1938+ } else {
1939+ valueToken2 = valueToken;
1940+ endToken2 = endToken;
1941+ }
1942+
18801943 // expand
1881- for (const Token *tok = valueToken ; tok != endToken ;) {
1944+ for (const Token *tok = valueToken2 ; tok != endToken2 ;) {
18821945 if (tok->op != ' #' ) {
18831946 // A##B => AB
18841947 if (sameline (tok, tok->next ) && tok->next && tok->next ->op == ' #' && tok->next ->next && tok->next ->next ->op == ' #' ) {
@@ -1927,7 +1990,7 @@ namespace simplecpp {
19271990 }
19281991
19291992 tok = tok->next ;
1930- if (tok == endToken ) {
1993+ if (tok == endToken2 ) {
19311994 output->push_back (new Token (*tok->previous ));
19321995 break ;
19331996 }
@@ -1997,24 +2060,6 @@ namespace simplecpp {
19972060 // Macro parameter..
19982061 {
19992062 TokenList temp (files);
2000- if (tok->str () == " __VA_OPT__" ) {
2001- if (sameline (tok, tok->next ) && tok->next ->str () == " (" ) {
2002- tok = tok->next ;
2003- int paren = 1 ;
2004- while (sameline (tok, tok->next )) {
2005- if (tok->next ->str () == " (" )
2006- ++paren;
2007- else if (tok->next ->str () == " )" )
2008- --paren;
2009- if (paren == 0 )
2010- return tok->next ->next ;
2011- tok = tok->next ;
2012- if (parametertokens.size () > args.size () && parametertokens.front ()->next ->str () != " )" )
2013- tok = expandToken (output, loc, tok, macros, expandedmacros, parametertokens)->previous ;
2014- }
2015- }
2016- throw Error (tok->location , " Missing parenthesis for __VA_OPT__(content)" );
2017- }
20182063 if (expandArg (&temp, tok, loc, macros, expandedmacros, parametertokens)) {
20192064 if (tok->str () == " __VA_ARGS__" && temp.empty () && output->cback () && output->cback ()->str () == " ," &&
20202065 tok->nextSkipComments () && tok->nextSkipComments ()->str () == " )" )
@@ -2315,6 +2360,13 @@ namespace simplecpp {
23152360 /* * is macro variadic? */
23162361 bool variadic;
23172362
2363+ /* * does the macro expansion have __VA_OPT__? */
2364+ bool variadicOpt;
2365+
2366+ /* * Expansion value for varadic macros with __VA_OPT__ expanded and discarded respectively */
2367+ const TokenList *optExpandValue;
2368+ const TokenList *optNoExpandValue;
2369+
23182370 /* * was the value of this macro actually defined in the code? */
23192371 bool valueDefinedInCode_;
23202372 };
@@ -3473,6 +3525,16 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
34733525 }
34743526 output.clear ();
34753527 return ;
3528+ } catch (simplecpp::Macro::Error &err) {
3529+ if (outputList) {
3530+ simplecpp::Output out (files);
3531+ out.type = simplecpp::Output::SYNTAX_ERROR;
3532+ out.location = err.location ;
3533+ out.msg = " Failed to parse #define, " + err.what ;
3534+ outputList->push_back (out);
3535+ }
3536+ output.clear ();
3537+ return ;
34763538 }
34773539 } else if (ifstates.top () == True && rawtok->str () == INCLUDE) {
34783540 TokenList inc1 (files);
0 commit comments