From 12f3ac5a2fd77472ed4848bd39dfb47f9f9097b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 18 Jun 2009 23:09:11 +0200 Subject: [PATCH] Preprocessor: better handling of "..." and "__VA_ARGS__" in macros --- src/preprocessor.cpp | 42 ++++++++++++++++++++++++++++++++++----- test/testpreprocessor.cpp | 8 +++++++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/preprocessor.cpp b/src/preprocessor.cpp index b1c7e724f..ed56198d6 100644 --- a/src/preprocessor.cpp +++ b/src/preprocessor.cpp @@ -892,6 +892,9 @@ public: _params.push_back(tok->str()); } } + + else if (Token::Match(tokens(), "%var% ( . . . )")) + _variadic = true; } } @@ -917,7 +920,36 @@ public: bool code(const std::vector ¶ms2, std::string ¯ocode) const { - if (_params.empty()) + if (_params.empty() && _variadic) + { + std::string s; + for (unsigned int i = 0; i < params2.size(); ++i) + { + if (i > 0) + s += ","; + s += params2[i]; + } + + macrocode = _macro.substr(1 + _macro.find(")")); + if (macrocode.empty()) + return true; + + std::string::size_type pos = 0; + // Remove leading spaces + if ((pos = macrocode.find_first_not_of(" ")) > 0) + macrocode.erase(0,pos); + // Remove ending newline + if ((pos = macrocode.find_first_of("\r\n")) != std::string::npos) + macrocode.erase(pos); + // Replace "__VA_ARGS__" with parameters + while ((pos = macrocode.find("__VA_ARGS__")) != std::string::npos) + { + macrocode.erase(pos, 11); + macrocode.insert(pos, s); + } + } + + else if (_params.empty()) { std::string::size_type pos = _macro.find(" "); if (pos == std::string::npos) @@ -1101,11 +1133,11 @@ std::string Preprocessor::expandMacros(std::string code, const std::string &file if (code.substr(pos1, macro.name().length()) != macro.name()) continue; - // Previous char must not be alphanumeric or '_' + // Previous char must not be alphanumeric nor '_' if (pos1 != 0 && (std::isalnum(code[pos1-1]) || code[pos1-1] == '_')) continue; - // The char after the macroname must not be alphanumeric or '_' + // The char after the macroname must not be alphanumeric nor '_' if (pos1 + macro.name().length() < code.length()) { std::string::size_type pos2 = pos1 + macro.name().length(); @@ -1120,7 +1152,7 @@ std::string Preprocessor::expandMacros(std::string code, const std::string &file unsigned int numberOfNewlines = 0; - if (macro.params().size()) + if (macro.variadic() || macro.params().size()) { if (code[pos2] == ' ') pos2++; @@ -1215,7 +1247,7 @@ std::string Preprocessor::expandMacros(std::string code, const std::string &file const std::string macrocode(std::string(numberOfNewlines, '\n') + tempMacro); // Insert macro code.. - if (!macro.params().empty()) + if (macro.variadic() || !macro.params().empty()) ++pos2; code.erase(pos1, pos2 - pos1); diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 29611a7fc..73d5470ab 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -114,6 +114,7 @@ private: TEST_CASE(preprocessor_include_in_str); TEST_CASE(fmt1); TEST_CASE(fmt2); + TEST_CASE(fmt3); TEST_CASE(multi_character_character); TEST_CASE(stringify); @@ -820,7 +821,12 @@ private: ASSERT_EQUALS("\nprintf(\"hello\");", actual); } - + void fmt3() + { + const char filedata[] = "#define FRED(...) { fred(__VA_ARGS__); }\n" + "FRED(123)"; + ASSERT_EQUALS("\n{ fred(123); }", OurPreprocessor::expandMacros(filedata)); + }