@@ -1485,7 +1485,7 @@ namespace simplecpp {
14851485
14861486 class Macro {
14871487 public:
1488- explicit Macro (std::vector<std::string> &f) : nameTokDef(nullptr ), valueToken(nullptr ), endToken(nullptr ), files(f), tokenListDefine(f), variadic(false ), valueDefinedInCode_(false ) {}
1488+ 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 ) {}
14891489
14901490 Macro (const Token *tok, std::vector<std::string> &f) : nameTokDef(nullptr ), files(f), tokenListDefine(f), valueDefinedInCode_(true ) {
14911491 if (sameline (tok->previousSkipComments (), tok))
@@ -1515,6 +1515,11 @@ namespace simplecpp {
15151515 *this = other;
15161516 }
15171517
1518+ ~Macro () {
1519+ delete optExpandValue;
1520+ delete optNoExpandValue;
1521+ }
1522+
15181523 Macro &operator =(const Macro &other) {
15191524 if (this != &other) {
15201525 files = other.files ;
@@ -1707,6 +1712,9 @@ namespace simplecpp {
17071712 bool parseDefine (const Token *nametoken) {
17081713 nameTokDef = nametoken;
17091714 variadic = false ;
1715+ variadicOpt = false ;
1716+ optExpandValue = nullptr ;
1717+ optNoExpandValue = nullptr ;
17101718 if (!nameTokDef) {
17111719 valueToken = endToken = nullptr ;
17121720 args.clear ();
@@ -1744,8 +1752,54 @@ namespace simplecpp {
17441752 if (!sameline (valueToken, nameTokDef))
17451753 valueToken = nullptr ;
17461754 endToken = valueToken;
1747- while (sameline (endToken, nameTokDef))
1755+ while (sameline (endToken, nameTokDef)) {
1756+ if (variadic && endToken->str () == " __VA_OPT__" )
1757+ variadicOpt = true ;
17481758 endToken = endToken->next ;
1759+ }
1760+
1761+ if (variadicOpt) {
1762+ TokenList expandValue (files);
1763+ TokenList noExpandValue (files);
1764+ for (const Token *tok = valueToken; tok && tok != endToken;) {
1765+ if (tok->str () == " __VA_OPT__" ) {
1766+ if (!sameline (tok, tok->next ) || tok->next ->op != ' (' )
1767+ throw Error (tok->location , " In definition of '" + nameTokDef->str () + " ': Missing opening parenthesis for __VA_OPT__" );
1768+ tok = tok->next ->next ;
1769+ int par = 1 ;
1770+ while (tok && tok != endToken) {
1771+ if (tok->op == ' (' )
1772+ par++;
1773+ else if (tok->op == ' )' )
1774+ par--;
1775+ else if (tok->str () == " __VA_OPT__" )
1776+ throw Error (tok->location , " In definition of '" + nameTokDef->str () + " ': __VA_OPT__ cannot be nested" );
1777+ if (par == 0 ) {
1778+ tok = tok->next ;
1779+ break ;
1780+ }
1781+ expandValue.push_back (new Token (*tok));
1782+ tok = tok->next ;
1783+ }
1784+ if (par != 0 ) {
1785+ const Token *const lastTok = expandValue.back () ? expandValue.back () : valueToken->next ;
1786+ throw Error (lastTok->location , " In definition of '" + nameTokDef->str () + " ': Missing closing parenthesis for __VA_OPT__" );
1787+ }
1788+ } else {
1789+ expandValue.push_back (new Token (*tok));
1790+ noExpandValue.push_back (new Token (*tok));
1791+ tok = tok->next ;
1792+ }
1793+ }
1794+ #if __cplusplus >= 201103L
1795+ optExpandValue = new TokenList (std::move (expandValue));
1796+ optNoExpandValue = new TokenList (std::move (noExpandValue));
1797+ #else
1798+ optExpandValue = new TokenList (expandValue);
1799+ optNoExpandValue = new TokenList (noExpandValue);
1800+ #endif
1801+ }
1802+
17491803 return true ;
17501804 }
17511805
@@ -1900,8 +1954,22 @@ namespace simplecpp {
19001954
19011955 Token * const output_end_1 = output->back ();
19021956
1957+ const Token *valueToken2;
1958+ const Token *endToken2;
1959+
1960+ if (variadicOpt) {
1961+ if (parametertokens2.size () > args.size () && parametertokens2[args.size () - 1 ]->next ->op != ' )' )
1962+ valueToken2 = optExpandValue->cfront ();
1963+ else
1964+ valueToken2 = optNoExpandValue->cfront ();
1965+ endToken2 = nullptr ;
1966+ } else {
1967+ valueToken2 = valueToken;
1968+ endToken2 = endToken;
1969+ }
1970+
19031971 // expand
1904- for (const Token *tok = valueToken ; tok != endToken ;) {
1972+ for (const Token *tok = valueToken2 ; tok != endToken2 ;) {
19051973 if (tok->op != ' #' ) {
19061974 // A##B => AB
19071975 if (sameline (tok, tok->next ) && tok->next && tok->next ->op == ' #' && tok->next ->next && tok->next ->next ->op == ' #' ) {
@@ -1950,7 +2018,7 @@ namespace simplecpp {
19502018 }
19512019
19522020 tok = tok->next ;
1953- if (tok == endToken ) {
2021+ if (tok == endToken2 ) {
19542022 output->push_back (new Token (*tok->previous ));
19552023 break ;
19562024 }
@@ -2020,24 +2088,6 @@ namespace simplecpp {
20202088 // Macro parameter..
20212089 {
20222090 TokenList temp (files);
2023- if (tok->str () == " __VA_OPT__" ) {
2024- if (sameline (tok, tok->next ) && tok->next ->str () == " (" ) {
2025- tok = tok->next ;
2026- int paren = 1 ;
2027- while (sameline (tok, tok->next )) {
2028- if (tok->next ->str () == " (" )
2029- ++paren;
2030- else if (tok->next ->str () == " )" )
2031- --paren;
2032- if (paren == 0 )
2033- return tok->next ->next ;
2034- tok = tok->next ;
2035- if (parametertokens.size () > args.size () && parametertokens.front ()->next ->str () != " )" )
2036- tok = expandToken (output, loc, tok, macros, expandedmacros, parametertokens)->previous ;
2037- }
2038- }
2039- throw Error (tok->location , " Missing parenthesis for __VA_OPT__(content)" );
2040- }
20412091 if (expandArg (&temp, tok, loc, macros, expandedmacros, parametertokens)) {
20422092 if (tok->str () == " __VA_ARGS__" && temp.empty () && output->cback () && output->cback ()->str () == " ," &&
20432093 tok->nextSkipComments () && tok->nextSkipComments ()->str () == " )" )
@@ -2338,6 +2388,13 @@ namespace simplecpp {
23382388 /* * is macro variadic? */
23392389 bool variadic;
23402390
2391+ /* * does the macro expansion have __VA_OPT__? */
2392+ bool variadicOpt;
2393+
2394+ /* * Expansion value for varadic macros with __VA_OPT__ expanded and discarded respectively */
2395+ const TokenList *optExpandValue;
2396+ const TokenList *optNoExpandValue;
2397+
23412398 /* * was the value of this macro actually defined in the code? */
23422399 bool valueDefinedInCode_;
23432400 };
@@ -3621,6 +3678,16 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
36213678 }
36223679 output.clear ();
36233680 return ;
3681+ } catch (simplecpp::Macro::Error &err) {
3682+ if (outputList) {
3683+ simplecpp::Output out (files);
3684+ out.type = simplecpp::Output::SYNTAX_ERROR;
3685+ out.location = err.location ;
3686+ out.msg = " Failed to parse #define, " + err.what ;
3687+ outputList->push_back (out);
3688+ }
3689+ output.clear ();
3690+ return ;
36243691 }
36253692 } else if (ifstates.top () == True && rawtok->str () == INCLUDE) {
36263693 TokenList inc1 (files);
0 commit comments