40
40
#include < utility>
41
41
#include < vector>
42
42
43
+ #ifdef _WIN32
44
+ #include < direct.h>
45
+ #else
46
+ #include < unistd.h>
47
+ #endif
48
+
43
49
#ifdef SIMPLECPP_WINDOWS
44
50
#include < windows.h>
45
51
#undef ERROR
@@ -147,6 +153,12 @@ static unsigned long long stringToULL(const std::string &s)
147
153
return ret;
148
154
}
149
155
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
+
150
162
static bool endsWith (const std::string &s, const std::string &e)
151
163
{
152
164
return (s.size () >= e.size ()) && std::equal (e.rbegin (), e.rend (), s.rbegin ());
@@ -2334,17 +2346,12 @@ namespace simplecpp {
2334
2346
namespace simplecpp {
2335
2347
2336
2348
#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
-
2342
2349
std::string convertCygwinToWindowsPath (const std::string &cygwinPath)
2343
2350
{
2344
2351
std::string windowsPath;
2345
2352
2346
2353
std::string::size_type pos = 0 ;
2347
- if (cygwinPath.size () >= 11 && startsWith (cygwinPath, " /cygdrive/" )) {
2354
+ if (cygwinPath.size () >= 11 && startsWith_ (cygwinPath, " /cygdrive/" )) {
2348
2355
const unsigned char driveLetter = cygwinPath[10 ];
2349
2356
if (std::isalpha (driveLetter)) {
2350
2357
if (cygwinPath.size () == 11 ) {
@@ -2681,6 +2688,47 @@ static bool isCpp17OrLater(const simplecpp::DUI &dui)
2681
2688
return !std_ver.empty () && (std_ver >= " 201703L" );
2682
2689
}
2683
2690
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
+
2684
2732
static std::string openHeader (std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader);
2685
2733
static void simplifyHasInclude (simplecpp::TokenList &expr, const simplecpp::DUI &dui)
2686
2734
{
@@ -3097,32 +3145,45 @@ static std::string openHeader(std::ifstream &f, const std::string &path)
3097
3145
return " " ;
3098
3146
}
3099
3147
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)
3101
3149
{
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);
3105
3156
}
3106
3157
3107
3158
static std::string openHeaderRelative (std::ifstream &f, const std::string &sourcefile, const std::string &header)
3108
3159
{
3109
3160
return openHeader (f, getRelativeFileName (sourcefile, header));
3110
3161
}
3111
3162
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
3112
3166
static std::string getIncludePathFileName (const std::string &includePath, const std::string &header)
3113
3167
{
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 ;
3118
3179
}
3119
3180
3120
3181
static std::string openHeaderIncludePath (std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
3121
3182
{
3122
3183
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 ;
3126
3187
}
3127
3188
return " " ;
3128
3189
}
@@ -3132,49 +3193,78 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const
3132
3193
if (isAbsolutePath (header))
3133
3194
return openHeader (f, header);
3134
3195
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
+ }
3140
3202
}
3141
3203
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);
3146
3206
}
3147
3207
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)
3149
3233
{
3150
3234
if (filedata.empty ()) {
3151
3235
return " " ;
3152
3236
}
3153
3237
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
+ }
3155
3243
}
3156
3244
3157
3245
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
3161
3253
}
3162
3254
3163
3255
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
+ }
3167
3260
}
3168
3261
3169
- if (systemheader && filedata.find (header) != filedata.end ())
3170
- return header;
3171
-
3172
3262
return " " ;
3173
3263
}
3174
3264
3175
3265
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)
3176
3266
{
3177
- return !getFileName (filedata, sourcefile, header, dui, systemheader).empty ();
3267
+ return !getFileIdPath (filedata, sourcefile, header, dui, systemheader).empty ();
3178
3268
}
3179
3269
3180
3270
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
3530
3620
3531
3621
const bool systemheader = (inctok->str ()[0 ] == ' <' );
3532
3622
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);
3534
3624
if (header2.empty ()) {
3535
3625
// try to load file..
3536
3626
std::ifstream f;
0 commit comments