diff --git a/main.cpp b/main.cpp index 3c3dceb42..01d65b1ae 100644 --- a/main.cpp +++ b/main.cpp @@ -239,7 +239,7 @@ int main(int argc, char* argv[]) std::ifstream fin( fname.c_str() ); std::map code; - preprocess(fin, code); + preprocess(fin, code, fname); for ( std::map::const_iterator it = code.begin(); it != code.end(); ++it ) CppCheck(it->second, filenames[c].c_str(), c); diff --git a/preprocessor.cpp b/preprocessor.cpp index 329c4495c..4ca818645 100644 --- a/preprocessor.cpp +++ b/preprocessor.cpp @@ -18,6 +18,7 @@ #include "preprocessor.h" +#include "CommonCheck.h" #include #include @@ -44,7 +45,7 @@ static std::string getcode(const std::string &filedata, std::string cfg); * \param istr The (file/string) stream to read from. * \param result The map that will get the results */ -void preprocess(std::istream &istr, std::map &result) +void preprocess(std::istream &istr, std::map &result, const std::string filename) { // Get filedata from stream.. bool ignoreSpace = true; @@ -52,6 +53,14 @@ void preprocess(std::istream &istr, std::map &result) std::ostringstream code; for (char ch = (char)istr.get(); istr.good(); ch = (char)istr.get()) { + if ( ch < 0 ) + { + // Bad content.. + errout << "[" << filename << "] Bad character found: " << int((unsigned char)ch) << std::endl; + result.clear(); + return; + } + // Replace assorted special chars with spaces.. if ( ch < 0 ) ch = ' '; @@ -160,7 +169,7 @@ void preprocess(std::istream &istr, std::map &result) static std::string 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 ) + if ( def && line.find("#ifdef ") != 0 && line.find("#if ") != 0 && line.find("#elif ") != 0 ) { return ""; } @@ -198,6 +207,8 @@ static std::list getcfgs( const std::string &filedata ) std::string def = getdef(line, true) + getdef(line, false); if (!def.empty()) { + if ( ! deflist.empty() && line.find("#elif ") == 0 ) + deflist.pop_back(); deflist.push_back(def); def = ""; for ( std::list::const_iterator it = deflist.begin(); it != deflist.end(); ++it) @@ -261,6 +272,7 @@ static std::string getcode(const std::string &filedata, std::string cfg) std::ostringstream ret; std::list matching_ifdef; + std::list matched_ifdef; std::istringstream istr(filedata); std::string line; @@ -269,17 +281,47 @@ static std::string getcode(const std::string &filedata, std::string cfg) std::string def = getdef( line, true ); std::string ndef = getdef( line, false ); - if ( ! def.empty() ) + if ( line.find("#elif ") == 0 ) + { + if ( matched_ifdef.back() ) + { + matching_ifdef.back() = false; + } + else + { + if ( match_cfg_def(cfg, def) ) + { + matching_ifdef.back() = true; + matched_ifdef.back() = true; + } + } + } + + else if ( ! def.empty() ) + { matching_ifdef.push_back( match_cfg_def(cfg, def) ); + matched_ifdef.push_back( matching_ifdef.back() ); + } else if ( ! ndef.empty() ) + { matching_ifdef.push_back( ! match_cfg_def(cfg, ndef) ); + matched_ifdef.push_back( matching_ifdef.back() ); + } - else if ( line == "#else" && !matching_ifdef.empty() ) - matching_ifdef.back() = ! matching_ifdef.back(); + else if ( line == "#else" ) + { + if ( ! matched_ifdef.empty() ) + matching_ifdef.back() = ! matched_ifdef.back(); + } - else if ( line == "#endif" && !matching_ifdef.empty() ) - matching_ifdef.pop_back(); + else if ( line == "#endif" ) + { + if ( ! matched_ifdef.empty() ) + matched_ifdef.pop_back(); + if ( ! matching_ifdef.empty() ) + matching_ifdef.pop_back(); + } bool match = true; for ( std::list::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it ) @@ -289,6 +331,7 @@ static std::string getcode(const std::string &filedata, std::string cfg) if ( line.find("#if") == 0 || line.find("#else") == 0 || + line.find("#elif") == 0 || line.find("#endif") == 0 ) line = ""; diff --git a/preprocessor.h b/preprocessor.h index a349aba64..759fb4821 100644 --- a/preprocessor.h +++ b/preprocessor.h @@ -26,7 +26,7 @@ #include -void preprocess(std::istream &istr, std::map &result); +void preprocess(std::istream &istr, std::map &result, const std::string &filename); //--------------------------------------------------------------------------- #endif diff --git a/testpreprocessor.cpp b/testpreprocessor.cpp index 0dc288ad7..35d929b43 100644 --- a/testpreprocessor.cpp +++ b/testpreprocessor.cpp @@ -52,6 +52,8 @@ private: TEST_CASE( if0 ); TEST_CASE( if1 ); + TEST_CASE( elif ); + TEST_CASE( include1 ); TEST_CASE( if_cond1 ); @@ -325,6 +327,30 @@ private: } + void elif() + { + const char filedata[] = "#if DEF1\n" + "ABC\n" + "#elif DEF2\n" + "DEF\n" + "#endif\n"; + + // Expected result.. + std::map expected; + expected[""] = "\n\n\n\n\n"; + expected["DEF1"] = "\nABC\n\n\n\n"; + expected["DEF2"] = "\n\n\nDEF\n\n"; + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + preprocess( istr, actual ); + + // Compare results.. + ASSERT_EQUALS( true, cmpmaps(actual, expected)); + } + + void include1() {