diff --git a/lib/token.cpp b/lib/token.cpp index d36f4acdf..71f7e5d0c 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -225,6 +225,46 @@ static bool strisop(const char str[]) return false; } +static int multiComparePercent(const char * * haystack_p, + const char * needle, + bool emptyStringFound) +{ + const char *haystack = *haystack_p; + + if (haystack[0] == '%' && haystack[1] != '|') { + if (haystack[1] == 'o' && // "%op%" + haystack[2] == 'p' && + haystack[3] == '%') { + if (strisop(needle)) + return 1; + *haystack_p = haystack = haystack + 4; + } else if (haystack[1] == 'o' && // "%or%" + haystack[2] == 'r' && + haystack[3] == '%') { + if (*needle == '|') + return 1; + *haystack_p = haystack = haystack + 4; + } else if (haystack[1] == 'o' && // "%oror%" + haystack[2] == 'r' && + haystack[3] == 'o' && + haystack[4] == 'r' && + haystack[5] == '%') { + if (needle[0] == '|' && needle[1] == '|') + return 1; + *haystack_p = haystack = haystack + 6; + } + + if (*haystack == '|') + *haystack_p = haystack = haystack + 1; + else if (*haystack == ' ' || *haystack == '\0') + return emptyStringFound ? 0 : -1; + else + return -1; + } + + return 0xFFFF; +} + int Token::multiCompare(const char *haystack, const char *needle) { if (haystack[0] == '%' && haystack[1] == 'o') { @@ -271,6 +311,10 @@ int Token::multiCompare(const char *haystack, const char *needle) needlePointer = needle; ++haystack; + + int ret = multiComparePercent(&haystack, needle, emptyStringFound); + if (ret < 2) + return ret; } else if (*haystack == ' ' || *haystack == '\0') { if (needlePointer == needle) return 0; @@ -291,36 +335,9 @@ int Token::multiCompare(const char *haystack, const char *needle) ++haystack; - if (haystack[0] == '%' && haystack[1] != '|') { - if (haystack[1] == 'o' && // "%op%" - haystack[2] == 'p' && - haystack[3] == '%') { - if (strisop(needle)) - return 1; - haystack = haystack + 4; - } else if (haystack[1] == 'o' && // "%or%" - haystack[2] == 'r' && - haystack[3] == '%') { - if (*needle == '|') - return 1; - haystack = haystack + 4; - } else if (haystack[1] == 'o' && // "%oror%" - haystack[2] == 'r' && - haystack[3] == 'o' && - haystack[4] == 'r' && - haystack[5] == '%') { - if (needle[0] == '|' && needle[1] == '|') - return 1; - haystack = haystack + 6; - } - - if (*haystack == '|') - haystack++; - else if (*haystack == ' ' || *haystack == '\0') - return emptyStringFound ? 0 : -1; - else - return -1; - } + int ret = multiComparePercent(&haystack, needle, emptyStringFound); + if (ret < 2) + return ret; } } diff --git a/lib/token.h b/lib/token.h index a1425ea5a..76762ad66 100644 --- a/lib/token.h +++ b/lib/token.h @@ -113,6 +113,9 @@ public: * - "!!else" No tokens or any token that is not "else". * - "someRandomText" If token contains "someRandomText". * + * multi-compare patterns such as "int|void|char" can contain %or%, %oror% and %op% + * but it is not recommended to put such an %cmd% as the first pattern. + * * The patterns can be also combined to compare to multiple tokens at once * by separating tokens with a space, e.g. * ") const|void {" will return true if first token is ')' next token is either diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 9a08ed16a..2034af759 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1869,7 +1869,10 @@ bool Tokenizer::tokenize(std::istream &code, // token concatenation for (Token *tok = _tokens; tok; tok = tok->next()) { - if (Token::Match(tok, "%var%|%num% ## %var%|%num%")) { + // TODO: pattern should be "%var%|%num% ## %var%|%num%" + if (Token::Match(tok, "%any% ## %any%") && + (tok->isName() || tok->isNumber()) && + (tok->tokAt(2)->isName() || tok->tokAt(2)->isNumber())) { tok->str(tok->str() + tok->strAt(2)); tok->deleteNext(); tok->deleteNext(); diff --git a/test/testtoken.cpp b/test/testtoken.cpp index 93a4f4f26..07de35575 100644 --- a/test/testtoken.cpp +++ b/test/testtoken.cpp @@ -107,8 +107,7 @@ private: void multiCompare2() { // #3294 // Original pattern that failed: [[,(=<>+-*|&^] %num% [+-*/] %num% ]|,|)|;|=|%op% givenACodeSampleToTokenize toks("a == 1"); - // FIXME: Result should be true - ASSERT_EQUALS(false, Token::Match(toks.tokens(), "a =|%op%")); + ASSERT_EQUALS(true, Token::Match(toks.tokens(), "a =|%op%")); } void getStrLength() {