Skip to content

Commit 107c9cf

Browse files
committed
fixed #386 - rewrote define handling [skip ci]
1 parent 3deeb91 commit 107c9cf

File tree

3 files changed

+117
-31
lines changed

3 files changed

+117
-31
lines changed

simplecpp.cpp

Lines changed: 48 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3289,25 +3289,28 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
32893289
// use a dummy vector for the macros because as this is not part of the file and would add an empty entry - e.g. /usr/include/poll.h
32903290
std::vector<std::string> dummy;
32913291

3292+
bool strictAnsiDefined = false;
3293+
bool strictAnsiUndefined = false;
32923294
const bool hasInclude = isCpp17OrLater(dui) || isGnu(dui);
32933295
MacroMap macros;
3294-
bool strictAnsiDefined = false;
3295-
for (std::list<std::string>::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) {
3296-
const std::string &macrostr = *it;
3297-
const std::string::size_type eq = macrostr.find('=');
3298-
const std::string::size_type par = macrostr.find('(');
3299-
const std::string macroname = macrostr.substr(0, std::min(eq,par));
3300-
if (macroname == "__STRICT_ANSI__")
3301-
strictAnsiDefined = true;
3302-
if (dui.undefined.find(macroname) != dui.undefined.end())
3296+
for (std::list<Define>::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) {
3297+
// TODO: (
3298+
const std::string& lhs(it->name);
3299+
if (it->undef) {
3300+
if (lhs == "__STRICT_ANSI__")
3301+
strictAnsiUndefined = true;
3302+
const MacroMap::iterator m_it = macros.find(lhs);
3303+
if (m_it != macros.end())
3304+
macros.erase(m_it);
33033305
continue;
3304-
const std::string lhs(macrostr.substr(0,eq));
3305-
const std::string rhs(eq==std::string::npos ? std::string("1") : macrostr.substr(eq+1));
3306+
}
3307+
if (lhs == "__STRICT_ANSI__")
3308+
strictAnsiDefined = true;
3309+
const std::string rhs(it->value.empty() ? "1" : it->value);
33063310
const Macro macro(lhs, rhs, dummy);
33073311
macros.insert(std::pair<TokenString,Macro>(macro.name(), macro));
33083312
}
33093313

3310-
const bool strictAnsiUndefined = dui.undefined.find("__STRICT_ANSI__") != dui.undefined.cend();
33113314
if (!isGnu(dui) && !strictAnsiDefined && !strictAnsiUndefined)
33123315
macros.insert(std::pair<TokenString, Macro>("__STRICT_ANSI__", Macro("__STRICT_ANSI__", "1", dummy)));
33133316

@@ -3418,13 +3421,11 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
34183421
continue;
34193422
try {
34203423
const Macro &macro = Macro(rawtok->previous, files);
3421-
if (dui.undefined.find(macro.name()) == dui.undefined.end()) {
3422-
const MacroMap::iterator it = macros.find(macro.name());
3423-
if (it == macros.end())
3424-
macros.insert(std::pair<TokenString, Macro>(macro.name(), macro));
3425-
else
3426-
it->second = macro;
3427-
}
3424+
const MacroMap::iterator it = macros.find(macro.name());
3425+
if (it == macros.end())
3426+
macros.insert(std::pair<TokenString, Macro>(macro.name(), macro));
3427+
else
3428+
it->second = macro;
34283429
} catch (const std::runtime_error &) {
34293430
if (outputList) {
34303431
simplecpp::Output err(files);
@@ -3857,3 +3858,31 @@ std::string simplecpp::getCppStdString(const std::string &std)
38573858
{
38583859
return getCppStdString(getCppStd(std));
38593860
}
3861+
3862+
simplecpp::Define simplecpp::Define::parse(const std::string& def, bool prefix)
3863+
{
3864+
Define define;
3865+
std::string::size_type offset = 0;
3866+
if (prefix) {
3867+
if (def.size() < 3)
3868+
throw 0;
3869+
if (def[0] != '-')
3870+
throw 0;
3871+
if (def[1] == 'U')
3872+
define.undef = true;
3873+
else if (def[2] != 'D')
3874+
throw 0;
3875+
offset = 2;
3876+
}
3877+
const std::string::size_type sep = def.find('=');
3878+
if (sep == std::string::npos) {
3879+
define.name = def.substr(offset);
3880+
}
3881+
else {
3882+
if (define.undef)
3883+
throw 0;
3884+
define.name = def.substr(offset, sep - offset);
3885+
define.value = def.substr(sep + 1);
3886+
}
3887+
return define;
3888+
}

simplecpp.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define simplecppH
88

99
#include <cctype>
10+
#include <cstdint>
1011
#include <cstring>
1112
#include <iosfwd>
1213
#include <list>
@@ -389,14 +390,33 @@ namespace simplecpp {
389390
long long result; // condition result
390391
};
391392

393+
struct SIMPLECPP_LIB Define {
394+
enum Type : std::uint8_t {
395+
Def,
396+
Undef,
397+
Builtin
398+
};
399+
400+
Define() : undef(false) {}
401+
Define(const std::string& def, Type t = Def) : undef(t == Undef) {
402+
const Define d = parse(def, false);
403+
name = d.name;
404+
value = d.value;
405+
}
406+
std::string name;
407+
std::string value;
408+
bool undef;
409+
410+
static Define parse(const std::string& def, bool prefix = true); /** parse -D/-U string */
411+
};
412+
392413
/**
393414
* Command line preprocessor settings.
394415
* On the command line these are configured by -D, -U, -I, --include, -std
395416
*/
396417
struct SIMPLECPP_LIB DUI {
397418
DUI() : clearIncludeCache(false), removeComments(false) {}
398-
std::list<std::string> defines;
399-
std::set<std::string> undefined;
419+
std::list<Define> defines;
400420
std::list<std::string> includePaths;
401421
std::list<std::string> includes;
402422
std::string std;

test.cpp

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,7 @@ static void strict_ansi_3()
17061706
"#endif";
17071707
simplecpp::DUI dui;
17081708
dui.std = "c99";
1709-
dui.undefined.insert("__STRICT_ANSI__");
1709+
dui.defines.emplace_back("__STRICT_ANSI__", simplecpp::Define::Undef);
17101710
ASSERT_EQUALS("", preprocess(code, dui));
17111711
}
17121712

@@ -1717,7 +1717,7 @@ static void strict_ansi_4()
17171717
"#endif";
17181718
simplecpp::DUI dui;
17191719
dui.std = "gnu99";
1720-
dui.defines.push_back("__STRICT_ANSI__");
1720+
dui.defines.emplace_back("__STRICT_ANSI__");
17211721
ASSERT_EQUALS("\nA", preprocess(code, dui));
17221722
}
17231723

@@ -1764,7 +1764,7 @@ static void ifA()
17641764
ASSERT_EQUALS("", preprocess(code));
17651765

17661766
simplecpp::DUI dui;
1767-
dui.defines.push_back("A=1");
1767+
dui.defines.emplace_back("A=1");
17681768
ASSERT_EQUALS("\nX", preprocess(code, dui));
17691769
}
17701770

@@ -1783,7 +1783,7 @@ static void ifDefined()
17831783
"#endif";
17841784
simplecpp::DUI dui;
17851785
ASSERT_EQUALS("", preprocess(code, dui));
1786-
dui.defines.push_back("A=1");
1786+
dui.defines.emplace_back("A=1");
17871787
ASSERT_EQUALS("\nX", preprocess(code, dui));
17881788
}
17891789

@@ -1794,7 +1794,7 @@ static void ifDefinedNoPar()
17941794
"#endif";
17951795
simplecpp::DUI dui;
17961796
ASSERT_EQUALS("", preprocess(code, dui));
1797-
dui.defines.push_back("A=1");
1797+
dui.defines.emplace_back("A=1");
17981798
ASSERT_EQUALS("\nX", preprocess(code, dui));
17991799
}
18001800

@@ -1806,7 +1806,7 @@ static void ifDefinedNested()
18061806
"#endif";
18071807
simplecpp::DUI dui;
18081808
ASSERT_EQUALS("", preprocess(code, dui));
1809-
dui.defines.push_back("FOO=1");
1809+
dui.defines.emplace_back("FOO=1");
18101810
ASSERT_EQUALS("\n\nX", preprocess(code, dui));
18111811
}
18121812

@@ -1818,7 +1818,7 @@ static void ifDefinedNestedNoPar()
18181818
"#endif";
18191819
simplecpp::DUI dui;
18201820
ASSERT_EQUALS("", preprocess(code, dui));
1821-
dui.defines.push_back("FOO=1");
1821+
dui.defines.emplace_back("FOO=1");
18221822
ASSERT_EQUALS("\n\nX", preprocess(code, dui));
18231823
}
18241824

@@ -1871,10 +1871,10 @@ static void ifLogical()
18711871
simplecpp::DUI dui;
18721872
ASSERT_EQUALS("", preprocess(code, dui));
18731873
dui.defines.clear();
1874-
dui.defines.push_back("A=1");
1874+
dui.defines.emplace_back("A=1");
18751875
ASSERT_EQUALS("\nX", preprocess(code, dui));
18761876
dui.defines.clear();
1877-
dui.defines.push_back("B=1");
1877+
dui.defines.emplace_back("B=1");
18781878
ASSERT_EQUALS("\nX", preprocess(code, dui));
18791879
}
18801880

@@ -2768,7 +2768,7 @@ static void userdef()
27682768
{
27692769
const char code[] = "#ifdef A\n123\n#endif\n";
27702770
simplecpp::DUI dui;
2771-
dui.defines.push_back("A=1");
2771+
dui.defines.emplace_back("A=1");
27722772
ASSERT_EQUALS("\n123", preprocess(code, dui));
27732773
}
27742774

@@ -3246,6 +3246,41 @@ static void safe_api()
32463246
#endif
32473247
}
32483248

3249+
static void define_parse()
3250+
{
3251+
{
3252+
const simplecpp::Define define = simplecpp::Define::parse("-DDEF");
3253+
ASSERT_EQUALS("DEF", define.name);
3254+
ASSERT_EQUALS("", define.value);
3255+
ASSERT_EQUALS(false, define.undef);
3256+
}
3257+
{
3258+
const simplecpp::Define define = simplecpp::Define::parse("-DDEF=1");
3259+
ASSERT_EQUALS("DEF", define.name);
3260+
ASSERT_EQUALS("1", define.value);
3261+
ASSERT_EQUALS(false, define.undef);
3262+
}
3263+
{
3264+
const simplecpp::Define define = simplecpp::Define::parse("-UDEF");
3265+
ASSERT_EQUALS("DEF", define.name);
3266+
ASSERT_EQUALS("", define.value);
3267+
ASSERT_EQUALS(true, define.undef);
3268+
}
3269+
3270+
{
3271+
const simplecpp::Define define = simplecpp::Define::parse("DEF", false);
3272+
ASSERT_EQUALS("DEF", define.name);
3273+
ASSERT_EQUALS("", define.value);
3274+
ASSERT_EQUALS(false, define.undef);
3275+
}
3276+
{
3277+
const simplecpp::Define define = simplecpp::Define::parse("DEF=1", false);
3278+
ASSERT_EQUALS("DEF", define.name);
3279+
ASSERT_EQUALS("1", define.value);
3280+
ASSERT_EQUALS(false, define.undef);
3281+
}
3282+
}
3283+
32493284
static void fuzz_crash()
32503285
{
32513286
{
@@ -3514,6 +3549,8 @@ int main(int argc, char **argv)
35143549

35153550
TEST_CASE(safe_api);
35163551

3552+
TEST_CASE(define_parse);
3553+
35173554
TEST_CASE(fuzz_crash);
35183555

35193556
return numberOfFailedAssertions > 0 ? EXIT_FAILURE : EXIT_SUCCESS;

0 commit comments

Comments
 (0)