@@ -1485,7 +1485,7 @@ namespace simplecpp {
1485
1485
1486
1486
class Macro {
1487
1487
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 ) {}
1489
1489
1490
1490
Macro (const Token *tok, std::vector<std::string> &f) : nameTokDef(nullptr ), files(f), tokenListDefine(f), valueDefinedInCode_(true ) {
1491
1491
if (sameline (tok->previousSkipComments (), tok))
@@ -1515,6 +1515,11 @@ namespace simplecpp {
1515
1515
*this = other;
1516
1516
}
1517
1517
1518
+ ~Macro () {
1519
+ delete optExpandValue;
1520
+ delete optNoExpandValue;
1521
+ }
1522
+
1518
1523
Macro &operator =(const Macro &other) {
1519
1524
if (this != &other) {
1520
1525
files = other.files ;
@@ -1707,6 +1712,9 @@ namespace simplecpp {
1707
1712
bool parseDefine (const Token *nametoken) {
1708
1713
nameTokDef = nametoken;
1709
1714
variadic = false ;
1715
+ variadicOpt = false ;
1716
+ optExpandValue = nullptr ;
1717
+ optNoExpandValue = nullptr ;
1710
1718
if (!nameTokDef) {
1711
1719
valueToken = endToken = nullptr ;
1712
1720
args.clear ();
@@ -1744,8 +1752,54 @@ namespace simplecpp {
1744
1752
if (!sameline (valueToken, nameTokDef))
1745
1753
valueToken = nullptr ;
1746
1754
endToken = valueToken;
1747
- while (sameline (endToken, nameTokDef))
1755
+ while (sameline (endToken, nameTokDef)) {
1756
+ if (variadic && endToken->str () == " __VA_OPT__" )
1757
+ variadicOpt = true ;
1748
1758
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
+
1749
1803
return true ;
1750
1804
}
1751
1805
@@ -1900,8 +1954,22 @@ namespace simplecpp {
1900
1954
1901
1955
Token * const output_end_1 = output->back ();
1902
1956
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
+
1903
1971
// expand
1904
- for (const Token *tok = valueToken ; tok != endToken ;) {
1972
+ for (const Token *tok = valueToken2 ; tok != endToken2 ;) {
1905
1973
if (tok->op != ' #' ) {
1906
1974
// A##B => AB
1907
1975
if (sameline (tok, tok->next ) && tok->next && tok->next ->op == ' #' && tok->next ->next && tok->next ->next ->op == ' #' ) {
@@ -1950,7 +2018,7 @@ namespace simplecpp {
1950
2018
}
1951
2019
1952
2020
tok = tok->next ;
1953
- if (tok == endToken ) {
2021
+ if (tok == endToken2 ) {
1954
2022
output->push_back (new Token (*tok->previous ));
1955
2023
break ;
1956
2024
}
@@ -2020,24 +2088,6 @@ namespace simplecpp {
2020
2088
// Macro parameter..
2021
2089
{
2022
2090
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
- }
2041
2091
if (expandArg (&temp, tok, loc, macros, expandedmacros, parametertokens)) {
2042
2092
if (tok->str () == " __VA_ARGS__" && temp.empty () && output->cback () && output->cback ()->str () == " ," &&
2043
2093
tok->nextSkipComments () && tok->nextSkipComments ()->str () == " )" )
@@ -2338,6 +2388,13 @@ namespace simplecpp {
2338
2388
/* * is macro variadic? */
2339
2389
bool variadic;
2340
2390
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
+
2341
2398
/* * was the value of this macro actually defined in the code? */
2342
2399
bool valueDefinedInCode_;
2343
2400
};
@@ -3621,6 +3678,16 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
3621
3678
}
3622
3679
output.clear ();
3623
3680
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 ;
3624
3691
}
3625
3692
} else if (ifstates.top () == True && rawtok->str () == INCLUDE) {
3626
3693
TokenList inc1 (files);
0 commit comments