From 7890589693c8369aa7aa695f5e453956ebfe2b79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 20 Nov 2009 19:18:57 +0100 Subject: [PATCH] Fixed #912 (### Unlogged error at Tokenizer::syntaxError: Invalid number of character (()) --- lib/preprocessor.cpp | 77 ++++++++++++++++++++++++++++++++++----- lib/preprocessor.h | 2 +- test/testpreprocessor.cpp | 20 ++++++++++ 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 9fc6a2408..0b6fc5409 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -161,7 +160,15 @@ void Preprocessor::writeError(const std::string &fileName, const std::string &co { if (lineNumbers.empty() || fileIndexes.empty()) { - std::cerr << "####### Preprocessor bug! #######\n"; + std::ostringstream line; + line << __LINE__; + + ErrorLogger::ErrorMessage errmsg; + errmsg._severity = "error"; + errmsg._msg = "####### Preprocessor bug! #######"; + errmsg._id = "preprocessor" + line.str(); + errorLogger->reportErr(errmsg); + std::exit(0); } @@ -707,7 +714,7 @@ void Preprocessor::preprocess(std::istream &istr, std::string &processedFile, st processedFile = replaceIfDefined(processedFile); // Get all possible configurations.. - resultConfigurations = getcfgs(processedFile); + resultConfigurations = getcfgs(processedFile, filename); } @@ -743,7 +750,7 @@ std::string Preprocessor::getdef(std::string line, bool def) -std::list Preprocessor::getcfgs(const std::string &filedata) +std::list Preprocessor::getcfgs(const std::string &filedata, const std::string &filename) { std::list ret; ret.push_back(""); @@ -757,10 +764,13 @@ std::list Preprocessor::getcfgs(const std::string &filedata) // 0=>Source file, 1=>Included by source file, 2=>included by header that was included by source file, etc int filelevel = 0; + unsigned int linenr = 0; std::istringstream istr(filedata); std::string line; while (getline(istr, line)) { + ++linenr; + if (line.compare(0, 6, "#file ") == 0) { ++filelevel; @@ -792,6 +802,36 @@ std::list Preprocessor::getcfgs(const std::string &filedata) std::string def = getdef(line, true) + getdef(line, false); if (!def.empty()) { + int par = 0; + for (std::string::size_type pos = 0; pos < def.length(); ++pos) + { + if (def[pos] == '(') + ++par; + else if (def[pos] == ')') + { + --par; + if (par < 0) + break; + } + } + if (par != 0) + { + std::ostringstream line; + line << __LINE__; + + ErrorLogger::ErrorMessage errmsg; + ErrorLogger::ErrorMessage::FileLocation loc; + loc.file = filename; + loc.line = linenr; + errmsg._callStack.push_back(loc); + errmsg._severity = "error"; + errmsg._msg = "mismatching number of '(' and ')' in this line: " + def; + errmsg._id = "preprocessor" + line.str(); + _errorLogger->reportErr(errmsg); + ret.clear(); + return ret; + } + if (! deflist.empty() && line.find("#elif ") == 0) deflist.pop_back(); deflist.push_back(def); @@ -812,7 +852,6 @@ std::list Preprocessor::getcfgs(const std::string &filedata) def += *it; } } - if (std::find(ret.begin(), ret.end(), def) == ret.end()) ret.push_back(def); } @@ -878,11 +917,22 @@ std::list Preprocessor::getcfgs(const std::string &filedata) if (s.find("&&") != std::string::npos) { - Tokenizer tokenizer; + Tokenizer tokenizer(_settings, _errorLogger); std::istringstream istr(s.c_str()); - if (!tokenizer.tokenize(istr, "")) + if (!tokenizer.tokenize(istr, filename.c_str())) { - std::cerr << "Error parsing this:\n" << s << "\n\n"; + std::ostringstream line; + line << __LINE__; + + ErrorLogger::ErrorMessage errmsg; + ErrorLogger::ErrorMessage::FileLocation loc; + loc.file = filename; + loc.line = 1; + errmsg._callStack.push_back(loc); + errmsg._severity = "error"; + errmsg._msg = "Error parsing this: " + s; + errmsg._id = "preprocessor" + line.str(); + _errorLogger->reportErr(errmsg); } @@ -1642,7 +1692,16 @@ std::string Preprocessor::expandMacros(std::string code, const std::string &file continue; } else - std::cerr << "### Preprocessor::expandMacros() loop limit exceeded."; + { + std::ostringstream line; + line << __LINE__; + + ErrorLogger::ErrorMessage errmsg; + errmsg._severity = "error"; + errmsg._msg = "### Preprocessor::expandMacros() loop limit exceeded."; + errmsg._id = "preprocessor" + line.str(); + errorLogger->reportErr(errmsg); + } } break; diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 15510255c..b929e88f8 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -129,7 +129,7 @@ private: * Get all possible configurations sorted in alphabetical order. * By looking at the ifdefs and ifndefs in filedata */ - std::list getcfgs(const std::string &filedata); + std::list getcfgs(const std::string &filedata, const std::string &filename); static std::string getdef(std::string line, bool def); diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 6e7cbe169..77dc67508 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -98,6 +98,7 @@ private: TEST_CASE(if_cond3); TEST_CASE(if_cond4); TEST_CASE(if_cond5); + TEST_CASE(if_cond6); TEST_CASE(multiline1); TEST_CASE(multiline2); @@ -778,6 +779,25 @@ private: ASSERT_EQUALS("\nab\n\ncd\n\nef\n\n", actual["A;B"]); } + void if_cond6() + { + const char filedata[] = "\n" + "#if defined(A) && defined(B))\n" + "#endif\n"; + + errout.str(""); + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + const Settings settings; + Preprocessor preprocessor(&settings, this); + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS("[file.c:2]: (error) mismatching number of '(' and ')' in this line: defined(A)&&defined(B))\n", errout.str()); + } + void multiline1() {