|
|
@ -38,7 +38,7 @@ bool Preprocessor::missingSystemIncludeFlag;
|
|
|
|
|
|
|
|
|
|
|
|
char Preprocessor::macroChar = char(1);
|
|
|
|
char Preprocessor::macroChar = char(1);
|
|
|
|
|
|
|
|
|
|
|
|
Preprocessor::Preprocessor(Settings *settings, ErrorLogger *errorLogger) : _settings(settings), _errorLogger(errorLogger)
|
|
|
|
Preprocessor::Preprocessor(Settings& settings, ErrorLogger *errorLogger) : _settings(settings), _errorLogger(errorLogger)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -183,10 +183,10 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename)
|
|
|
|
bom = 0; // allowed boms are 0/0xfffe/0xfeff
|
|
|
|
bom = 0; // allowed boms are 0/0xfffe/0xfeff
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->checkConfiguration)
|
|
|
|
if (_settings.checkConfiguration)
|
|
|
|
return readpreprocessor(istr,bom);
|
|
|
|
return readpreprocessor(istr,bom);
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------
|
|
|
|
// ------------------------------------------------------------------------------------------
|
|
|
@ -251,27 +251,27 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename)
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Remove all comments..
|
|
|
|
// Remove all comments..
|
|
|
|
result = removeComments(result, filename);
|
|
|
|
result = removeComments(result, filename);
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------
|
|
|
|
// ------------------------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Clean up all preprocessor statements
|
|
|
|
// Clean up all preprocessor statements
|
|
|
|
result = preprocessCleanupDirectives(result);
|
|
|
|
result = preprocessCleanupDirectives(result);
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------
|
|
|
|
// ------------------------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Clean up preprocessor #if statements with Parentheses
|
|
|
|
// Clean up preprocessor #if statements with Parentheses
|
|
|
|
result = removeParentheses(result);
|
|
|
|
result = removeParentheses(result);
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
// Remove '#if 0' blocks
|
|
|
|
// Remove '#if 0' blocks
|
|
|
|
if (result.find("#if 0\n") != std::string::npos)
|
|
|
|
if (result.find("#if 0\n") != std::string::npos)
|
|
|
|
result = removeIf0(result);
|
|
|
|
result = removeIf0(result);
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
@ -476,7 +476,7 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
unsigned char previous = 0;
|
|
|
|
unsigned char previous = 0;
|
|
|
|
bool inPreprocessorLine = false;
|
|
|
|
bool inPreprocessorLine = false;
|
|
|
|
std::vector<std::string> suppressionIDs;
|
|
|
|
std::vector<std::string> suppressionIDs;
|
|
|
|
const bool detectFallThroughComments = _settings && _settings->experimental && _settings->isEnabled("style");
|
|
|
|
const bool detectFallThroughComments = _settings.experimental && _settings.isEnabled("style");
|
|
|
|
bool fallThroughComment = false;
|
|
|
|
bool fallThroughComment = false;
|
|
|
|
|
|
|
|
|
|
|
|
for (std::string::size_type i = hasbom(str) ? 3U : 0U; i < str.length(); ++i) {
|
|
|
|
for (std::string::size_type i = hasbom(str) ? 3U : 0U; i < str.length(); ++i) {
|
|
|
@ -491,21 +491,9 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
writeError(filename, lineno, _errorLogger, "unhandledCharacters", errmsg.str());
|
|
|
|
writeError(filename, lineno, _errorLogger, "unhandledCharacters", errmsg.str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
if (str.compare(i, 7, "#error ") == 0 || str.compare(i, 9, "#warning ") == 0) {
|
|
|
|
|
|
|
|
if (str.compare(i, 6, "#error") == 0)
|
|
|
|
|
|
|
|
code << "#error";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = str.find("\n", i);
|
|
|
|
|
|
|
|
if (i == std::string::npos)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--i;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// First skip over any whitespace that may be present
|
|
|
|
// First skip over any whitespace that may be present
|
|
|
|
if (std::isspace(ch)) {
|
|
|
|
if (std::isspace(ch)) {
|
|
|
|
if (ch == ' ' && previous == ' ') {
|
|
|
|
if (ch == ' ' && previous == ' ') {
|
|
|
@ -530,6 +518,18 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((ch == '#') && (str.compare(i, 7, "#error ") == 0 || str.compare(i, 9, "#warning ") == 0)) {
|
|
|
|
|
|
|
|
if (str.compare(i, 6, "#error") == 0)
|
|
|
|
|
|
|
|
code << "#error";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i = str.find("\n", i);
|
|
|
|
|
|
|
|
if (i == std::string::npos)
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--i;
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Remove comments..
|
|
|
|
// Remove comments..
|
|
|
|
if (str.compare(i, 2, "//") == 0) {
|
|
|
|
if (str.compare(i, 2, "//") == 0) {
|
|
|
|
const std::size_t commentStart = i + 2;
|
|
|
|
const std::size_t commentStart = i + 2;
|
|
|
@ -538,7 +538,7 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
std::string comment(str, commentStart, i - commentStart);
|
|
|
|
std::string comment(str, commentStart, i - commentStart);
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->_inlineSuppressions) {
|
|
|
|
if (_settings._inlineSuppressions) {
|
|
|
|
std::istringstream iss(comment);
|
|
|
|
std::istringstream iss(comment);
|
|
|
|
std::string word;
|
|
|
|
std::string word;
|
|
|
|
iss >> word;
|
|
|
|
iss >> word;
|
|
|
@ -575,7 +575,7 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
fallThroughComment = true;
|
|
|
|
fallThroughComment = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->_inlineSuppressions) {
|
|
|
|
if (_settings._inlineSuppressions) {
|
|
|
|
std::istringstream iss(comment);
|
|
|
|
std::istringstream iss(comment);
|
|
|
|
std::string word;
|
|
|
|
std::string word;
|
|
|
|
iss >> word;
|
|
|
|
iss >> word;
|
|
|
@ -617,15 +617,13 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
|
|
|
|
|
|
|
|
// Add any pending inline suppressions that have accumulated.
|
|
|
|
// Add any pending inline suppressions that have accumulated.
|
|
|
|
if (!suppressionIDs.empty()) {
|
|
|
|
if (!suppressionIDs.empty()) {
|
|
|
|
if (_settings != nullptr) {
|
|
|
|
|
|
|
|
// Add the suppressions.
|
|
|
|
// Add the suppressions.
|
|
|
|
for (std::size_t j = 0; j < suppressionIDs.size(); ++j) {
|
|
|
|
for (std::size_t j = 0; j < suppressionIDs.size(); ++j) {
|
|
|
|
const std::string errmsg(_settings->nomsg.addSuppression(suppressionIDs[j], filename, lineno));
|
|
|
|
const std::string errmsg(_settings.nomsg.addSuppression(suppressionIDs[j], filename, lineno));
|
|
|
|
if (!errmsg.empty()) {
|
|
|
|
if (!errmsg.empty()) {
|
|
|
|
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
|
|
|
|
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
suppressionIDs.clear();
|
|
|
|
suppressionIDs.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -645,12 +643,11 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
|
|
|
|
|
|
|
|
// Add any pending inline suppressions that have accumulated.
|
|
|
|
// Add any pending inline suppressions that have accumulated.
|
|
|
|
if (!suppressionIDs.empty()) {
|
|
|
|
if (!suppressionIDs.empty()) {
|
|
|
|
if (_settings != nullptr) {
|
|
|
|
|
|
|
|
// Relative filename
|
|
|
|
// Relative filename
|
|
|
|
std::string relativeFilename(filename);
|
|
|
|
std::string relativeFilename(filename);
|
|
|
|
if (_settings->_relativePaths) {
|
|
|
|
if (_settings._relativePaths) {
|
|
|
|
for (std::size_t j = 0U; j < _settings->_basePaths.size(); ++j) {
|
|
|
|
for (std::size_t j = 0U; j < _settings._basePaths.size(); ++j) {
|
|
|
|
const std::string bp = _settings->_basePaths[j] + "/";
|
|
|
|
const std::string bp = _settings._basePaths[j] + "/";
|
|
|
|
if (relativeFilename.compare(0,bp.size(),bp)==0) {
|
|
|
|
if (relativeFilename.compare(0,bp.size(),bp)==0) {
|
|
|
|
relativeFilename = relativeFilename.substr(bp.size());
|
|
|
|
relativeFilename = relativeFilename.substr(bp.size());
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -659,12 +656,11 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
|
|
|
|
|
|
|
|
|
|
|
|
// Add the suppressions.
|
|
|
|
// Add the suppressions.
|
|
|
|
for (std::size_t j = 0; j < suppressionIDs.size(); ++j) {
|
|
|
|
for (std::size_t j = 0; j < suppressionIDs.size(); ++j) {
|
|
|
|
const std::string errmsg(_settings->nomsg.addSuppression(suppressionIDs[j], relativeFilename, lineno));
|
|
|
|
const std::string errmsg(_settings.nomsg.addSuppression(suppressionIDs[j], relativeFilename, lineno));
|
|
|
|
if (!errmsg.empty()) {
|
|
|
|
if (!errmsg.empty()) {
|
|
|
|
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
|
|
|
|
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
suppressionIDs.clear();
|
|
|
|
suppressionIDs.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -789,7 +785,7 @@ std::string Preprocessor::removeParentheses(const std::string &str)
|
|
|
|
std::ostringstream ret;
|
|
|
|
std::ostringstream ret;
|
|
|
|
std::string line;
|
|
|
|
std::string line;
|
|
|
|
while (std::getline(istr, line)) {
|
|
|
|
while (std::getline(istr, line)) {
|
|
|
|
if (line.compare(0, 3, "#if") == 0 || line.compare(0, 5, "#elif") == 0) {
|
|
|
|
if ((line[0] == '#') && (line.compare(0, 3, "#if") == 0 || line.compare(0, 5, "#elif") == 0)) {
|
|
|
|
std::string::size_type pos;
|
|
|
|
std::string::size_type pos;
|
|
|
|
pos = 0;
|
|
|
|
pos = 0;
|
|
|
|
while ((pos = line.find(" (", pos)) != std::string::npos)
|
|
|
|
while ((pos = line.find(" (", pos)) != std::string::npos)
|
|
|
@ -868,7 +864,7 @@ void Preprocessor::preprocess(std::istream &istr, std::map<std::string, std::str
|
|
|
|
std::string data;
|
|
|
|
std::string data;
|
|
|
|
preprocess(istr, data, configs, filename, includePaths);
|
|
|
|
preprocess(istr, data, configs, filename, includePaths);
|
|
|
|
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) {
|
|
|
|
for (std::list<std::string>::const_iterator it = configs.begin(); it != configs.end(); ++it) {
|
|
|
|
if (_settings && (_settings->userUndefs.find(*it) == _settings->userUndefs.end())) {
|
|
|
|
if (_settings.userUndefs.find(*it) == _settings.userUndefs.end()) {
|
|
|
|
result[ *it ] = getcode(data, *it, filename);
|
|
|
|
result[ *it ] = getcode(data, *it, filename);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -909,7 +905,7 @@ void Preprocessor::replaceIfDefined(std::string &str) const
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++pos;
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -925,7 +921,7 @@ void Preprocessor::replaceIfDefined(std::string &str) const
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++pos;
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -940,7 +936,7 @@ void Preprocessor::replaceIfDefined(std::string &str) const
|
|
|
|
}
|
|
|
|
}
|
|
|
|
++pos;
|
|
|
|
++pos;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -963,9 +959,8 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
|
|
|
|
|
|
|
|
|
|
|
|
processedFile = read(srcCodeStream, filename);
|
|
|
|
processedFile = read(srcCodeStream, filename);
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings) {
|
|
|
|
for (std::list<std::string>::iterator it = _settings.userIncludes.begin();
|
|
|
|
for (std::list<std::string>::const_iterator it = _settings->userIncludes.begin();
|
|
|
|
it != _settings.userIncludes.end();
|
|
|
|
it != _settings->userIncludes.end();
|
|
|
|
|
|
|
|
++it) {
|
|
|
|
++it) {
|
|
|
|
std::string cur = *it;
|
|
|
|
std::string cur = *it;
|
|
|
|
|
|
|
|
|
|
|
@ -994,12 +989,11 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
|
|
|
|
;
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (std::vector<std::string>::const_iterator it = _settings->library.defines.begin();
|
|
|
|
for (std::vector<std::string>::iterator it = _settings.library.defines.begin();
|
|
|
|
it != _settings->library.defines.end();
|
|
|
|
it != _settings.library.defines.end();
|
|
|
|
++it) {
|
|
|
|
++it) {
|
|
|
|
forcedIncludes += *it;
|
|
|
|
forcedIncludes += *it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!forcedIncludes.empty()) {
|
|
|
|
if (!forcedIncludes.empty()) {
|
|
|
|
processedFile =
|
|
|
|
processedFile =
|
|
|
@ -1030,7 +1024,7 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
|
|
|
|
else
|
|
|
|
else
|
|
|
|
line.insert(pos, ")");
|
|
|
|
line.insert(pos, ")");
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1039,9 +1033,9 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
|
|
|
|
processedFile = ostr.str();
|
|
|
|
processedFile = ostr.str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::map<std::string, std::string> defs(getcfgmap(_settings ? _settings->userDefines : emptyString, _settings, filename));
|
|
|
|
std::map<std::string, std::string> defs(getcfgmap(_settings.userDefines, &_settings, filename));
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->_maxConfigs == 1U) {
|
|
|
|
if (_settings._maxConfigs == 1U) {
|
|
|
|
std::set<std::string> pragmaOnce;
|
|
|
|
std::set<std::string> pragmaOnce;
|
|
|
|
std::list<std::string> includes;
|
|
|
|
std::list<std::string> includes;
|
|
|
|
processedFile = handleIncludes(processedFile, filename, includePaths, defs, pragmaOnce, includes);
|
|
|
|
processedFile = handleIncludes(processedFile, filename, includePaths, defs, pragmaOnce, includes);
|
|
|
@ -1061,10 +1055,10 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
|
|
|
|
|
|
|
|
|
|
|
|
void Preprocessor::handleUndef(std::list<std::string> &configurations) const
|
|
|
|
void Preprocessor::handleUndef(std::list<std::string> &configurations) const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (_settings && !_settings->userUndefs.empty()) {
|
|
|
|
if (!_settings.userUndefs.empty()) {
|
|
|
|
for (std::list<std::string>::iterator cfg = configurations.begin(); cfg != configurations.end();) {
|
|
|
|
for (std::list<std::string>::iterator cfg = configurations.begin(); cfg != configurations.end();) {
|
|
|
|
bool undef = false;
|
|
|
|
bool undef = false;
|
|
|
|
for (std::set<std::string>::const_iterator it = _settings->userUndefs.begin(); it != _settings->userUndefs.end(); ++it) {
|
|
|
|
for (std::set<std::string>::const_iterator it = _settings.userUndefs.begin(); it != _settings.userUndefs.end(); ++it) {
|
|
|
|
if (*it == *cfg)
|
|
|
|
if (*it == *cfg)
|
|
|
|
undef = true;
|
|
|
|
undef = true;
|
|
|
|
else if (cfg->compare(0,it->length(),*it)==0 && cfg->find_first_of(";=") == it->length())
|
|
|
|
else if (cfg->compare(0,it->length(),*it)==0 && cfg->find_first_of(";=") == it->length())
|
|
|
@ -1133,7 +1127,7 @@ std::string Preprocessor::getdef(std::string line, bool def)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Simplify variable in variable map. */
|
|
|
|
/** Simplify variable in variable map. */
|
|
|
|
static Token *simplifyVarMapExpandValue(Token *tok, const std::map<std::string, std::string> &variables, std::set<std::string> seenVariables, const Settings* settings)
|
|
|
|
static Token *simplifyVarMapExpandValue(Token *tok, const std::map<std::string, std::string> &variables, std::set<std::string> seenVariables, const Settings& settings)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// TODO: handle function-macros too.
|
|
|
|
// TODO: handle function-macros too.
|
|
|
|
|
|
|
|
|
|
|
@ -1144,7 +1138,7 @@ static Token *simplifyVarMapExpandValue(Token *tok, const std::map<std::string,
|
|
|
|
|
|
|
|
|
|
|
|
const std::map<std::string, std::string>::const_iterator it = variables.find(tok->str());
|
|
|
|
const std::map<std::string, std::string>::const_iterator it = variables.find(tok->str());
|
|
|
|
if (it != variables.end()) {
|
|
|
|
if (it != variables.end()) {
|
|
|
|
TokenList tokenList(settings);
|
|
|
|
TokenList tokenList(&settings);
|
|
|
|
std::istringstream istr(it->second);
|
|
|
|
std::istringstream istr(it->second);
|
|
|
|
if (tokenList.createTokens(istr)) {
|
|
|
|
if (tokenList.createTokens(istr)) {
|
|
|
|
// expand token list
|
|
|
|
// expand token list
|
|
|
@ -1172,10 +1166,10 @@ static Token *simplifyVarMapExpandValue(Token *tok, const std::map<std::string,
|
|
|
|
* Simplifies the variable map. For example if the map contains A=>B, B=>1, then A=>B is simplified to A=>1.
|
|
|
|
* Simplifies the variable map. For example if the map contains A=>B, B=>1, then A=>B is simplified to A=>1.
|
|
|
|
* @param [in,out] variables - a map of variable name to variable value. This map will be modified.
|
|
|
|
* @param [in,out] variables - a map of variable name to variable value. This map will be modified.
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
static void simplifyVarMap(std::map<std::string, std::string> &variables, const Settings* settings)
|
|
|
|
static void simplifyVarMap(std::map<std::string, std::string> &variables, const Settings& settings)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (std::map<std::string, std::string>::iterator i = variables.begin(); i != variables.end(); ++i) {
|
|
|
|
for (std::map<std::string, std::string>::iterator i = variables.begin(); i != variables.end(); ++i) {
|
|
|
|
TokenList tokenList(settings);
|
|
|
|
TokenList tokenList(&settings);
|
|
|
|
std::istringstream istr(i->second);
|
|
|
|
std::istringstream istr(i->second);
|
|
|
|
if (tokenList.createTokens(istr)) {
|
|
|
|
if (tokenList.createTokens(istr)) {
|
|
|
|
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
|
|
|
for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
|
|
|
@ -1214,11 +1208,11 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|
|
|
unsigned int linenr = 0;
|
|
|
|
unsigned int linenr = 0;
|
|
|
|
std::istringstream istr(filedata);
|
|
|
|
std::istringstream istr(filedata);
|
|
|
|
std::string line;
|
|
|
|
std::string line;
|
|
|
|
const bool printDebug = (_settings && _settings->debugwarnings);
|
|
|
|
const bool printDebug = _settings.debugwarnings;
|
|
|
|
while (std::getline(istr, line)) {
|
|
|
|
while (std::getline(istr, line)) {
|
|
|
|
++linenr;
|
|
|
|
++linenr;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
|
|
if (_errorLogger)
|
|
|
|
if (_errorLogger)
|
|
|
@ -1232,13 +1226,8 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|
|
|
const std::string::size_type start=line.find("\"");
|
|
|
|
const std::string::size_type start=line.find("\"");
|
|
|
|
const std::string::size_type end=line.find("\"",start+1);
|
|
|
|
const std::string::size_type end=line.find("\"",start+1);
|
|
|
|
const std::string includeFile=line.substr(start+1,end-start-1);
|
|
|
|
const std::string includeFile=line.substr(start+1,end-start-1);
|
|
|
|
bool fileExcluded = false;
|
|
|
|
|
|
|
|
++filelevel;
|
|
|
|
++filelevel;
|
|
|
|
if (! _settings) {
|
|
|
|
bool fileExcluded = _settings.configurationExcluded(includeFile);
|
|
|
|
fileExcluded = false;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fileExcluded = _settings->configurationExcluded(includeFile);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
includeStack.push(std::pair<std::string,bool>(includeFile,fileExcluded));
|
|
|
|
includeStack.push(std::pair<std::string,bool>(includeFile,fileExcluded));
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1487,7 +1476,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
|
|
|
std::string s(*it);
|
|
|
|
std::string s(*it);
|
|
|
|
|
|
|
|
|
|
|
|
if (s.find("&&") != std::string::npos) {
|
|
|
|
if (s.find("&&") != std::string::npos) {
|
|
|
|
Tokenizer tokenizer(_settings, _errorLogger);
|
|
|
|
Tokenizer tokenizer(&_settings, _errorLogger);
|
|
|
|
if (!tokenizer.tokenizeCondition(s)) {
|
|
|
|
if (!tokenizer.tokenizeCondition(s)) {
|
|
|
|
std::ostringstream lineStream;
|
|
|
|
std::ostringstream lineStream;
|
|
|
|
lineStream << __LINE__;
|
|
|
|
lineStream << __LINE__;
|
|
|
@ -1766,7 +1755,7 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|
|
|
std::list<bool> matched_ifdef;
|
|
|
|
std::list<bool> matched_ifdef;
|
|
|
|
|
|
|
|
|
|
|
|
// Create a map for the cfg for faster access to defines
|
|
|
|
// Create a map for the cfg for faster access to defines
|
|
|
|
std::map<std::string, std::string> cfgmap(getcfgmap(cfg, _settings, filename));
|
|
|
|
std::map<std::string, std::string> cfgmap(getcfgmap(cfg, &_settings, filename));
|
|
|
|
|
|
|
|
|
|
|
|
std::stack<std::string> filenames;
|
|
|
|
std::stack<std::string> filenames;
|
|
|
|
filenames.push(filename);
|
|
|
|
filenames.push(filename);
|
|
|
@ -1776,7 +1765,7 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|
|
|
while (std::getline(istr, line)) {
|
|
|
|
while (std::getline(istr, line)) {
|
|
|
|
++lineno;
|
|
|
|
++lineno;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
if (line.compare(0, 11, "#pragma asm") == 0) {
|
|
|
|
if (line.compare(0, 11, "#pragma asm") == 0) {
|
|
|
@ -1794,7 +1783,7 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
if (line.find("=") != std::string::npos) {
|
|
|
|
if (line.find("=") != std::string::npos) {
|
|
|
|
Tokenizer tokenizer(_settings, _errorLogger);
|
|
|
|
Tokenizer tokenizer(&_settings, _errorLogger);
|
|
|
|
line.erase(0, sizeof("#pragma endasm"));
|
|
|
|
line.erase(0, sizeof("#pragma endasm"));
|
|
|
|
std::istringstream tempIstr(line);
|
|
|
|
std::istringstream tempIstr(line);
|
|
|
|
tokenizer.tokenize(tempIstr, "", "", true);
|
|
|
|
tokenizer.tokenize(tempIstr, "", "", true);
|
|
|
@ -1816,10 +1805,10 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|
|
|
if (line.compare(0, 8, "#define ") == 0) {
|
|
|
|
if (line.compare(0, 8, "#define ") == 0) {
|
|
|
|
match = true;
|
|
|
|
match = true;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings) {
|
|
|
|
|
|
|
|
typedef std::set<std::string>::const_iterator It;
|
|
|
|
typedef std::set<std::string>::const_iterator It;
|
|
|
|
for (It it = _settings->userUndefs.begin(); it != _settings->userUndefs.end(); ++it) {
|
|
|
|
for (It it = _settings.userUndefs.begin(); it != _settings.userUndefs.end(); ++it) {
|
|
|
|
const std::string::size_type pos = line.find_first_not_of(' ',8);
|
|
|
|
std::string::size_type pos = line.find_first_not_of(' ',8);
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
std::string::size_type pos2 = line.find(*it,pos);
|
|
|
|
std::string::size_type pos2 = line.find(*it,pos);
|
|
|
|
if ((pos2 != std::string::npos) &&
|
|
|
|
if ((pos2 != std::string::npos) &&
|
|
|
@ -1831,7 +1820,6 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
if (match) {
|
|
|
|
for (std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it) {
|
|
|
|
for (std::list<bool>::const_iterator it = matching_ifdef.begin(); it != matching_ifdef.end(); ++it) {
|
|
|
@ -1922,7 +1910,7 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
|
|
|
|
|
|
|
|
|
|
|
|
// #error => return ""
|
|
|
|
// #error => return ""
|
|
|
|
if (match && line.compare(0, 6, "#error") == 0) {
|
|
|
|
if (match && line.compare(0, 6, "#error") == 0) {
|
|
|
|
if (_settings && !_settings->userDefines.empty() && !_settings->_force) {
|
|
|
|
if (!_settings.userDefines.empty() && !_settings._force) {
|
|
|
|
error(filenames.top(), lineno, line);
|
|
|
|
error(filenames.top(), lineno, line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
@ -2067,7 +2055,7 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str
|
|
|
|
|
|
|
|
|
|
|
|
unsigned int linenr = 0;
|
|
|
|
unsigned int linenr = 0;
|
|
|
|
|
|
|
|
|
|
|
|
const std::set<std::string>& undefs = _settings ? _settings->userUndefs : std::set<std::string>();
|
|
|
|
const std::set<std::string> &undefs = _settings.userUndefs;
|
|
|
|
|
|
|
|
|
|
|
|
if (_errorLogger)
|
|
|
|
if (_errorLogger)
|
|
|
|
_errorLogger->reportProgress(filePath, "Preprocessor (handleIncludes)", 0);
|
|
|
|
_errorLogger->reportProgress(filePath, "Preprocessor (handleIncludes)", 0);
|
|
|
@ -2079,7 +2067,7 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str
|
|
|
|
while (std::getline(istr,line)) {
|
|
|
|
while (std::getline(istr,line)) {
|
|
|
|
++linenr;
|
|
|
|
++linenr;
|
|
|
|
|
|
|
|
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return "";
|
|
|
|
return "";
|
|
|
|
|
|
|
|
|
|
|
|
// has there been a true #if condition at the current indentmatch level?
|
|
|
|
// has there been a true #if condition at the current indentmatch level?
|
|
|
@ -2279,7 +2267,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::set<std::string> handledFiles;
|
|
|
|
std::set<std::string> handledFiles;
|
|
|
|
while ((pos = code.find("#include", pos)) != std::string::npos) {
|
|
|
|
while ((pos = code.find("#include", pos)) != std::string::npos) {
|
|
|
|
if (_settings && _settings->terminated())
|
|
|
|
if (_settings.terminated())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// Accept only includes that are at the start of a line
|
|
|
|
// Accept only includes that are at the start of a line
|
|
|
@ -2338,7 +2326,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath
|
|
|
|
path = filename;
|
|
|
|
path = filename;
|
|
|
|
path.erase(1 + path.find_last_of("\\/"));
|
|
|
|
path.erase(1 + path.find_last_of("\\/"));
|
|
|
|
paths.push_back(path);
|
|
|
|
paths.push_back(path);
|
|
|
|
} else if (!fileOpened && _settings) {
|
|
|
|
} else if (!fileOpened) {
|
|
|
|
std::string f = filePath;
|
|
|
|
std::string f = filePath;
|
|
|
|
|
|
|
|
|
|
|
|
// Determine line number of include
|
|
|
|
// Determine line number of include
|
|
|
@ -2373,16 +2361,16 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath
|
|
|
|
void Preprocessor::missingInclude(const std::string &filename, unsigned int linenr, const std::string &header, HeaderTypes headerType)
|
|
|
|
void Preprocessor::missingInclude(const std::string &filename, unsigned int linenr, const std::string &header, HeaderTypes headerType)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const std::string fname = Path::fromNativeSeparators(filename);
|
|
|
|
const std::string fname = Path::fromNativeSeparators(filename);
|
|
|
|
if (_settings->nomsg.isSuppressed("missingInclude", fname, linenr))
|
|
|
|
if (_settings.nomsg.isSuppressed("missingInclude", fname, linenr))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
if (headerType == SystemHeader && _settings->nomsg.isSuppressed("missingIncludeSystem", fname, linenr))
|
|
|
|
if (headerType == SystemHeader && _settings.nomsg.isSuppressed("missingIncludeSystem", fname, linenr))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (headerType == SystemHeader)
|
|
|
|
if (headerType == SystemHeader)
|
|
|
|
missingSystemIncludeFlag = true;
|
|
|
|
missingSystemIncludeFlag = true;
|
|
|
|
else
|
|
|
|
else
|
|
|
|
missingIncludeFlag = true;
|
|
|
|
missingIncludeFlag = true;
|
|
|
|
if (_errorLogger && _settings->checkConfiguration) {
|
|
|
|
if (_errorLogger && _settings.checkConfiguration) {
|
|
|
|
|
|
|
|
|
|
|
|
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
|
|
|
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
|
|
|
if (!filename.empty()) {
|
|
|
|
if (!filename.empty()) {
|
|
|
@ -2868,7 +2856,7 @@ static bool getlines(std::istream &istr, std::string &line)
|
|
|
|
|
|
|
|
|
|
|
|
bool Preprocessor::validateCfg(const std::string &code, const std::string &cfg)
|
|
|
|
bool Preprocessor::validateCfg(const std::string &code, const std::string &cfg)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
const bool printInformation = (_settings && _settings->isEnabled("information"));
|
|
|
|
const bool printInformation = _settings.isEnabled("information");
|
|
|
|
|
|
|
|
|
|
|
|
// fill up "macros" with empty configuration macros
|
|
|
|
// fill up "macros" with empty configuration macros
|
|
|
|
std::set<std::string> macros;
|
|
|
|
std::set<std::string> macros;
|
|
|
@ -3273,7 +3261,7 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file
|
|
|
|
void Preprocessor::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
|
|
|
void Preprocessor::getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Settings settings2(*settings);
|
|
|
|
Settings settings2(*settings);
|
|
|
|
Preprocessor preprocessor(&settings2, errorLogger);
|
|
|
|
Preprocessor preprocessor(settings2, errorLogger);
|
|
|
|
settings2.checkConfiguration=true;
|
|
|
|
settings2.checkConfiguration=true;
|
|
|
|
preprocessor.missingInclude("", 1, "", UserHeader);
|
|
|
|
preprocessor.missingInclude("", 1, "", UserHeader);
|
|
|
|
preprocessor.missingInclude("", 1, "", SystemHeader);
|
|
|
|
preprocessor.missingInclude("", 1, "", SystemHeader);
|
|
|
|