diff --git a/addons/misra.py b/addons/misra.py
index 2004200d0b8..ca8eb2bfb69 100755
--- a/addons/misra.py
+++ b/addons/misra.py
@@ -1823,20 +1823,6 @@ def misra_3_1(self, rawTokens):
self.reportError(token, 3, 1)
break
- def misra_3_2(self, rawTokens):
- for token in rawTokens:
- if token.str.startswith('//'):
- # Check for comment ends with trigraph which might be replaced
- # by a backslash.
- if token.str.endswith('??/'):
- self.reportError(token, 3, 2)
- # Check for comment which has been merged with subsequent line
- # because it ends with backslash.
- # The last backslash is no more part of the comment token thus
- # check if next token exists and compare line numbers.
- elif (token.next is not None) and (token.linenr == token.next.linenr):
- self.reportError(token, 3, 2)
-
def misra_4_1(self, rawTokens):
for token in rawTokens:
if (token.str[0] != '"') and (token.str[0] != '\''):
@@ -4718,7 +4704,7 @@ def fillVerifyExpected(verify_expected, tok):
# data.rawTokens is same for all configurations
if cfgNumber == 0:
self.executeCheck(301, self.misra_3_1, data.rawTokens)
- self.executeCheck(302, self.misra_3_2, data.rawTokens)
+ #self.executeCheck(302, self.misra_3_2, data.rawTokens)
self.executeCheck(401, self.misra_4_1, data.rawTokens)
self.executeCheck(402, self.misra_4_2, data.rawTokens)
self.executeCheck(501, self.misra_5_1, cfg)
diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c
index 73a815b6dd7..2435dcf253a 100644
--- a/addons/test/misra/misra-test.c
+++ b/addons/test/misra/misra-test.c
@@ -121,22 +121,6 @@ static void misra_2_7_b(int a, int b, int c, // 2.7
static void misra_2_7_c(int a, ...) { (void)a; }
static void misra_2_7_d(int) { } // 2.7 8.2
-static void misra_3_2(int enable)
-{
- // This won't generate a violation because of subsequent blank line \
-
- int y = 0;
- int x = 0; // 3.2 non-compliant comment ends with backslash \
- if (enable != 0)
- {
- ++x; // This is always executed
- // 3.2 potentially non-compliant comment ends with trigraph resolved to backslash ??/
- ++y; // This is hidden if trigraph replacement is active
- }
-
- (void)printf("x=%i, y=%i\n", x, y); //21.6
-}
-
extern int misra_5_1_extern_var_hides_var_x;
extern int misra_5_1_extern_var_hides_var_y; //5.1
int misra_5_1_var_hides_var________a; // 8.4
diff --git a/cfg/qt.cfg b/cfg/qt.cfg
index 12f31c4d0f6..00cb66c1909 100644
--- a/cfg/qt.cfg
+++ b/cfg/qt.cfg
@@ -5428,6 +5428,8 @@
+
+
diff --git a/cfg/wxwidgets.cfg b/cfg/wxwidgets.cfg
index 685750f7ff2..e09b19e15af 100644
--- a/cfg/wxwidgets.cfg
+++ b/cfg/wxwidgets.cfg
@@ -109,6 +109,8 @@
+
+
diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp
index bccb9b1b585..5093b4b74f2 100755
--- a/externals/simplecpp/simplecpp.cpp
+++ b/externals/simplecpp/simplecpp.cpp
@@ -4,8 +4,10 @@
*/
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
-#define SIMPLECPP_WINDOWS
-#define NOMINMAX
+# define _WIN32_WINNT 0x0602
+# define NOMINMAX
+# include
+# undef ERROR
#endif
#include "simplecpp.h"
@@ -32,21 +34,16 @@
#include
#include
#ifdef SIMPLECPP_WINDOWS
-#include
+# include
#endif
#include
#include
#include
#ifdef _WIN32
-#include
+# include
#else
-#include
-#endif
-
-#ifdef SIMPLECPP_WINDOWS
-#include
-#undef ERROR
+# include
#endif
static bool isHex(const std::string &s)
@@ -139,12 +136,6 @@ static unsigned long long stringToULL(const std::string &s)
return ret;
}
-// TODO: added an undercore since this conflicts with a function of the same name in utils.h from Cppcheck source when building Cppcheck with MSBuild
-static bool startsWith_(const std::string &s, const std::string &p)
-{
- return (s.size() >= p.size()) && std::equal(p.begin(), p.end(), s.begin());
-}
-
static bool endsWith(const std::string &s, const std::string &e)
{
return (s.size() >= e.size()) && std::equal(e.rbegin(), e.rend(), s.rbegin());
@@ -435,7 +426,7 @@ class FileStream : public simplecpp::TokenList::Stream {
lastStatus = lastCh = fgetc(file);
return lastCh;
}
- virtual int peek() override{
+ virtual int peek() override {
// keep lastCh intact
const int ch = fgetc(file);
unget_internal(ch);
@@ -767,17 +758,35 @@ void simplecpp::TokenList::readfile(Stream &stream, const std::string &filename,
// comment
else if (ch == '/' && stream.peekChar() == '/') {
- while (stream.good() && ch != '\r' && ch != '\n') {
+ while (stream.good() && ch != '\n') {
currentToken += ch;
ch = stream.readChar();
+ if(ch == '\\') {
+ TokenString tmp;
+ char tmp_ch = ch;
+ while((stream.good()) && (tmp_ch == '\\' || tmp_ch == ' ' || tmp_ch == '\t')) {
+ tmp += tmp_ch;
+ tmp_ch = stream.readChar();
+ }
+ if(!stream.good()) {
+ break;
+ }
+
+ if(tmp_ch != '\n') {
+ currentToken += tmp;
+ } else {
+ const TokenString check_portability = currentToken + tmp;
+ const std::string::size_type pos = check_portability.find_last_not_of(" \t");
+ if (pos < check_portability.size() - 1U && check_portability[pos] == '\\')
+ portabilityBackslash(outputList, files, location);
+ ++multiline;
+ tmp_ch = stream.readChar();
+ currentToken += '\n';
+ }
+ ch = tmp_ch;
+ }
}
- const std::string::size_type pos = currentToken.find_last_not_of(" \t");
- if (pos < currentToken.size() - 1U && currentToken[pos] == '\\')
- portabilityBackslash(outputList, files, location);
- if (currentToken[currentToken.size() - 1U] == '\\') {
- ++multiline;
- currentToken.erase(currentToken.size() - 1U);
- } else {
+ if (ch == '\n') {
stream.ungetChar();
}
}
@@ -2409,132 +2418,6 @@ namespace simplecpp {
}
#ifdef SIMPLECPP_WINDOWS
-
-using MyMutex = std::mutex;
-template
-using MyLock = std::lock_guard;
-
-class RealFileNameMap {
-public:
- RealFileNameMap() {}
-
- bool getCacheEntry(const std::string& path, std::string& returnPath) {
- MyLock lock(m_mutex);
-
- const std::map::iterator it = m_fileMap.find(path);
- if (it != m_fileMap.end()) {
- returnPath = it->second;
- return true;
- }
- return false;
- }
-
- void addToCache(const std::string& path, const std::string& actualPath) {
- MyLock lock(m_mutex);
- m_fileMap[path] = actualPath;
- }
-
-private:
- std::map m_fileMap;
- MyMutex m_mutex;
-};
-
-static RealFileNameMap realFileNameMap;
-
-static bool realFileName(const std::string &f, std::string &result)
-{
- // are there alpha characters in last subpath?
- bool alpha = false;
- for (std::string::size_type pos = 1; pos <= f.size(); ++pos) {
- const unsigned char c = f[f.size() - pos];
- if (c == '/' || c == '\\')
- break;
- if (std::isalpha(c)) {
- alpha = true;
- break;
- }
- }
-
- // do not convert this path if there are no alpha characters (either pointless or cause wrong results for . and ..)
- if (!alpha)
- return false;
-
- // Lookup filename or foldername on file system
- if (!realFileNameMap.getCacheEntry(f, result)) {
-
- WIN32_FIND_DATAA FindFileData;
-
-#ifdef __CYGWIN__
- const std::string fConverted = simplecpp::convertCygwinToWindowsPath(f);
- const HANDLE hFind = FindFirstFileExA(fConverted.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0);
-#else
- HANDLE hFind = FindFirstFileExA(f.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0);
-#endif
-
- if (INVALID_HANDLE_VALUE == hFind)
- return false;
- result = FindFileData.cFileName;
- realFileNameMap.addToCache(f, result);
- FindClose(hFind);
- }
- return true;
-}
-
-static RealFileNameMap realFilePathMap;
-
-/** Change case in given path to match filesystem */
-static std::string realFilename(const std::string &f)
-{
- std::string ret;
- ret.reserve(f.size()); // this will be the final size
- if (realFilePathMap.getCacheEntry(f, ret))
- return ret;
-
- // Current subpath
- std::string subpath;
-
- for (std::string::size_type pos = 0; pos < f.size(); ++pos) {
- const unsigned char c = f[pos];
-
- // Separator.. add subpath and separator
- if (c == '/' || c == '\\') {
- // if subpath is empty just add separator
- if (subpath.empty()) {
- ret += c;
- continue;
- }
-
- const bool isDriveSpecification =
- (pos == 2 && subpath.size() == 2 && std::isalpha(subpath[0]) && subpath[1] == ':');
-
- // Append real filename (proper case)
- std::string f2;
- if (!isDriveSpecification && realFileName(f.substr(0, pos), f2))
- ret += f2;
- else
- ret += subpath;
-
- subpath.clear();
-
- // Append separator
- ret += c;
- } else {
- subpath += c;
- }
- }
-
- if (!subpath.empty()) {
- std::string f2;
- if (realFileName(f,f2))
- ret += f2;
- else
- ret += subpath;
- }
-
- realFilePathMap.addToCache(f, ret);
- return ret;
-}
-
static bool isAbsolutePath(const std::string &path)
{
if (path.length() >= 3 && path[0] > 0 && std::isalpha(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
@@ -2542,8 +2425,6 @@ static bool isAbsolutePath(const std::string &path)
return path.length() > 1U && (path[0] == '/' || path[0] == '\\');
}
#else
-#define realFilename(f) f
-
static bool isAbsolutePath(const std::string &path)
{
return path.length() > 1U && path[0] == '/';
@@ -2621,8 +2502,7 @@ namespace simplecpp {
if (unc)
path = '/' + path;
- // cppcheck-suppress duplicateExpressionTernary - platform-dependent implementation
- return strpbrk(path.c_str(), "*?") == nullptr ? realFilename(path) : path;
+ return path;
}
}
@@ -2684,37 +2564,8 @@ static bool isGnu(const simplecpp::DUI &dui)
return dui.std.rfind("gnu", 0) != std::string::npos;
}
-static std::string currentDirectoryOSCalc() {
- const std::size_t size = 4096;
- char currentPath[size];
-
-#ifndef _WIN32
- if (getcwd(currentPath, size) != nullptr)
-#else
- if (_getcwd(currentPath, size) != nullptr)
-#endif
- return std::string(currentPath);
-
- return "";
-}
-
-static const std::string& currentDirectory() {
- static const std::string curdir = simplecpp::simplifyPath(currentDirectoryOSCalc());
- return curdir;
-}
-
-static std::string toAbsolutePath(const std::string& path) {
- if (path.empty()) {
- return path;// preserve error file path that is indicated by an empty string
- }
- if (!isAbsolutePath(path)) {
- return simplecpp::simplifyPath(currentDirectory() + "/" + path);
- }
- // otherwise
- return simplecpp::simplifyPath(path);
-}
-
-static std::string dirPath(const std::string& path, bool withTrailingSlash=true) {
+static std::string dirPath(const std::string& path, bool withTrailingSlash=true)
+{
const std::size_t lastSlash = path.find_last_of("\\/");
if (lastSlash == std::string::npos) {
return "";
@@ -2722,36 +2573,6 @@ static std::string dirPath(const std::string& path, bool withTrailingSlash=true)
return path.substr(0, lastSlash + (withTrailingSlash ? 1U : 0U));
}
-static std::string omitPathTrailingSlash(const std::string& path) {
- if (endsWith(path, "/")) {
- return path.substr(0, path.size() - 1U);
- }
- return path;
-}
-
-static std::string extractRelativePathFromAbsolute(const std::string& absoluteSimplifiedPath, const std::string& prefixSimplifiedAbsoluteDir = currentDirectory()) {
- const std::string normalizedAbsolutePath = omitPathTrailingSlash(absoluteSimplifiedPath);
- std::string currentPrefix = omitPathTrailingSlash(prefixSimplifiedAbsoluteDir);
- std::string leadingParenting;
- while (!startsWith_(normalizedAbsolutePath, currentPrefix)) {
- leadingParenting = "../" + leadingParenting;
- currentPrefix = dirPath(currentPrefix, false);
- }
- const std::size_t size = currentPrefix.size();
- std::string relativeFromMeetingPath = normalizedAbsolutePath.substr(size, normalizedAbsolutePath.size() - size);
- if (currentPrefix.empty() && !(startsWith_(absoluteSimplifiedPath, "/") && startsWith_(prefixSimplifiedAbsoluteDir, "/"))) {
- // In the case that there is no common prefix path,
- // and at not both of the paths start with `/` (can happen only in Windows paths on distinct partitions),
- // return the absolute simplified path as is because no relative path can match.
- return absoluteSimplifiedPath;
- }
- if (startsWith_(relativeFromMeetingPath, "/")) {
- // omit the leading slash
- relativeFromMeetingPath = relativeFromMeetingPath.substr(1, relativeFromMeetingPath.size());
- }
- return leadingParenting + relativeFromMeetingPath;
-}
-
static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader);
static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI &dui)
{
@@ -2796,10 +2617,8 @@ static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI
for (simplecpp::Token *headerToken = tok1->next; headerToken != tok3; headerToken = headerToken->next)
header += headerToken->str();
- // cppcheck-suppress selfAssignment - platform-dependent implementation
- header = realFilename(header);
} else {
- header = realFilename(tok1->str().substr(1U, tok1->str().size() - 2U));
+ header = tok1->str().substr(1U, tok1->str().size() - 2U);
}
std::ifstream f;
const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader);
@@ -2827,6 +2646,8 @@ static void simplifyName(simplecpp::TokenList &expr)
if (alt)
continue;
}
+ if (tok->next && tok->next->str() == "(")
+ throw std::runtime_error("undefined function-like macro invocation: " + tok->str() + "( ... )");
tok->setstr("0");
}
}
@@ -3129,206 +2950,185 @@ class NonExistingFilesCache {
NonExistingFilesCache() {}
bool contains(const std::string& path) {
- MyLock lock(m_mutex);
+ std::lock_guard lock(m_mutex);
return (m_pathSet.find(path) != m_pathSet.end());
}
void add(const std::string& path) {
- MyLock lock(m_mutex);
+ std::lock_guard lock(m_mutex);
m_pathSet.insert(path);
}
void clear() {
- MyLock lock(m_mutex);
+ std::lock_guard lock(m_mutex);
m_pathSet.clear();
}
private:
std::set m_pathSet;
- MyMutex m_mutex;
+ std::mutex m_mutex;
};
static NonExistingFilesCache nonExistingFilesCache;
#endif
-static std::string openHeader(std::ifstream &f, const std::string &path)
+static std::string openHeaderDirect(std::ifstream &f, const std::string &path)
{
- std::string simplePath = simplecpp::simplifyPath(path);
#ifdef SIMPLECPP_WINDOWS
- if (nonExistingFilesCache.contains(simplePath))
+ if (nonExistingFilesCache.contains(path))
return ""; // file is known not to exist, skip expensive file open call
#endif
- f.open(simplePath.c_str());
+ f.open(path.c_str());
if (f.is_open())
- return simplePath;
+ return path;
#ifdef SIMPLECPP_WINDOWS
- nonExistingFilesCache.add(simplePath);
+ nonExistingFilesCache.add(path);
#endif
return "";
}
-static std::string getRelativeFileName(const std::string &baseFile, const std::string &header, bool returnAbsolutePath)
-{
- const std::string baseFileSimplified = simplecpp::simplifyPath(baseFile);
- const std::string baseFileAbsolute = isAbsolutePath(baseFileSimplified) ?
- baseFileSimplified :
- simplecpp::simplifyPath(currentDirectory() + "/" + baseFileSimplified);
-
- const std::string headerSimplified = simplecpp::simplifyPath(header);
- const std::string path = isAbsolutePath(headerSimplified) ?
- headerSimplified :
- simplecpp::simplifyPath(dirPath(baseFileAbsolute) + headerSimplified);
-
- return returnAbsolutePath ? toAbsolutePath(path) : extractRelativePathFromAbsolute(path);
-}
-
-static std::string openHeaderRelative(std::ifstream &f, const std::string &sourcefile, const std::string &header)
-{
- return openHeader(f, getRelativeFileName(sourcefile, header, isAbsolutePath(sourcefile)));
-}
-
-// returns the simplified header path:
-// * If the header path is absolute, returns it in absolute path
-// * Otherwise, returns it in relative path with respect to the current directory
-static std::string getIncludePathFileName(const std::string &includePath, const std::string &header)
+static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader)
{
- std::string simplifiedHeader = simplecpp::simplifyPath(header);
+ if (isAbsolutePath(header))
+ return openHeaderDirect(f, simplecpp::simplifyPath(header));
- if (isAbsolutePath(simplifiedHeader)) {
- return simplifiedHeader;
+ // prefer first to search the header relatively to source file if found, when not a system header
+ if (!systemheader) {
+ std::string path = openHeaderDirect(f, simplecpp::simplifyPath(dirPath(sourcefile) + header));
+ if (!path.empty()) {
+ return path;
+ }
}
- std::string basePath = toAbsolutePath(includePath);
- if (!basePath.empty() && basePath[basePath.size()-1U]!='/' && basePath[basePath.size()-1U]!='\\')
- basePath += '/';
- const std::string absoluteSimplifiedHeaderPath = simplecpp::simplifyPath(basePath + simplifiedHeader);
- // preserve absoluteness/relativieness of the including dir
- return isAbsolutePath(includePath) ? absoluteSimplifiedHeaderPath : extractRelativePathFromAbsolute(absoluteSimplifiedHeaderPath);
-}
-
-static std::string openHeaderIncludePath(std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
-{
- for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) {
- std::string path = openHeader(f, getIncludePathFileName(*it, header));
+ // search the header on the include paths (provided by the flags "-I...")
+ for (const auto &includePath : dui.includePaths) {
+ std::string path = openHeaderDirect(f, simplecpp::simplifyPath(includePath + "/" + header));
if (!path.empty())
return path;
}
return "";
}
-static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader)
+std::pair simplecpp::FileDataCache::tryload(FileDataCache::name_map_type::iterator &name_it, const simplecpp::DUI &dui, std::vector &filenames, simplecpp::OutputList *outputList)
{
- if (isAbsolutePath(header))
- return openHeader(f, header);
+ const std::string &path = name_it->first;
+ FileID fileId;
- // prefer first to search the header relatively to source file if found, when not a system header
- if (!systemheader) {
- std::string relativeHeader = openHeaderRelative(f, sourcefile, header);
- if (!relativeHeader.empty()) {
- return relativeHeader;
- }
+ if (!getFileId(path, fileId))
+ return {nullptr, false};
+
+ const auto id_it = mIdMap.find(fileId);
+ if (id_it != mIdMap.end()) {
+ name_it->second = id_it->second;
+ return {id_it->second, false};
}
- // search the header on the include paths (provided by the flags "-I...")
- return openHeaderIncludePath(f, dui, header);
-}
+ std::ifstream f(path);
+ FileData *const data = new FileData {path, TokenList(f, filenames, path, outputList)};
-static std::string findPathInMapBothRelativeAndAbsolute(const std::map &filedata, const std::string& path) {
- // here there are two possibilities - either we match this from absolute path or from a relative one
- if (filedata.find(path) != filedata.end()) {// try first to respect the exact match
- return path;
- }
+ if (dui.removeComments)
+ data->tokens.removeComments();
- // otherwise - try to use the normalize to the correct representation
- std::string alternativePath;
- if (isAbsolutePath(path)) {
- alternativePath = extractRelativePathFromAbsolute(simplecpp::simplifyPath(path));
- } else {
- alternativePath = toAbsolutePath(path);
- }
+ name_it->second = data;
+ mIdMap.emplace(fileId, data);
+ mData.emplace_back(data);
- if (filedata.find(alternativePath) != filedata.end()) {
- return alternativePath;
- }
- return "";
+ return {data, true};
}
-static std::string getFileIdPath(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
+std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList)
{
- if (filedata.empty()) {
- return "";
- }
if (isAbsolutePath(header)) {
- const std::string simplifiedHeaderPath = simplecpp::simplifyPath(header);
- const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, simplifiedHeaderPath);
- if (!match.empty()) {
- return match;
+ auto ins = mNameMap.emplace(simplecpp::simplifyPath(header), nullptr);
+
+ if (ins.second) {
+ const auto ret = tryload(ins.first, dui, filenames, outputList);
+ if (ret.first != nullptr) {
+ return ret;
+ }
+ } else {
+ return {ins.first->second, false};
}
+
+ return {nullptr, false};
}
if (!systemheader) {
- const std::string relativeFilename = getRelativeFileName(sourcefile, header, true);
- const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, relativeFilename);
- if (!match.empty()) {
- return match;
- }
- // if the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match
- std::ifstream f;
- openHeader(f, relativeFilename);
- if (f.is_open()) {
- f.close();
- return "";
+ auto ins = mNameMap.emplace(simplecpp::simplifyPath(dirPath(sourcefile) + header), nullptr);
+
+ if (ins.second) {
+ const auto ret = tryload(ins.first, dui, filenames, outputList);
+ if (ret.first != nullptr) {
+ return ret;
+ }
+ } else if (ins.first->second != nullptr) {
+ return {ins.first->second, false};
}
- } else if (filedata.find(header) != filedata.end()) {
- return header;// system header that its file is already in the filedata - return that as is
}
- for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) {
- const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, getIncludePathFileName(*it, header));
- if (!match.empty()) {
- return match;
+ for (const auto &includePath : dui.includePaths) {
+ auto ins = mNameMap.emplace(simplecpp::simplifyPath(includePath + "/" + header), nullptr);
+
+ if (ins.second) {
+ const auto ret = tryload(ins.first, dui, filenames, outputList);
+ if (ret.first != nullptr) {
+ return ret;
+ }
+ } else if (ins.first->second != nullptr) {
+ return {ins.first->second, false};
}
}
- return "";
+ return {nullptr, false};
}
-static bool hasFile(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
+bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id)
{
- return !getFileIdPath(filedata, sourcefile, header, dui, systemheader).empty();
-}
+#ifdef SIMPLECPP_WINDOWS
+ HANDLE hFile = CreateFileA(path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-static void safeInsertTokenListToMap(std::map &filedata, const std::string &header2, simplecpp::TokenList *tokens, const std::string &header, const std::string &sourcefile, bool systemheader, const char* contextDesc)
-{
- const bool inserted = filedata.insert(std::make_pair(header2, tokens)).second;
- if (!inserted) {
- std::cerr << "error in " << contextDesc << " - attempt to add a tokenized file to the file map, but this file is already in the map! Details:" <<
- "header: " << header << " header2: " << header2 << " source: " << sourcefile << " systemheader: " << systemheader << std::endl;
- std::abort();
- }
+ if (hFile == INVALID_HANDLE_VALUE)
+ return false;
+
+ const BOOL ret = GetFileInformationByHandleEx(hFile, FileIdInfo, &id.fileIdInfo, sizeof(id.fileIdInfo));
+
+ CloseHandle(hFile);
+
+ return ret == TRUE;
+#else
+ struct stat statbuf;
+
+ if (stat(path.c_str(), &statbuf) != 0)
+ return false;
+
+ id.dev = statbuf.st_dev;
+ id.ino = statbuf.st_ino;
+
+ return true;
+#endif
}
-std::map simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
+simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
{
#ifdef SIMPLECPP_WINDOWS
if (dui.clearIncludeCache)
nonExistingFilesCache.clear();
#endif
- std::map ret;
+ FileDataCache cache;
std::list filelist;
// -include files
for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) {
- const std::string &filename = realFilename(*it);
+ const std::string &filename = *it;
- if (ret.find(filename) != ret.end())
- continue;
+ const auto loadResult = cache.get("", filename, dui, false, filenames, outputList);
+ const bool loaded = loadResult.second;
+ FileData *const filedata = loadResult.first;
- std::ifstream fin(filename.c_str());
- if (!fin.is_open()) {
+ if (filedata == nullptr) {
if (outputList) {
simplecpp::Output err(filenames);
err.type = simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND;
@@ -3338,18 +3138,17 @@ std::map simplecpp::load(const simplecpp::To
}
continue;
}
- fin.close();
- TokenList *tokenlist = new TokenList(filename, filenames, outputList);
- if (!tokenlist->front()) {
- delete tokenlist;
+ if (!loaded)
+ continue;
+
+ if (!filedata->tokens.front())
continue;
- }
if (dui.removeComments)
- tokenlist->removeComments();
- ret[filename] = tokenlist;
- filelist.push_back(tokenlist->front());
+ filedata->tokens.removeComments();
+
+ filelist.push_back(filedata->tokens.front());
}
for (const Token *rawtok = rawtokens.cfront(); rawtok || !filelist.empty(); rawtok = rawtok ? rawtok->next : nullptr) {
@@ -3372,25 +3171,20 @@ std::map simplecpp::load(const simplecpp::To
continue;
const bool systemheader = (htok->str()[0] == '<');
- const std::string header(realFilename(htok->str().substr(1U, htok->str().size() - 2U)));
- if (hasFile(ret, sourcefile, header, dui, systemheader))
- continue;
+ const std::string header(htok->str().substr(1U, htok->str().size() - 2U));
- std::ifstream f;
- const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader);
- if (!f.is_open())
+ FileData *const filedata = cache.get(sourcefile, header, dui, systemheader, filenames, outputList).first;
+ if (!filedata)
continue;
- f.close();
- TokenList *tokens = new TokenList(header2, filenames, outputList);
if (dui.removeComments)
- tokens->removeComments();
- safeInsertTokenListToMap(ret, header2, tokens, header, rawtok->location.file(), systemheader, "simplecpp::load");
- if (tokens->front())
- filelist.push_back(tokens->front());
+ filedata->tokens.removeComments();
+
+ if (filedata->tokens.front())
+ filelist.push_back(filedata->tokens.front());
}
- return ret;
+ return cache;
}
static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token **tok1, simplecpp::MacroMap ¯os, std::vector &files, simplecpp::OutputList *outputList)
@@ -3446,7 +3240,7 @@ static std::string getTimeDefine(const struct tm *timep)
return std::string("\"").append(buf).append("\"");
}
-void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond)
+void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, simplecpp::FileDataCache &cache, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond)
{
#ifdef SIMPLECPP_WINDOWS
if (dui.clearIncludeCache)
@@ -3537,6 +3331,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
// AlwaysFalse => drop all code in #if and #else
enum IfState { True, ElseIsTrue, AlwaysFalse };
std::stack ifstates;
+ std::stack iftokens;
ifstates.push(True);
std::stack includetokenstack;
@@ -3545,9 +3340,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
includetokenstack.push(rawtokens.cfront());
for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) {
- const std::map::const_iterator f = filedata.find(*it);
- if (f != filedata.end())
- includetokenstack.push(f->second->cfront());
+ const FileData *const filedata = cache.get("", *it, dui, false, files, outputList).first;
+ if (filedata != nullptr && filedata->tokens.cfront() != nullptr)
+ includetokenstack.push(filedata->tokens.cfront());
}
std::map > maybeUsedMacros;
@@ -3678,21 +3473,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
const Token * const inctok = inc2.cfront();
const bool systemheader = (inctok->str()[0] == '<');
- const std::string header(realFilename(inctok->str().substr(1U, inctok->str().size() - 2U)));
- std::string header2 = getFileIdPath(filedata, rawtok->location.file(), header, dui, systemheader);
- if (header2.empty()) {
- // try to load file..
- std::ifstream f;
- header2 = openHeader(f, dui, rawtok->location.file(), header, systemheader);
- if (f.is_open()) {
- f.close();
- TokenList * const tokens = new TokenList(header2, files, outputList);
- if (dui.removeComments)
- tokens->removeComments();
- safeInsertTokenListToMap(filedata, header2, tokens, header, rawtok->location.file(), systemheader, "simplecpp::preprocess");
- }
- }
- if (header2.empty()) {
+ const std::string header(inctok->str().substr(1U, inctok->str().size() - 2U));
+ const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).first;
+ if (filedata == nullptr) {
if (outputList) {
simplecpp::Output out(files);
out.type = Output::MISSING_HEADER;
@@ -3708,10 +3491,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
out.msg = "#include nested too deeply";
outputList->push_back(out);
}
- } else if (pragmaOnce.find(header2) == pragmaOnce.end()) {
+ } else if (pragmaOnce.find(filedata->filename) == pragmaOnce.end()) {
includetokenstack.push(gotoNextLine(rawtok));
- const TokenList * const includetokens = filedata.find(header2)->second;
- rawtok = includetokens ? includetokens->cfront() : nullptr;
+ rawtok = filedata->tokens.cfront();
continue;
}
} else if (rawtok->str() == IF || rawtok->str() == IFDEF || rawtok->str() == IFNDEF || rawtok->str() == ELIF) {
@@ -3788,12 +3570,10 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
if (systemheader) {
while ((tok = tok->next) && tok->op != '>')
header += tok->str();
- // cppcheck-suppress selfAssignment - platform-dependent implementation
- header = realFilename(header);
if (tok && tok->op == '>')
closingAngularBracket = true;
} else {
- header = realFilename(tok->str().substr(1U, tok->str().size() - 2U));
+ header = tok->str().substr(1U, tok->str().size() - 2U);
closingAngularBracket = true;
}
std::ifstream f;
@@ -3860,15 +3640,24 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
ifstates.push(AlwaysFalse);
else
ifstates.push(conditionIsTrue ? True : ElseIsTrue);
+ iftokens.push(rawtok);
} else if (ifstates.top() == True) {
ifstates.top() = AlwaysFalse;
+ iftokens.top()->nextcond = rawtok;
+ iftokens.top() = rawtok;
} else if (ifstates.top() == ElseIsTrue && conditionIsTrue) {
ifstates.top() = True;
+ iftokens.top()->nextcond = rawtok;
+ iftokens.top() = rawtok;
}
} else if (rawtok->str() == ELSE) {
ifstates.top() = (ifstates.top() == ElseIsTrue) ? True : AlwaysFalse;
+ iftokens.top()->nextcond = rawtok;
+ iftokens.top() = rawtok;
} else if (rawtok->str() == ENDIF) {
ifstates.pop();
+ iftokens.top()->nextcond = rawtok;
+ iftokens.pop();
} else if (rawtok->str() == UNDEF) {
if (ifstates.top() == True) {
const Token *tok = rawtok->next;
@@ -3880,7 +3669,10 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
} else if (ifstates.top() == True && rawtok->str() == PRAGMA && rawtok->next && rawtok->next->str() == ONCE && sameline(rawtok,rawtok->next)) {
pragmaOnce.insert(rawtok->location.file());
}
- rawtok = gotoNextLine(rawtok);
+ if (ifstates.top() != True && rawtok->nextcond)
+ rawtok = rawtok->nextcond->previous;
+ else
+ rawtok = gotoNextLine(rawtok);
continue;
}
@@ -3941,11 +3733,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
}
}
-void simplecpp::cleanup(std::map &filedata)
+void simplecpp::cleanup(FileDataCache &cache)
{
- for (std::map::iterator it = filedata.begin(); it != filedata.end(); ++it)
- delete it->second;
- filedata.clear();
+ cache.clear();
}
simplecpp::cstd_t simplecpp::getCStd(const std::string &std)
diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h
index 9fd95808364..76487d6c90e 100755
--- a/externals/simplecpp/simplecpp.h
+++ b/externals/simplecpp/simplecpp.h
@@ -6,13 +6,19 @@
#ifndef simplecppH
#define simplecppH
+#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__)
+# define SIMPLECPP_WINDOWS
+#endif
+
#include
#include
#include
#include
#include