@@ -1463,7 +1463,7 @@ namespace simplecpp {
14631463
14641464 class Macro {
14651465 public:
1466- explicit Macro (std::vector<std::string> &f) : nameTokDef(nullptr ), valueToken(nullptr ), endToken(nullptr ), files(f), tokenListDefine(f), variadic(false ), valueDefinedInCode_(false ) {}
1466+ 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 ) {}
14671467
14681468 Macro (const Token *tok, std::vector<std::string> &f) : nameTokDef(nullptr ), files(f), tokenListDefine(f), valueDefinedInCode_(true ) {
14691469 if (sameline (tok->previousSkipComments (), tok))
@@ -1493,6 +1493,11 @@ namespace simplecpp {
14931493 *this = other;
14941494 }
14951495
1496+ ~Macro () {
1497+ delete optExpandValue;
1498+ delete optNoExpandValue;
1499+ }
1500+
14961501 Macro &operator =(const Macro &other) {
14971502 if (this != &other) {
14981503 files = other.files ;
@@ -1685,6 +1690,9 @@ namespace simplecpp {
16851690 bool parseDefine (const Token *nametoken) {
16861691 nameTokDef = nametoken;
16871692 variadic = false ;
1693+ variadicOpt = false ;
1694+ optExpandValue = nullptr ;
1695+ optNoExpandValue = nullptr ;
16881696 if (!nameTokDef) {
16891697 valueToken = endToken = nullptr ;
16901698 args.clear ();
@@ -1722,8 +1730,54 @@ namespace simplecpp {
17221730 if (!sameline (valueToken, nameTokDef))
17231731 valueToken = nullptr ;
17241732 endToken = valueToken;
1725- while (sameline (endToken, nameTokDef))
1733+ while (sameline (endToken, nameTokDef)) {
1734+ if (variadic && endToken->str () == " __VA_OPT__" )
1735+ variadicOpt = true ;
17261736 endToken = endToken->next ;
1737+ }
1738+
1739+ if (variadicOpt) {
1740+ TokenList expandValue (files);
1741+ TokenList noExpandValue (files);
1742+ for (const Token *tok = valueToken; tok && tok != endToken;) {
1743+ if (tok->str () == " __VA_OPT__" ) {
1744+ if (!sameline (tok, tok->next ) || tok->next ->op != ' (' )
1745+ throw Error (tok->location , " In definition of '" + nameTokDef->str () + " ': Missing opening parenthesis for __VA_OPT__" );
1746+ tok = tok->next ->next ;
1747+ int par = 1 ;
1748+ while (tok && tok != endToken) {
1749+ if (tok->op == ' (' )
1750+ par++;
1751+ else if (tok->op == ' )' )
1752+ par--;
1753+ else if (tok->str () == " __VA_OPT__" )
1754+ throw Error (tok->location , " In definition of '" + nameTokDef->str () + " ': __VA_OPT__ cannot be nested" );
1755+ if (par == 0 ) {
1756+ tok = tok->next ;
1757+ break ;
1758+ }
1759+ expandValue.push_back (new Token (*tok));
1760+ tok = tok->next ;
1761+ }
1762+ if (par != 0 ) {
1763+ const Token *const lastTok = expandValue.back () ? expandValue.back () : valueToken->next ;
1764+ throw Error (lastTok->location , " In definition of '" + nameTokDef->str () + " ': Missing closing parenthesis for __VA_OPT__" );
1765+ }
1766+ } else {
1767+ expandValue.push_back (new Token (*tok));
1768+ noExpandValue.push_back (new Token (*tok));
1769+ tok = tok->next ;
1770+ }
1771+ }
1772+ #if __cplusplus >= 201103L
1773+ optExpandValue = new TokenList (std::move (expandValue));
1774+ optNoExpandValue = new TokenList (std::move (noExpandValue));
1775+ #else
1776+ optExpandValue = new TokenList (expandValue);
1777+ optNoExpandValue = new TokenList (noExpandValue);
1778+ #endif
1779+ }
1780+
17271781 return true ;
17281782 }
17291783
@@ -1878,8 +1932,22 @@ namespace simplecpp {
18781932
18791933 Token * const output_end_1 = output->back ();
18801934
1935+ const Token *valueToken2;
1936+ const Token *endToken2;
1937+
1938+ if (variadicOpt) {
1939+ if (parametertokens2.size () > args.size () && parametertokens2[args.size () - 1 ]->next ->op != ' )' )
1940+ valueToken2 = optExpandValue->cfront ();
1941+ else
1942+ valueToken2 = optNoExpandValue->cfront ();
1943+ endToken2 = nullptr ;
1944+ } else {
1945+ valueToken2 = valueToken;
1946+ endToken2 = endToken;
1947+ }
1948+
18811949 // expand
1882- for (const Token *tok = valueToken ; tok != endToken ;) {
1950+ for (const Token *tok = valueToken2 ; tok != endToken2 ;) {
18831951 if (tok->op != ' #' ) {
18841952 // A##B => AB
18851953 if (sameline (tok, tok->next ) && tok->next && tok->next ->op == ' #' && tok->next ->next && tok->next ->next ->op == ' #' ) {
@@ -1928,7 +1996,7 @@ namespace simplecpp {
19281996 }
19291997
19301998 tok = tok->next ;
1931- if (tok == endToken ) {
1999+ if (tok == endToken2 ) {
19322000 output->push_back (new Token (*tok->previous ));
19332001 break ;
19342002 }
@@ -1998,24 +2066,6 @@ namespace simplecpp {
19982066 // Macro parameter..
19992067 {
20002068 TokenList temp (files);
2001- if (tok->str () == " __VA_OPT__" ) {
2002- if (sameline (tok, tok->next ) && tok->next ->str () == " (" ) {
2003- tok = tok->next ;
2004- int paren = 1 ;
2005- while (sameline (tok, tok->next )) {
2006- if (tok->next ->str () == " (" )
2007- ++paren;
2008- else if (tok->next ->str () == " )" )
2009- --paren;
2010- if (paren == 0 )
2011- return tok->next ->next ;
2012- tok = tok->next ;
2013- if (parametertokens.size () > args.size () && parametertokens.front ()->next ->str () != " )" )
2014- tok = expandToken (output, loc, tok, macros, expandedmacros, parametertokens)->previous ;
2015- }
2016- }
2017- throw Error (tok->location , " Missing parenthesis for __VA_OPT__(content)" );
2018- }
20192069 if (expandArg (&temp, tok, loc, macros, expandedmacros, parametertokens)) {
20202070 if (tok->str () == " __VA_ARGS__" && temp.empty () && output->cback () && output->cback ()->str () == " ," &&
20212071 tok->nextSkipComments () && tok->nextSkipComments ()->str () == " )" )
@@ -2316,6 +2366,13 @@ namespace simplecpp {
23162366 /* * is macro variadic? */
23172367 bool variadic;
23182368
2369+ /* * does the macro expansion have __VA_OPT__? */
2370+ bool variadicOpt;
2371+
2372+ /* * Expansion value for varadic macros with __VA_OPT__ expanded and discarded respectively */
2373+ const TokenList *optExpandValue;
2374+ const TokenList *optNoExpandValue;
2375+
23192376 /* * was the value of this macro actually defined in the code? */
23202377 bool valueDefinedInCode_;
23212378 };
@@ -3561,6 +3618,16 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
35613618 }
35623619 output.clear ();
35633620 return ;
3621+ } catch (simplecpp::Macro::Error &err) {
3622+ if (outputList) {
3623+ simplecpp::Output out (files);
3624+ out.type = simplecpp::Output::SYNTAX_ERROR;
3625+ out.location = err.location ;
3626+ out.msg = " Failed to parse #define, " + err.what ;
3627+ outputList->push_back (out);
3628+ }
3629+ output.clear ();
3630+ return ;
35643631 }
35653632 } else if (ifstates.top () == True && rawtok->str () == INCLUDE) {
35663633 TokenList inc1 (files);
0 commit comments