Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions simplecpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3289,25 +3289,28 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
// 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
std::vector<std::string> dummy;

bool strictAnsiDefined = false;
bool strictAnsiUndefined = false;
const bool hasInclude = isCpp17OrLater(dui) || isGnu(dui);
MacroMap macros;
bool strictAnsiDefined = false;
for (std::list<std::string>::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) {
const std::string &macrostr = *it;
const std::string::size_type eq = macrostr.find('=');
const std::string::size_type par = macrostr.find('(');
const std::string macroname = macrostr.substr(0, std::min(eq,par));
if (macroname == "__STRICT_ANSI__")
strictAnsiDefined = true;
if (dui.undefined.find(macroname) != dui.undefined.end())
for (std::list<Define>::const_iterator it = dui.defines.cbegin(); it != dui.defines.cend(); ++it) {
const std::string& lhs(it->name);
if (it->undef) {
if (lhs == "__STRICT_ANSI__")
strictAnsiUndefined = true;
const MacroMap::iterator m_it = macros.find(lhs);
if (m_it != macros.end())
macros.erase(m_it);
continue;
const std::string lhs(macrostr.substr(0,eq));
const std::string rhs(eq==std::string::npos ? std::string("1") : macrostr.substr(eq+1));
}
if (lhs == "__STRICT_ANSI__")
strictAnsiDefined = true;
const std::string rhs(it->value.empty() ? "1" : it->value);
const Macro macro(lhs, rhs, dummy);
macros.insert(std::pair<TokenString,Macro>(macro.name(), macro));
}

const bool strictAnsiUndefined = dui.undefined.find("__STRICT_ANSI__") != dui.undefined.cend();
// TODO: test left-to-right
if (!isGnu(dui) && !strictAnsiDefined && !strictAnsiUndefined)
macros.insert(std::pair<TokenString, Macro>("__STRICT_ANSI__", Macro("__STRICT_ANSI__", "1", dummy)));

Expand Down Expand Up @@ -3418,13 +3421,11 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
continue;
try {
const Macro &macro = Macro(rawtok->previous, files);
if (dui.undefined.find(macro.name()) == dui.undefined.end()) {
const MacroMap::iterator it = macros.find(macro.name());
if (it == macros.end())
macros.insert(std::pair<TokenString, Macro>(macro.name(), macro));
else
it->second = macro;
}
const MacroMap::iterator it = macros.find(macro.name());
if (it == macros.end())
macros.insert(std::pair<TokenString, Macro>(macro.name(), macro));
else
it->second = macro;
} catch (const std::runtime_error &) {
if (outputList) {
simplecpp::Output err(files);
Expand Down Expand Up @@ -3857,3 +3858,31 @@ std::string simplecpp::getCppStdString(const std::string &std)
{
return getCppStdString(getCppStd(std));
}

simplecpp::Define simplecpp::Define::parse(const std::string& def, bool prefix)
{
Define define;
std::string::size_type offset = 0;
if (prefix) {
if (def.size() < 3)
throw 0;
if (def[0] != '-')
throw 0;
if (def[1] == 'U')
define.undef = true;
else if (def[1] != 'D')
throw 0;
offset = 2;
}
const std::string::size_type sep = def.find('=');
if (sep == std::string::npos) {
define.name = def.substr(offset);
}
else {
if (define.undef)
throw 0;
define.name = def.substr(offset, sep - offset);
define.value = def.substr(sep + 1);
}
return define;
}
24 changes: 22 additions & 2 deletions simplecpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define simplecppH

#include <cctype>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <list>
Expand Down Expand Up @@ -389,14 +390,33 @@ namespace simplecpp {
long long result; // condition result
};

struct SIMPLECPP_LIB Define {
enum Type : std::uint8_t {
Def,
Undef,
Builtin
};

Define() : undef(false) {}
Define(const std::string& def, Type t = Def) : undef(t == Undef) {
const Define d = parse(def, false);
name = d.name;
value = d.value;
}
std::string name;
std::string value;
bool undef;

static Define parse(const std::string& def, bool prefix = true); /** parse -D/-U string */
};

/**
* Command line preprocessor settings.
* On the command line these are configured by -D, -U, -I, --include, -std
*/
struct SIMPLECPP_LIB DUI {
DUI() : clearIncludeCache(false), removeComments(false) {}
std::list<std::string> defines;
std::set<std::string> undefined;
std::list<Define> defines;
std::list<std::string> includePaths;
std::list<std::string> includes;
std::string std;
Expand Down
70 changes: 60 additions & 10 deletions test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1706,7 +1706,7 @@ static void strict_ansi_3()
"#endif";
simplecpp::DUI dui;
dui.std = "c99";
dui.undefined.insert("__STRICT_ANSI__");
dui.defines.emplace_back("__STRICT_ANSI__", simplecpp::Define::Undef);
ASSERT_EQUALS("", preprocess(code, dui));
}

Expand All @@ -1717,7 +1717,7 @@ static void strict_ansi_4()
"#endif";
simplecpp::DUI dui;
dui.std = "gnu99";
dui.defines.push_back("__STRICT_ANSI__");
dui.defines.emplace_back("__STRICT_ANSI__");
ASSERT_EQUALS("\nA", preprocess(code, dui));
}

Expand Down Expand Up @@ -1764,7 +1764,7 @@ static void ifA()
ASSERT_EQUALS("", preprocess(code));

simplecpp::DUI dui;
dui.defines.push_back("A=1");
dui.defines.emplace_back("A=1");
ASSERT_EQUALS("\nX", preprocess(code, dui));
}

Expand All @@ -1783,7 +1783,7 @@ static void ifDefined()
"#endif";
simplecpp::DUI dui;
ASSERT_EQUALS("", preprocess(code, dui));
dui.defines.push_back("A=1");
dui.defines.emplace_back("A=1");
ASSERT_EQUALS("\nX", preprocess(code, dui));
}

Expand All @@ -1794,7 +1794,7 @@ static void ifDefinedNoPar()
"#endif";
simplecpp::DUI dui;
ASSERT_EQUALS("", preprocess(code, dui));
dui.defines.push_back("A=1");
dui.defines.emplace_back("A=1");
ASSERT_EQUALS("\nX", preprocess(code, dui));
}

Expand All @@ -1806,7 +1806,7 @@ static void ifDefinedNested()
"#endif";
simplecpp::DUI dui;
ASSERT_EQUALS("", preprocess(code, dui));
dui.defines.push_back("FOO=1");
dui.defines.emplace_back("FOO=1");
ASSERT_EQUALS("\n\nX", preprocess(code, dui));
}

Expand All @@ -1818,7 +1818,7 @@ static void ifDefinedNestedNoPar()
"#endif";
simplecpp::DUI dui;
ASSERT_EQUALS("", preprocess(code, dui));
dui.defines.push_back("FOO=1");
dui.defines.emplace_back("FOO=1");
ASSERT_EQUALS("\n\nX", preprocess(code, dui));
}

Expand Down Expand Up @@ -1871,10 +1871,10 @@ static void ifLogical()
simplecpp::DUI dui;
ASSERT_EQUALS("", preprocess(code, dui));
dui.defines.clear();
dui.defines.push_back("A=1");
dui.defines.emplace_back("A=1");
ASSERT_EQUALS("\nX", preprocess(code, dui));
dui.defines.clear();
dui.defines.push_back("B=1");
dui.defines.emplace_back("B=1");
ASSERT_EQUALS("\nX", preprocess(code, dui));
}

Expand Down Expand Up @@ -2768,7 +2768,7 @@ static void userdef()
{
const char code[] = "#ifdef A\n123\n#endif\n";
simplecpp::DUI dui;
dui.defines.push_back("A=1");
dui.defines.emplace_back("A=1");
ASSERT_EQUALS("\n123", preprocess(code, dui));
}

Expand Down Expand Up @@ -3246,6 +3246,54 @@ static void safe_api()
#endif
}

static void define_parse()
{
{
const simplecpp::Define define = simplecpp::Define::parse("-DDEF");
ASSERT_EQUALS("DEF", define.name);
ASSERT_EQUALS("", define.value);
ASSERT_EQUALS(false, define.undef);
}
{
const simplecpp::Define define = simplecpp::Define::parse("-DDEF=1");
ASSERT_EQUALS("DEF", define.name);
ASSERT_EQUALS("1", define.value);
ASSERT_EQUALS(false, define.undef);
}
{
const simplecpp::Define define = simplecpp::Define::parse("-UDEF");
ASSERT_EQUALS("DEF", define.name);
ASSERT_EQUALS("", define.value);
ASSERT_EQUALS(true, define.undef);
}

{
const simplecpp::Define define = simplecpp::Define::parse("DEF", false);
ASSERT_EQUALS("DEF", define.name);
ASSERT_EQUALS("", define.value);
ASSERT_EQUALS(false, define.undef);
}
{
const simplecpp::Define define = simplecpp::Define::parse("DEF=1", false);
ASSERT_EQUALS("DEF", define.name);
ASSERT_EQUALS("1", define.value);
ASSERT_EQUALS(false, define.undef);
}
{
const simplecpp::Define define = simplecpp::Define::parse("-D__has_builtin(x)=(1)", true);
ASSERT_EQUALS("__has_builtin(x)", define.name);
ASSERT_EQUALS("(1)", define.value);
ASSERT_EQUALS(false, define.undef);
}
{
const simplecpp::Define define = simplecpp::Define::parse("__has_builtin(x)=(1)", false);
ASSERT_EQUALS("__has_builtin(x)", define.name);
ASSERT_EQUALS("(1)", define.value);
ASSERT_EQUALS(false, define.undef);
}
// -UDEF=0
}

static void fuzz_crash()
{
{
Expand Down Expand Up @@ -3514,6 +3562,8 @@ int main(int argc, char **argv)

TEST_CASE(safe_api);

TEST_CASE(define_parse);

TEST_CASE(fuzz_crash);

return numberOfFailedAssertions > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
Expand Down