📄 tokenize.cpp
字号:
while (tok2) { if (strchr("{(", tok2->aaaa0())) { ++parlevel; } else if (strchr("})", tok2->aaaa0())) { if (parlevel < 0) break; --parlevel; } else if (parlevel == 0 && strchr(";,", tok2->aaaa0())) { // "type var =" => "type var; var =" Token *VarTok = type0->tokAt(typelen); if (VarTok->aaaa0() == '*') VarTok = VarTok->next(); InsertTokens(eq, VarTok, 2); eq->str(";"); // "= x, " => "= x; type " if (tok2->str() == ",") { tok2->str(";"); InsertTokens(tok2, type0, typelen); } break; } tok2 = tok2->next(); } } } } // In case variable declarations have been updated... setVarId(); // Replace NULL with 0.. for (Token *tok = _tokens; tok; tok = tok->next()) { if (tok->str() == "NULL") tok->str("0"); } // Replace pointer casts of 0.. "(char *)0" => "0" for (Token *tok = _tokens; tok; tok = tok->next()) { if (Token::Match(tok->next(), "( %type% * ) 0") || Token::Match(tok->next(), "( %type% %type% * ) 0")) { while (!Token::simpleMatch(tok->next(), "0")) tok->deleteNext(); } } simplifyIfAddBraces(); simplifyFunctionParameters(); elseif(); for (Token *tok = _tokens; tok; tok = tok->next()) { if (Token::Match(tok, "case %any% : %var%")) tok->next()->next()->insertToken(";"); if (Token::Match(tok, "default : %var%")) tok->next()->insertToken(";"); } bool modified = true; while (modified) { modified = false; modified |= simplifyConditions(); modified |= simplifyFunctionReturn(); modified |= simplifyKnownVariables(); modified |= removeReduntantConditions(); modified |= simplifyRedundantParanthesis(); modified |= simplifyCalculations(); }}//---------------------------------------------------------------------------const Token *Tokenizer::findClosing(const Token *tok, const char *start, const char *end){ if (!tok) return 0; // Find the closing "}" int indentLevel = 0; for (const Token *closing = tok->next(); closing; closing = closing->next()) { if (closing->str() == start) { ++indentLevel; continue; } if (closing->str() == end) --indentLevel; if (indentLevel >= 0) continue; // Closing } is found. return closing; } return 0;}bool Tokenizer::removeReduntantConditions(){ bool ret = false; for (Token *tok = _tokens; tok; tok = tok->next()) { if (!Token::simpleMatch(tok, "if")) continue; if (!Token::Match(tok->tokAt(1), "( %bool% ) {")) continue; // Find matching else const Token *elseTag = 0; // Find the closing "}" elseTag = Tokenizer::findClosing(tok->tokAt(4), "{", "}"); if (elseTag) elseTag = elseTag->next(); bool boolValue = false; if (tok->tokAt(2)->str() == "true") boolValue = true; // Handle if with else if (elseTag && elseTag->str() == "else") { if (Token::simpleMatch(elseTag->next(), "if")) { // Handle "else if" if (boolValue == false) { // Convert "if( false ) {aaa;} else if() {bbb;}" => "if() {bbb;}" Token::eraseTokens(tok, elseTag->tokAt(2)); ret = true; } else { // Keep first if, remove every else if and else after it const Token *lastTagInIf = elseTag->tokAt(2); while (lastTagInIf) { if (lastTagInIf->str() == "(") { lastTagInIf = Tokenizer::findClosing(lastTagInIf, "(", ")"); lastTagInIf = lastTagInIf->next(); } lastTagInIf = Tokenizer::findClosing(lastTagInIf, "{", "}"); lastTagInIf = lastTagInIf->next(); if (!Token::simpleMatch(lastTagInIf, "else")) break; lastTagInIf = lastTagInIf->next(); if (Token::simpleMatch(lastTagInIf, "if")) lastTagInIf = lastTagInIf->next(); } Token::eraseTokens(elseTag->previous(), lastTagInIf); ret = true; } } else { // Handle else if (boolValue == false) { // Convert "if( false ) {aaa;} else {bbb;}" => "{bbb;}" or ";{bbb;}" if (tok->previous()) tok = tok->previous(); else tok->str(";"); Token::eraseTokens(tok, elseTag->tokAt(1)); } else { if (Token::simpleMatch(elseTag->tokAt(1), "{")) { // Convert "if( true ) {aaa;} else {bbb;}" => "{aaa;}" const Token *end = Tokenizer::findClosing(elseTag->tokAt(1), "{", "}"); if (!end) { // Possibly syntax error in code return false; } // Remove the "else { aaa; }" Token::eraseTokens(elseTag->previous(), end->tokAt(1)); } // Remove "if( true )" if (tok->previous()) tok = tok->previous(); else tok->str(";"); Token::eraseTokens(tok, tok->tokAt(5)); } ret = true; } } // Handle if without else else { if (boolValue == false) { // Remove if and its content if (tok->previous()) tok = tok->previous(); else tok->str(";"); Token::eraseTokens(tok, elseTag); } else { // convert "if( true ) {aaa;}" => "{aaa;}" if (tok->previous()) tok = tok->previous(); else tok->str(";"); Token::eraseTokens(tok, tok->tokAt(5)); } ret = true; } } return ret;}bool Tokenizer::simplifyIfAddBraces(){ bool ret = false; for (Token *tok = _tokens; tok; tok = tok ? tok->next() : NULL) { if (Token::Match(tok, "if|for|while (")) { // Goto the ending ')' int parlevel = 1; tok = tok->next(); while (parlevel >= 1 && (tok = tok->next())) { if (tok->str() == "(") ++parlevel; else if (tok->str() == ")") --parlevel; } // ')' should be followed by '{' if (!tok || Token::simpleMatch(tok, ") {")) continue; } else if (tok->str() == "else") { // An else followed by an if or brace don't need to be processed further if (Token::Match(tok, "else if|{")) continue; } else { continue; } // insert open brace.. tok->insertToken("{"); tok = tok->next(); // insert close brace.. // In most cases it would work to just search for the next ';' and insert a closing brace after it. // But here are special cases.. // * if (cond) for (;;) break; // * if (cond1) if (cond2) { } int parlevel = 0; int indentlevel = 0; while ((tok = tok->next()) != NULL) { if (tok->str() == "{") ++indentlevel; else if (tok->str() == "}") { --indentlevel; if (indentlevel == 0) break; } else if (tok->str() == "(") ++parlevel; else if (tok->str() == ")") --parlevel; else if (indentlevel == 0 && parlevel == 0 && tok->str() == ";") break; } if (tok) { tok->insertToken("}"); ret = true; } } return ret;}bool Tokenizer::simplifyConditions(){ bool ret = false; for (Token *tok = _tokens; tok; tok = tok->next()) { if (Token::simpleMatch(tok, "( true &&") || Token::simpleMatch(tok, "&& true &&") || Token::simpleMatch(tok->next(), "&& true )")) { tok->deleteNext(); tok->deleteNext(); ret = true; } else if (Token::simpleMatch(tok, "( false ||") || Token::simpleMatch(tok, "|| false ||") || Token::simpleMatch(tok->next(), "|| false )")) { tok->deleteNext(); tok->deleteNext(); ret = true; } // Change numeric constant in condition to "true" or "false" if (Token::Match(tok, "if|while ( %num%") && (tok->tokAt(3)->str() == ")" || tok->tokAt(3)->str() == "||" || tok->tokAt(3)->str() == "&&")) { tok->next()->next()->str((tok->tokAt(2)->str() != "0") ? "true" : "false"); ret = true; } Token *tok2 = tok->tokAt(2); if (tok2 && (tok->str() == "&&" || tok->str() == "||") && Token::Match(tok->next(), "%num%") && (tok2->str() == ")" || tok2->str() == "&&" || tok2->str() == "||")) { tok->next()->str((tok->next()->str() != "0") ? "true" : "false"); ret = true; } // Reduce "(%num% == %num%)" => "(true)"/"(false)" const Token *tok4 = tok->tokAt(4); if (! tok4) break; if ((tok->str() == "&&" || tok->str() == "||" || tok->str() == "(") && Token::Match(tok->tokAt(1), "%num% %any% %num%") && (tok4->str() == "&&" || tok4->str() == "||" || tok4->str() == ")")) { double op1 = (strstr(tok->strAt(1), "0x")) ? std::strtol(tok->strAt(1), 0, 16) : std::atof(tok->strAt(1)); double op2 = (strstr(tok->strAt(3), "0x")) ? std::strtol(tok->strAt(3), 0, 16) : std::atof(tok->strAt(3)); std::string cmp = tok->strAt(2); bool result = false; if (cmp == "==") result = (op1 == op2); else if (cmp == "!=") result = (op1 != op2); else if (cmp == ">=") result = (op1 >= op2); else if (cmp == ">") result = (op1 > op2); else if (cmp == "<=") result = (op1 <= op2); else if (cmp == "<") result = (op1 < op2); else cmp = ""; if (! cmp.empty()) { tok = tok->next(); tok->deleteNext(); tok->deleteNext(); tok->str(result ? "true" : "false"); ret = true; } } } return ret;}bool Tokenizer::simplifyCasts(){ bool ret = false; for (Token *tok = _tokens; tok; tok = tok->next()) { if (!tok->isName() && Token::Match(tok->next(), "( %type% * )")) { tok->deleteNext(); tok->deleteNext(); tok->deleteNext(); tok->deleteNext(); ret = true; } else if (Token::Match(tok->next(), "dynamic_cast|reinterpret_cast|const_cast|static_cast <")) { while (tok->next() && tok->next()->str() != ">") tok->deleteNext(); tok->deleteNext(); tok->deleteNext(); Token *tok2 = tok; int parlevel = 0; while (tok2->next() && parlevel >= 0) { tok2 = tok2->next(); if (Token::simpleMatch(tok2->next(), "(")) ++parlevel; else if (Token::simpleMatch(tok2->next(), ")")) --parlevel; } if (tok2->next()) tok2->deleteNext(); ret = true; } } return ret;}bool Tokenizer::simplifyFunctionParameters(){ bool ret = false; int indentlevel = 0; for (Token *tok = _tokens; tok; tok = tok->next()) { if (tok->str() == "{") ++indentlevel; else if (tok->str() == "}") --indentlevel; // Find the function e.g. foo( x ) or foo( x, y ) else if (indentlevel == 0 && Token::Match(tok, "%var% ( %var% [,)]")) { // We have found old style function, now we need to change it // Get list of argument names std::map<std::string, Token*> argumentNames; bool bailOut = false; for (tok = tok->tokAt(2); tok; tok = tok->tokAt(2)) { if (!Token::Match(tok, "%var% [,)]")) { bailOut = true; break; } argumentNames[tok->str()] = tok; if (tok->next()->str() == ")") { tok = tok->tokAt(2); break; } } if (bailOut) { continue; } Token *start = tok; while (tok && tok->str() != "{")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -