bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) { const char *p = pattern; bool firstpattern = true; while (*p) { // Skip spaces in pattern.. while (*p == ' ') ++p; // No token => Success! if (*p == 0) return true; if (!tok) { // If we have no tokens, pattern "!!else" should return true if (p[1] == '!' && p[0] == '!' && p[2] != '\0') { while (*p && *p != ' ') ++p; continue; } else return false; } // If we are in the first token, we skip all initial !! patterns if (firstpattern && !tok->previous() && tok->next() && p[1] == '!' && p[0] == '!' && p[2] != '\0') { while (*p && *p != ' ') ++p; continue; } firstpattern = false; // Compare the first character of the string for optimization reasons // before doing more detailed checks. bool patternUnderstood = false; if (p[0] == '%') { switch (p[1]) { case 'v': // TODO: %var% should match only for // variables that have varId != 0, but that needs a lot of // work, before that change can be made. // Any symbolname.. if (p[4] == '%') { // %var% if (!tok->isName()) return false; p += 5; patternUnderstood = true; } else { // %varid% if (varid == 0) { std::list<ErrorLogger::ErrorMessage::FileLocation> locationList; const ErrorLogger::ErrorMessage errmsg(locationList, Severity::error, "Internal error. Token::Match called with varid 0.", "cppcheckError", false); Check::reportError(errmsg); } if (tok->varId() != varid) return false; p += 7; patternUnderstood = true; } break; case 't': // Type (%type%) { if (!tok->isName()) return false; if (tok->varId() != 0) return false; if (tok->str() == "delete") return false; p += 6; patternUnderstood = true; } break; case 'a': // Accept any token (%any%) { p += 5; patternUnderstood = true; } break; case 'n': // Number (%num) { if (!tok->isNumber()) return false; p += 5; patternUnderstood = true; } break; case 's': // String (%str%) { if (tok->_str[0] != '\"') return false; p += 5; patternUnderstood = true; } break; case 'b': // Bool (%bool%) { if (!tok->isBoolean()) return false; p += 6; patternUnderstood = true; } break; case 'o': // Or (%or%) and Op (%op%) if (p[3] == '%') { patternUnderstood = true; // multicompare.. if (p[4] == '|') { int result = multiCompare(p, tok->str().c_str()); if (result == -1) return false; // No match while (*p && *p != ' ') p++; } // single compare.. else if (p[2] == 'r') { if (tok->str() != "|") return false; p += 4; } else if (p[3] == 'p') { if (!tok->isOp()) return false; p += 4; } else patternUnderstood = false; } // Oror (%oror%) else if (p[5] == '%') { // multicompare.. if (p[6] == '|') { int result = multiCompare(p, tok->str().c_str()); if (result == -1) return false; // No match while (*p && *p != ' ') p++; } // single compare.. else if (tok->str() != "||") return false; else p += 6; patternUnderstood = true; } break; default: if (firstWordEquals(p, tok->_str.c_str())) { p += tok->_str.length(); patternUnderstood = true; } break; } if (!patternUnderstood) { return false; } tok = tok->next(); continue; } // [.. => search for a one-character token.. else if (p[0] == '[' && chrInFirstWord(p, ']')) { if (tok->_str.length() != 1) return false; const char *temp = p + 1; bool chrFound = false; int count = 0; while (*temp && *temp != ' ') { if (*temp == ']') { ++count; ++temp; continue; } if (*temp == tok->_str[0]) { chrFound = true; break; } ++temp; } if (count > 1) { if (tok->_str[0] == ']') chrFound = true; } if (!chrFound) return false; } // Parse multi options, such as void|int|char (accept token which is one of these 3) else if (chrInFirstWord(p, '|') && (p[0] != '|' || firstWordLen(p) > 2)) { int res = multiCompare(p, tok->_str.c_str()); if (res == 0) { // Empty alternative matches, use the same token on next round while (*p && *p != ' ') ++p; continue; } else if (res == -1) { // No match return false; } } // Parse "not" options. Token can be anything except the given one else if (p[1] == '!' && p[0] == '!' && p[2] != '\0') { if (firstWordEquals(&(p[2]), tok->str().c_str()) == 0) return false; } else if (firstWordEquals(p, tok->_str.c_str()) != 0) { return false; } while (*p && *p != ' ') ++p; tok = tok->next(); } // The end of the pattern has been reached and nothing wrong has been found return true; }
bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) { const char *p = pattern; while (*p) { // Skip spaces in pattern.. while (*p == ' ') ++p; // No token => Success! if (*p == '\0') break; if (!tok) { // If we have no tokens, pattern "!!else" should return true if (p[0] == '!' && p[1] == '!' && p[2] != '\0') { while (*p && *p != ' ') ++p; continue; } else return false; } // [.. => search for a one-character token.. if (p[0] == '[' && chrInFirstWord(p, ']')) { if (tok->str().length() != 1) return false; const char *temp = p+1; bool chrFound = false; unsigned int count = 0; while (*temp && *temp != ' ') { if (*temp == ']') { ++count; } else if (*temp == tok->str()[0]) { chrFound = true; break; } ++temp; } if (count > 1 && tok->str()[0] == ']') chrFound = true; if (!chrFound) return false; p = temp; while (*p && *p != ' ') ++p; } // Parse "not" options. Token can be anything except the given one else if (p[0] == '!' && p[1] == '!' && p[2] != '\0') { p += 2; if (firstWordEquals(p, tok->str().c_str())) return false; while (*p && *p != ' ') ++p; } // Parse multi options, such as void|int|char (accept token which is one of these 3) else { int res = multiCompare(tok, p, varid); if (res == 0) { // Empty alternative matches, use the same token on next round while (*p && *p != ' ') ++p; continue; } else if (res == -1) { // No match return false; } } while (*p && *p != ' ') ++p; tok = tok->next(); } // The end of the pattern has been reached and nothing wrong has been found return true; }
bool Token::Match(const Token *tok, const char pattern[], unsigned int varid) { const char *p = pattern; bool firstpattern = true; bool first = true; while (*p) { if (!first) { while (*p && *p != ' ') ++p; } first = false; // Skip spaces in pattern.. while (*p == ' ') ++p; // No token => Success! if (*p == 0) return true; if (!tok) { // If we have no tokens, pattern "!!else" should return true if (p[1] == '!' && p[0] == '!' && p[2] != '\0') continue; else return false; } // If we are in the first token, we skip all initial !! patterns if (firstpattern && !tok->previous() && tok->next() && p[1] == '!' && p[0] == '!' && p[2] != '\0') continue; firstpattern = false; // Compare the first character of the string for optimization reasons // before doing more detailed checks. bool patternIdentified = false; if (p[0] == '%') { // Any symbolname.. if (firstWordEquals(p, "%var%") == 0) { if (!tok->isName()) return false; patternIdentified = true; } // Type.. if (firstWordEquals(p, "%type%") == 0) { if (!tok->isName()) return false; if (tok->str() == "delete") return false; patternIdentified = true; } // Accept any token else if (firstWordEquals(p, "%any%") == 0) { patternIdentified = true; } else if (firstWordEquals(p, "%varid%") == 0) { if (varid == 0) { std::cerr << "\n###### If you see this, there is a bug ######" << std::endl << "Token::Match(\"" << pattern << "\", 0)" << std::endl; } if (tok->varId() != varid) return false; patternIdentified = true; } else if (firstWordEquals(p, "%num%") == 0) { if (!tok->isNumber()) return false; patternIdentified = true; } else if (firstWordEquals(p, "%bool%") == 0) { if (!tok->isBoolean()) return false; patternIdentified = true; } else if (firstWordEquals(p, "%str%") == 0) { if (tok->_str[0] != '\"') return false; patternIdentified = true; } } if (patternIdentified) { // Pattern was identified already above. } // [.. => search for a one-character token.. else if (p[0] == '[' && chrInFirstWord(p, ']') && tok->_str.length() == 1) { const char *temp = p + 1; bool chrFound = false; int count = 0; while (*temp && *temp != ' ') { if (*temp == ']') { ++count; ++temp; continue; } if (*temp == tok->_str[0]) { chrFound = true; break; } ++temp; } if (count > 1) { if (tok->_str[0] == ']') chrFound = true; } if (!chrFound) return false; } // Parse multi options, such as void|int|char (accept token which is one of these 3) else if (chrInFirstWord(p, '|') && (p[0] != '|' || firstWordLen(p) > 2)) { int res = multiCompare(p, tok->_str.c_str()); if (res == 0) { // Empty alternative matches, use the same token on next round continue; } else if (res == -1) { // No match return false; } } // Parse "not" options. Token can be anything except the given one else if (p[1] == '!' && p[0] == '!' && p[2] != '\0') { if (firstWordEquals(&(p[2]), tok->str().c_str()) == 0) return false; } else if (firstWordEquals(p, tok->_str.c_str()) != 0) return false; tok = tok->next(); } // The end of the pattern has been reached and nothing wrong has been found return true; }