Skip to content

Commit 2074075

Browse files
authored
Fix #13841 (Update simplecpp to 1.4.1) (danmar#7531)
1 parent 6d7dc76 commit 2074075

File tree

1 file changed

+129
-39
lines changed

1 file changed

+129
-39
lines changed

externals/simplecpp/simplecpp.cpp

Lines changed: 129 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@
4040
#include <utility>
4141
#include <vector>
4242

43+
#ifdef _WIN32
44+
#include <direct.h>
45+
#else
46+
#include <unistd.h>
47+
#endif
48+
4349
#ifdef SIMPLECPP_WINDOWS
4450
#include <windows.h>
4551
#undef ERROR
@@ -147,6 +153,12 @@ static unsigned long long stringToULL(const std::string &s)
147153
return ret;
148154
}
149155

156+
// 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
157+
static bool startsWith_(const std::string &s, const std::string &p)
158+
{
159+
return (s.size() >= p.size()) && std::equal(p.begin(), p.end(), s.begin());
160+
}
161+
150162
static bool endsWith(const std::string &s, const std::string &e)
151163
{
152164
return (s.size() >= e.size()) && std::equal(e.rbegin(), e.rend(), s.rbegin());
@@ -2334,17 +2346,12 @@ namespace simplecpp {
23342346
namespace simplecpp {
23352347

23362348
#ifdef __CYGWIN__
2337-
bool startsWith(const std::string &str, const std::string &s)
2338-
{
2339-
return (str.size() >= s.size() && str.compare(0, s.size(), s) == 0);
2340-
}
2341-
23422349
std::string convertCygwinToWindowsPath(const std::string &cygwinPath)
23432350
{
23442351
std::string windowsPath;
23452352

23462353
std::string::size_type pos = 0;
2347-
if (cygwinPath.size() >= 11 && startsWith(cygwinPath, "/cygdrive/")) {
2354+
if (cygwinPath.size() >= 11 && startsWith_(cygwinPath, "/cygdrive/")) {
23482355
const unsigned char driveLetter = cygwinPath[10];
23492356
if (std::isalpha(driveLetter)) {
23502357
if (cygwinPath.size() == 11) {
@@ -2681,6 +2688,47 @@ static bool isCpp17OrLater(const simplecpp::DUI &dui)
26812688
return !std_ver.empty() && (std_ver >= "201703L");
26822689
}
26832690

2691+
2692+
static std::string currentDirectoryOSCalc() {
2693+
const std::size_t size = 4096;
2694+
char currentPath[size];
2695+
2696+
#ifndef _WIN32
2697+
if (getcwd(currentPath, size) != nullptr)
2698+
#else
2699+
if (_getcwd(currentPath, size) != nullptr)
2700+
#endif
2701+
return std::string(currentPath);
2702+
2703+
return "";
2704+
}
2705+
2706+
static const std::string& currentDirectory() {
2707+
static const std::string curdir = simplecpp::simplifyPath(currentDirectoryOSCalc());
2708+
return curdir;
2709+
}
2710+
2711+
static std::string toAbsolutePath(const std::string& path) {
2712+
if (path.empty()) {
2713+
return path;// preserve error file path that is indicated by an empty string
2714+
}
2715+
if (!isAbsolutePath(path)) {
2716+
return simplecpp::simplifyPath(currentDirectory() + "/" + path);
2717+
}
2718+
// otherwise
2719+
return simplecpp::simplifyPath(path);
2720+
}
2721+
2722+
static std::pair<std::string, bool> extractRelativePathFromAbsolute(const std::string& absolutepath) {
2723+
static const std::string prefix = currentDirectory() + "/";
2724+
if (startsWith_(absolutepath, prefix)) {
2725+
const std::size_t size = prefix.size();
2726+
return std::make_pair(absolutepath.substr(size, absolutepath.size() - size), true);
2727+
}
2728+
// otherwise
2729+
return std::make_pair("", false);
2730+
}
2731+
26842732
static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader);
26852733
static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI &dui)
26862734
{
@@ -3097,32 +3145,45 @@ static std::string openHeader(std::ifstream &f, const std::string &path)
30973145
return "";
30983146
}
30993147

3100-
static std::string getRelativeFileName(const std::string &sourcefile, const std::string &header)
3148+
static std::string getRelativeFileName(const std::string &baseFile, const std::string &header)
31013149
{
3102-
if (sourcefile.find_first_of("\\/") != std::string::npos)
3103-
return simplecpp::simplifyPath(sourcefile.substr(0, sourcefile.find_last_of("\\/") + 1U) + header);
3104-
return simplecpp::simplifyPath(header);
3150+
std::string path;
3151+
if (baseFile.find_first_of("\\/") != std::string::npos)
3152+
path = baseFile.substr(0, baseFile.find_last_of("\\/") + 1U) + header;
3153+
else
3154+
path = header;
3155+
return simplecpp::simplifyPath(path);
31053156
}
31063157

31073158
static std::string openHeaderRelative(std::ifstream &f, const std::string &sourcefile, const std::string &header)
31083159
{
31093160
return openHeader(f, getRelativeFileName(sourcefile, header));
31103161
}
31113162

3163+
// returns the simplified header path:
3164+
// * If the header path is absolute, returns it in absolute path
3165+
// * Otherwise, returns it in relative path with respect to the current directory
31123166
static std::string getIncludePathFileName(const std::string &includePath, const std::string &header)
31133167
{
3114-
std::string path = includePath;
3115-
if (!path.empty() && path[path.size()-1U]!='/' && path[path.size()-1U]!='\\')
3116-
path += '/';
3117-
return path + header;
3168+
std::string simplifiedHeader = simplecpp::simplifyPath(header);
3169+
3170+
if (isAbsolutePath(simplifiedHeader)) {
3171+
return simplifiedHeader;
3172+
}
3173+
3174+
std::string basePath = toAbsolutePath(includePath);
3175+
if (!basePath.empty() && basePath[basePath.size()-1U]!='/' && basePath[basePath.size()-1U]!='\\')
3176+
basePath += '/';
3177+
const std::string absolutesimplifiedHeaderPath = basePath + simplifiedHeader;
3178+
return extractRelativePathFromAbsolute(absolutesimplifiedHeaderPath).first;
31183179
}
31193180

31203181
static std::string openHeaderIncludePath(std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
31213182
{
31223183
for (std::list<std::string>::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) {
3123-
std::string simplePath = openHeader(f, getIncludePathFileName(*it, header));
3124-
if (!simplePath.empty())
3125-
return simplePath;
3184+
std::string path = openHeader(f, getIncludePathFileName(*it, header));
3185+
if (!path.empty())
3186+
return path;
31263187
}
31273188
return "";
31283189
}
@@ -3132,49 +3193,78 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const
31323193
if (isAbsolutePath(header))
31333194
return openHeader(f, header);
31343195

3135-
std::string ret;
3136-
3137-
if (systemheader) {
3138-
ret = openHeaderIncludePath(f, dui, header);
3139-
return ret;
3196+
// prefer first to search the header relatively to source file if found, when not a system header
3197+
if (!systemheader) {
3198+
std::string relativeHeader = openHeaderRelative(f, sourcefile, header);
3199+
if (!relativeHeader.empty()) {
3200+
return relativeHeader;
3201+
}
31403202
}
31413203

3142-
ret = openHeaderRelative(f, sourcefile, header);
3143-
if (ret.empty())
3144-
return openHeaderIncludePath(f, dui, header);
3145-
return ret;
3204+
// search the header on the include paths (provided by the flags "-I...")
3205+
return openHeaderIncludePath(f, dui, header);
31463206
}
31473207

3148-
static std::string getFileName(const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
3208+
static std::string findPathInMapBothRelativeAndAbsolute(const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string& path) {
3209+
// here there are two possibilities - either we match this from absolute path or from a relative one
3210+
if (filedata.find(path) != filedata.end()) {// try first to respect the exact match
3211+
return path;
3212+
}
3213+
// otherwise - try to use the normalize to the correct representation
3214+
if (isAbsolutePath(path)) {
3215+
const std::pair<std::string, bool> relativeExtractedResult = extractRelativePathFromAbsolute(path);
3216+
if (relativeExtractedResult.second) {
3217+
const std::string relativePath = relativeExtractedResult.first;
3218+
if (filedata.find(relativePath) != filedata.end()) {
3219+
return relativePath;
3220+
}
3221+
}
3222+
} else {
3223+
const std::string absolutePath = toAbsolutePath(path);
3224+
if (filedata.find(absolutePath) != filedata.end()) {
3225+
return absolutePath;
3226+
}
3227+
}
3228+
// otherwise
3229+
return "";
3230+
}
3231+
3232+
static std::string getFileIdPath(const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
31493233
{
31503234
if (filedata.empty()) {
31513235
return "";
31523236
}
31533237
if (isAbsolutePath(header)) {
3154-
return (filedata.find(header) != filedata.end()) ? simplecpp::simplifyPath(header) : "";
3238+
const std::string simplifiedHeaderPath = simplecpp::simplifyPath(header);
3239+
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, simplifiedHeaderPath);
3240+
if (!match.empty()) {
3241+
return match;
3242+
}
31553243
}
31563244

31573245
if (!systemheader) {
3158-
const std::string relativeFilename = getRelativeFileName(sourcefile, header);
3159-
if (filedata.find(relativeFilename) != filedata.end())
3160-
return relativeFilename;
3246+
const std::string relativeOrAbsoluteFilename = getRelativeFileName(sourcefile, header);// unknown if absolute or relative, but always simplified
3247+
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, relativeOrAbsoluteFilename);
3248+
if (!match.empty()) {
3249+
return match;
3250+
}
3251+
} else if (filedata.find(header) != filedata.end()) {
3252+
return header;// system header that its file is already in the filedata - return that as is
31613253
}
31623254

31633255
for (std::list<std::string>::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) {
3164-
std::string s = simplecpp::simplifyPath(getIncludePathFileName(*it, header));
3165-
if (filedata.find(s) != filedata.end())
3166-
return s;
3256+
const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, getIncludePathFileName(*it, header));
3257+
if (!match.empty()) {
3258+
return match;
3259+
}
31673260
}
31683261

3169-
if (systemheader && filedata.find(header) != filedata.end())
3170-
return header;
3171-
31723262
return "";
31733263
}
31743264

31753265
static bool hasFile(const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
31763266
{
3177-
return !getFileName(filedata, sourcefile, header, dui, systemheader).empty();
3267+
return !getFileIdPath(filedata, sourcefile, header, dui, systemheader).empty();
31783268
}
31793269

31803270
std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector<std::string> &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
@@ -3530,7 +3620,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
35303620

35313621
const bool systemheader = (inctok->str()[0] == '<');
35323622
const std::string header(realFilename(inctok->str().substr(1U, inctok->str().size() - 2U)));
3533-
std::string header2 = getFileName(filedata, rawtok->location.file(), header, dui, systemheader);
3623+
std::string header2 = getFileIdPath(filedata, rawtok->location.file(), header, dui, systemheader);
35343624
if (header2.empty()) {
35353625
// try to load file..
35363626
std::ifstream f;

0 commit comments

Comments
 (0)