diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 6a29c9e13..3e5ca8726 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -714,13 +714,14 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe std::string Preprocessor::getdef(std::string line, bool def) { // If def is true, the line must start with "#ifdef" - if (def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0 && line.find("#if defined ") != 0) + if (def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 + && (line.find("#elif ") != 0 || line.find("#elif !") == 0)) { return ""; } // If def is false, the line must start with "#ifndef" - if (!def && line.find("#ifndef ") != 0) + if (!def && line.find("#ifndef ") != 0 && line.find("#elif !") != 0) { return ""; } @@ -728,6 +729,17 @@ std::string Preprocessor::getdef(std::string line, bool def) // Remove the "#ifdef" or "#ifndef" if (line.find("#if defined ") == 0) line.erase(0, 11); + else if (line.find("#elif !defined(") == 0) + { + std::string::size_type pos = 0; + + line.erase(0, 15); + pos = line.find(")"); + // if pos == ::npos then another part of the code will complain + // about the mismatch + if (pos != std::string::npos) + line.erase(pos, 1); + } else line.erase(0, line.find(" ")); @@ -1360,6 +1372,22 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg, } } + else if (line.find("#elif !") == 0) + { + if (matched_ifdef.back()) + { + matching_ifdef.back() = false; + } + else + { + if (!match_cfg_def(cfgmap, ndef)) + { + matching_ifdef.back() = true; + matched_ifdef.back() = true; + } + } + } + else if (line.find("#elif ") == 0) { if (matched_ifdef.back()) diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 76823ad26..80d32aacc 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -911,6 +911,7 @@ private: if_cond2b(); if_cond2c(); if_cond2d(); + if_cond2e(); } void if_cond2b() @@ -998,6 +999,31 @@ private: ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n\n\n\n\n\n\n\n", actual["B"]); } + void if_cond2e() + { + const char filedata[] = "#if !defined(A)\n" + "!a\n" + "#elif !defined(B)\n" + "!b\n" + "#endif\n"; + + // Preprocess => actual result.. + errout.str(""); + std::istringstream istr(filedata); + std::map actual; + Settings settings; + settings.debug = settings.debugwarnings = true; + Preprocessor preprocessor(&settings, this); + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS(3, static_cast(actual.size())); + ASSERT_EQUALS("\n!a\n\n\n\n", actual[""]); + ASSERT_EQUALS("\n\n\n!b\n\n", actual["A"]); + TODO_ASSERT_EQUALS("\n\n\n\n\n", "", actual["A;B"]); + ASSERT_EQUALS("", errout.str()); + } + void if_cond3() { const char filedata[] = "#ifdef A\n"