From a781a838222d280d308f6eac01e44ba7fe846f43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 1 Sep 2013 07:13:48 +0200 Subject: [PATCH] Preprocessor: Quicker response for --check-config. No 'normal' code is needed so skip it. --- lib/preprocessor.cpp | 71 +++++++++++++++++++++++++++++++++++++++ lib/preprocessor.h | 3 ++ test/testpreprocessor.cpp | 2 +- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 44b739c3c..00f01647b 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -174,6 +174,9 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename) if (_settings && _settings->terminated()) return ""; + if (_settings && _settings->checkConfiguration) + return readpreprocessor(istr,bom); + // ------------------------------------------------------------------------------------------ // // handling @@ -262,6 +265,74 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename) return result; } + +/** read preprocessor statements */ +std::string Preprocessor::readpreprocessor(std::istream &istr, const unsigned int bom) const +{ + enum { NEWLINE, SPACE, PREPROCESSOR, BACKSLASH, OTHER } state = NEWLINE; + std::ostringstream code; + unsigned int newlines = 1; + char chPrev = ' '; + for (unsigned char ch = readChar(istr,bom); istr.good(); ch = readChar(istr,bom)) { + // Replace assorted special chars with spaces.. + if (((ch & 0x80) == 0) && (ch != '\n') && (std::isspace(ch) || std::iscntrl(ch))) + ch = ' '; + + if (ch == ' ' && chPrev == ' ') + continue; + if (state == PREPROCESSOR && chPrev == '/' && (ch == '/' || ch == '*')) + state = OTHER; + chPrev = ch; + + if (ch == '\n') { + if (state != BACKSLASH) { + state = NEWLINE; + code << std::string(newlines, '\n'); + newlines = 1; + } else { + ++newlines; + state = PREPROCESSOR; + } + continue; + } + + switch (state) { + case NEWLINE: + if (ch==' ') + state = SPACE; + else if (ch == '#') { + state = PREPROCESSOR; + code << ch; + } else + state = OTHER; + break; + case SPACE: + if (ch == '#') { + state = PREPROCESSOR; + code << ch; + } else if (ch != ' ') + state = OTHER; + break; + case PREPROCESSOR: + code << ch; + if (ch == '\\') + state = BACKSLASH; + break; + case BACKSLASH: + code << ch; + if (ch != ' ') + state = PREPROCESSOR; + break; + case OTHER: + break; + }; + } + + std::string result = preprocessCleanupDirectives(code.str()); + result = removeParentheses(result); + return removeIf0(result); +} + std::string Preprocessor::preprocessCleanupDirectives(const std::string &processedFile) { std::ostringstream code; diff --git a/lib/preprocessor.h b/lib/preprocessor.h index d12405a67..4e30641aa 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -92,6 +92,9 @@ public: /** Just read the code into a string. Perform simple cleanup of the code */ std::string read(std::istream &istr, const std::string &filename); + /** read preprocessor statements into a string. */ + std::string readpreprocessor(std::istream &istr, const unsigned int bom) const; + /** * Get preprocessed code for a given configuration * @param filedata file data including preprocessing 'if', 'define', etc diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index fa43151c8..443400521 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -3792,7 +3792,7 @@ private: // Compare results.. ASSERT_EQUALS("[file.c:2]: (information) Include file: \"config.h\" not found.\n", errout.str()); - ASSERT_EQUALS("\n\n\n\nvoid foo();\n", actual[""]); + ASSERT_EQUALS("\n\n\n\n\n", actual[""]); } void undef9() {