Fixed #1060 (Preprocessor: wrong define handling)
This commit is contained in:
parent
91114c50d2
commit
e52fb36c5c
|
@ -593,8 +593,16 @@ std::string Preprocessor::getdef(std::string line, bool def)
|
|||
line.erase(0, line.find(" "));
|
||||
|
||||
// Remove all spaces.
|
||||
while (line.find(" ") != std::string::npos)
|
||||
line.erase(line.find(" "), 1);
|
||||
std::string::size_type pos = 0;
|
||||
while ((pos = line.find(" ", pos)) != std::string::npos)
|
||||
{
|
||||
const char chprev = (pos > 0) ? line[pos-1] : 0;
|
||||
const char chnext = (pos + 1 < line.length()) ? line[pos+1] : 0;
|
||||
if (std::isalnum(chprev) && std::isalnum(chnext))
|
||||
++pos;
|
||||
else
|
||||
line.erase(pos, 1);
|
||||
}
|
||||
|
||||
// The remaining string is our result.
|
||||
return line;
|
||||
|
@ -870,12 +878,37 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|||
void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &variables, std::string &condition)
|
||||
{
|
||||
Tokenizer tokenizer;
|
||||
std::istringstream istr(condition.c_str());
|
||||
std::istringstream istr(("(" + condition + ")").c_str());
|
||||
tokenizer.tokenize(istr, "");
|
||||
|
||||
// replace variable names with values..
|
||||
for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next())
|
||||
{
|
||||
if (!tok->isName())
|
||||
continue;
|
||||
|
||||
if (Token::Match(tok, "defined ( %var% )"))
|
||||
{
|
||||
if (variables.find(tok->strAt(2)) == variables.end())
|
||||
tok->str("0");
|
||||
else
|
||||
tok->str("1");
|
||||
tok->deleteNext();
|
||||
tok->deleteNext();
|
||||
tok->deleteNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "defined %var%"))
|
||||
{
|
||||
if (variables.find(tok->strAt(1)) == variables.end())
|
||||
tok->str("0");
|
||||
else
|
||||
tok->str("1");
|
||||
tok->deleteNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::map<std::string, std::string>::const_iterator it = variables.find(tok->str());
|
||||
if (it != variables.end())
|
||||
{
|
||||
|
@ -889,28 +922,13 @@ void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &v
|
|||
// simplify calculations..
|
||||
tokenizer.simplifyCalculations();
|
||||
|
||||
if (!tokenizer.tokens()->tokAt(3) && Token::Match(tokenizer.tokens(), "%num% ==|!=|<=|>=|<|> %num%"))
|
||||
{
|
||||
const std::string &op1(tokenizer.tokens()->str());
|
||||
const std::string &cmp(tokenizer.tokens()->tokAt(1)->str());
|
||||
const std::string &op2(tokenizer.tokens()->tokAt(2)->str());
|
||||
if (cmp == "==")
|
||||
condition = (op1 == op2) ? "1" : "0";
|
||||
else if (cmp == "!=")
|
||||
condition = (op1 != op2) ? "1" : "0";
|
||||
else if (cmp == "<=")
|
||||
condition = (op1 <= op2) ? "1" : "0";
|
||||
else if (cmp == ">=")
|
||||
condition = (op1 >= op2) ? "1" : "0";
|
||||
else if (cmp == "<")
|
||||
condition = (op1 < op2) ? "1" : "0";
|
||||
else if (cmp == ">")
|
||||
condition = (op1 > op2) ? "1" : "0";
|
||||
}
|
||||
if (Token::simpleMatch(tokenizer.tokens(), "( 1 )") ||
|
||||
Token::simpleMatch(tokenizer.tokens(), "( 1 ||"))
|
||||
condition = "1";
|
||||
else if (Token::simpleMatch(tokenizer.tokens(), "( 0 )"))
|
||||
condition = "0";
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def)
|
||||
{
|
||||
//std::cout << "cfg: \"" << cfg << "\" ";
|
||||
|
@ -921,68 +939,12 @@ bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg,
|
|||
if (cfg.find(def) != cfg.end())
|
||||
return true;
|
||||
|
||||
for (std::string::size_type pos = def.find("defined("); pos != std::string::npos; pos = def.find("defined(", pos + 1))
|
||||
{
|
||||
// The character before "defined" must not be '_' or alphanumeric
|
||||
unsigned char chPrev = (pos > 0) ? def[pos-1] : ' ';
|
||||
if (chPrev == '_' || std::isalnum(chPrev))
|
||||
continue;
|
||||
|
||||
// Extract the parameter..
|
||||
std::string::size_type pos2 = def.find(")", pos);
|
||||
if (pos2 == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string::size_type pos1 = pos + 8;
|
||||
const std::string par(def.substr(pos1, pos2 - pos1));
|
||||
const bool isdefined(cfg.find(par) != cfg.end());
|
||||
|
||||
def.erase(pos, pos2 + 1 - pos);
|
||||
def.insert(pos, isdefined ? "1" : "0");
|
||||
}
|
||||
|
||||
if (def.find("1||") != std::string::npos || def.find("||1") != std::string::npos)
|
||||
return true;
|
||||
|
||||
while (def.find("1&&") != std::string::npos)
|
||||
{
|
||||
def.erase(def.find("1&&"), 3);
|
||||
}
|
||||
|
||||
//std::cout << " => \"" << def << "\"" << std::endl;
|
||||
|
||||
if (def == "0")
|
||||
return false;
|
||||
|
||||
if (def == "1")
|
||||
return true;
|
||||
|
||||
/*
|
||||
if (cfg.empty())
|
||||
return false;
|
||||
|
||||
// remove the define values
|
||||
while (cfg.find("=") != std::string::npos)
|
||||
{
|
||||
std::string::size_type pos1 = cfg.find("=");
|
||||
std::string::size_type pos2 = cfg.find(";", pos1);
|
||||
if (pos2 == std::string::npos)
|
||||
cfg.erase(pos1);
|
||||
else
|
||||
cfg.erase(pos1, pos2 - pos1);
|
||||
}
|
||||
|
||||
while (! cfg.empty())
|
||||
{
|
||||
if (cfg.find(";") == std::string::npos)
|
||||
return bool(cfg == def);
|
||||
std::string _cfg = cfg.substr(0, cfg.find(";"));
|
||||
if (_cfg == def)
|
||||
return true;
|
||||
cfg.erase(0, cfg.find(";") + 1);
|
||||
}
|
||||
*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1116,15 +1078,15 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg,
|
|||
if (match && line.compare(0, 6, "#error") == 0)
|
||||
return "";
|
||||
|
||||
if (!match && line.find("#define") == 0)
|
||||
if (!match && line.compare(0, 8, "#define ") == 0)
|
||||
{
|
||||
// Remove define that is not part of this configuration
|
||||
line = "";
|
||||
}
|
||||
else if (line.find("#file \"") == 0 ||
|
||||
line.find("#endfile") == 0 ||
|
||||
line.find("#define") == 0 ||
|
||||
line.find("#undef") == 0)
|
||||
else if (line.compare(0, 7, "#file \"") == 0 ||
|
||||
line.compare(0, 8, "#endfile") == 0 ||
|
||||
line.compare(0, 8, "#define ") == 0 ||
|
||||
line.compare(0, 6, "#undef") == 0)
|
||||
{
|
||||
// We must not remove #file tags or line numbers
|
||||
// are corrupted. File tags are removed by the tokenizer.
|
||||
|
|
|
@ -3900,6 +3900,48 @@ bool Tokenizer::simplifyCalculations()
|
|||
tok->deleteNext();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::simpleMatch(tok->previous(), "( 0 ||") ||
|
||||
Token::simpleMatch(tok, "|| 0 )") ||
|
||||
Token::simpleMatch(tok->previous(), "( 1 &&") ||
|
||||
Token::simpleMatch(tok, "&& 1 )"))
|
||||
{
|
||||
tok->deleteThis();
|
||||
tok->deleteThis();
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "%num% ==|!=|<=|>=|<|> %num%") &&
|
||||
MathLib::isInt(tok->str()) &&
|
||||
MathLib::isInt(tok->tokAt(2)->str()))
|
||||
{
|
||||
const std::string prev(tok->previous() ? tok->strAt(-1) : "");
|
||||
const std::string after(tok->tokAt(3) ? tok->strAt(3) : "");
|
||||
if ((prev == "(" || prev == "&&" || prev == "||") && (after == ")" || after == "&&" || after == "||"))
|
||||
{
|
||||
const int op1(MathLib::toLongNumber(tok->str()));
|
||||
const std::string &cmp(tok->next()->str());
|
||||
const int op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||
|
||||
std::string result;
|
||||
|
||||
if (cmp == "==")
|
||||
result = (op1 == op2) ? "1" : "0";
|
||||
else if (cmp == "!=")
|
||||
result = (op1 != op2) ? "1" : "0";
|
||||
else if (cmp == "<=")
|
||||
result = (op1 <= op2) ? "1" : "0";
|
||||
else if (cmp == ">=")
|
||||
result = (op1 >= op2) ? "1" : "0";
|
||||
else if (cmp == "<")
|
||||
result = (op1 < op2) ? "1" : "0";
|
||||
else if (cmp == ">")
|
||||
result = (op1 > op2) ? "1" : "0";
|
||||
|
||||
tok->str(result);
|
||||
tok->deleteNext();
|
||||
tok->deleteNext();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -594,6 +594,18 @@ private:
|
|||
|
||||
void match_cfg_def()
|
||||
{
|
||||
{
|
||||
std::map<std::string, std::string> cfg;
|
||||
ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A>1||defined(B)"));
|
||||
}
|
||||
|
||||
{
|
||||
std::map<std::string, std::string> cfg;
|
||||
cfg["A"] = "";
|
||||
cfg["B"] = "";
|
||||
ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "defined(A)&&defined(B)"));
|
||||
}
|
||||
|
||||
{
|
||||
std::map<std::string, std::string> cfg;
|
||||
cfg["ABC"] = "";
|
||||
|
|
Loading…
Reference in New Issue