4343#ifdef SIMPLECPP_WINDOWS
4444#include < windows.h>
4545#undef ERROR
46+ #else
47+ #include < unistd.h>
4648#endif
4749
4850#if __cplusplus >= 201103L
@@ -147,6 +149,12 @@ static unsigned long long stringToULL(const std::string &s)
147149 return ret;
148150}
149151
152+ // 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
153+ static bool startsWith_ (const std::string &s, const std::string &p)
154+ {
155+ return (s.size () >= p.size ()) && std::equal (p.begin (), p.end (), s.begin ());
156+ }
157+
150158static bool endsWith (const std::string &s, const std::string &e)
151159{
152160 return (s.size () >= e.size ()) && std::equal (e.rbegin (), e.rend (), s.rbegin ());
@@ -2334,17 +2342,12 @@ namespace simplecpp {
23342342namespace simplecpp {
23352343
23362344#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-
23422345 std::string convertCygwinToWindowsPath (const std::string &cygwinPath)
23432346 {
23442347 std::string windowsPath;
23452348
23462349 std::string::size_type pos = 0 ;
2347- if (cygwinPath.size () >= 11 && startsWith (cygwinPath, " /cygdrive/" )) {
2350+ if (cygwinPath.size () >= 11 && startsWith_ (cygwinPath, " /cygdrive/" )) {
23482351 const unsigned char driveLetter = cygwinPath[10 ];
23492352 if (std::isalpha (driveLetter)) {
23502353 if (cygwinPath.size () == 11 ) {
@@ -2681,6 +2684,54 @@ static bool isCpp17OrLater(const simplecpp::DUI &dui)
26812684 return !std_ver.empty () && (std_ver >= " 201703L" );
26822685}
26832686
2687+
2688+ static std::string currentDirectoryOSCalc () {
2689+ #ifdef SIMPLECPP_WINDOWS
2690+ TCHAR NPath[MAX_PATH];
2691+ GetCurrentDirectory (MAX_PATH, NPath);
2692+ #ifdef _UNICODE
2693+ // convert the result from TCHAR* to char*
2694+ char NPathA[MAX_PATH];
2695+ ::WideCharToMultiByte (CP_ACP, 0 , NPath, lstrlen(NPath), NPathA, MAX_PATH, NULL, NULL);
2696+ return NPathA;
2697+ #else
2698+ // in this case, TCHAR* is just defined to be a char*
2699+ return NPath;
2700+ #endif
2701+ #else
2702+ const std::size_t size = 1024 ;
2703+ char the_path[size];
2704+ getcwd (the_path, size);
2705+ return the_path;
2706+ #endif
2707+ }
2708+
2709+ static const std::string& currentDirectory () {
2710+ static const std::string curdir = simplecpp::simplifyPath (currentDirectoryOSCalc ());
2711+ return curdir;
2712+ }
2713+
2714+ static std::string toAbsolutePath (const std::string& path) {
2715+ if (path.empty ()) {
2716+ return path;// preserve error file path that is indicated by an empty string
2717+ }
2718+ if (!isAbsolutePath (path)) {
2719+ return simplecpp::simplifyPath (currentDirectory () + " /" + path);
2720+ }
2721+ // otherwise
2722+ return simplecpp::simplifyPath (path);
2723+ }
2724+
2725+ static std::pair<std::string, bool > extractRelativePathFromAbsolute (const std::string& absolutepath) {
2726+ static const std::string prefix = currentDirectory () + " /" ;
2727+ if (startsWith_ (absolutepath, prefix)) {
2728+ const std::size_t size = prefix.size ();
2729+ return std::make_pair (absolutepath.substr (size, absolutepath.size () - size), true );
2730+ }
2731+ // otherwise
2732+ return std::make_pair (" " , false );
2733+ }
2734+
26842735static std::string openHeader (std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader);
26852736static void simplifyHasInclude (simplecpp::TokenList &expr, const simplecpp::DUI &dui)
26862737{
@@ -3099,9 +3150,12 @@ static std::string openHeader(std::ifstream &f, const std::string &path)
30993150
31003151static std::string getRelativeFileName (const std::string &sourcefile, const std::string &header)
31013152{
3153+ std::string path;
31023154 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);
3155+ path = sourcefile.substr (0 , sourcefile.find_last_of (" \\ /" ) + 1U ) + header;
3156+ else
3157+ path = header;
3158+ return simplecpp::simplifyPath (path);
31053159}
31063160
31073161static std::string openHeaderRelative (std::ifstream &f, const std::string &sourcefile, const std::string &header)
@@ -3111,7 +3165,7 @@ static std::string openHeaderRelative(std::ifstream &f, const std::string &sourc
31113165
31123166static std::string getIncludePathFileName (const std::string &includePath, const std::string &header)
31133167{
3114- std::string path = includePath;
3168+ std::string path = toAbsolutePath ( includePath) ;
31153169 if (!path.empty () && path[path.size ()-1U ]!=' /' && path[path.size ()-1U ]!=' \\ ' )
31163170 path += ' /' ;
31173171 return path + header;
@@ -3120,9 +3174,9 @@ static std::string getIncludePathFileName(const std::string &includePath, const
31203174static std::string openHeaderIncludePath (std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
31213175{
31223176 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 ;
3177+ std::string path = openHeader (f, getIncludePathFileName (*it, header));
3178+ if (!path .empty ())
3179+ return path ;
31263180 }
31273181 return " " ;
31283182}
@@ -3132,49 +3186,76 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const
31323186 if (isAbsolutePath (header))
31333187 return openHeader (f, header);
31343188
3135- std::string ret;
3136-
31373189 if (systemheader) {
3138- ret = openHeaderIncludePath (f, dui, header);
3139- return ret ;
3190+ // always return absolute path for systemheaders
3191+ return toAbsolutePath ( openHeaderIncludePath (f, dui, header)) ;
31403192 }
31413193
3194+ std::string ret;
3195+
31423196 ret = openHeaderRelative (f, sourcefile, header);
31433197 if (ret.empty ())
3144- return openHeaderIncludePath (f, dui, header);
3198+ return toAbsolutePath ( openHeaderIncludePath (f, dui, header)); // in a similar way to system headers
31453199 return ret;
31463200}
31473201
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)
3202+ static std::string findPathInMapBothRelativeAndAbsolute (const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string& path) {
3203+ // here there are two possibilities - either we match this from absolute path or from a relative one
3204+ if (filedata.find (path) != filedata.end ()) {// try first to respect the exact match
3205+ return path;
3206+ }
3207+ // otherwise - try to use the normalize to the correct representation
3208+ if (isAbsolutePath (path)) {
3209+ const std::pair<std::string, bool > relativeExtractedResult = extractRelativePathFromAbsolute (path);
3210+ if (relativeExtractedResult.second ) {
3211+ const std::string relativePath = relativeExtractedResult.first ;
3212+ if (filedata.find (relativePath) != filedata.end ()) {
3213+ return relativePath;
3214+ }
3215+ }
3216+ } else {
3217+ const std::string absolutePath = toAbsolutePath (path);
3218+ if (filedata.find (absolutePath) != filedata.end ())
3219+ return absolutePath;
3220+ }
3221+ // otherwise
3222+ return " " ;
3223+ }
3224+
3225+ 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)
31493226{
31503227 if (filedata.empty ()) {
31513228 return " " ;
31523229 }
31533230 if (isAbsolutePath (header)) {
3154- return (filedata.find (header) != filedata.end ()) ? simplecpp::simplifyPath (header) : " " ;
3231+ const std::string simplifiedHeaderPath = simplecpp::simplifyPath (header);
3232+ return (filedata.find (simplifiedHeaderPath) != filedata.end ()) ? simplifiedHeaderPath : " " ;
31553233 }
31563234
31573235 if (!systemheader) {
3158- const std::string relativeFilename = getRelativeFileName (sourcefile, header);
3159- if (filedata.find (relativeFilename) != filedata.end ())
3160- return relativeFilename;
3236+ const std::string relativeOrAbsoluteFilename = getRelativeFileName (sourcefile, header);// unknown if absolute or relative, but always simplified
3237+ const std::string match = findPathInMapBothRelativeAndAbsolute (filedata, relativeOrAbsoluteFilename);
3238+ if (!match.empty ()) {
3239+ return match;
3240+ }
31613241 }
31623242
31633243 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;
3244+ const std::string match = findPathInMapBothRelativeAndAbsolute (filedata, simplecpp::simplifyPath (getIncludePathFileName (*it, header)));
3245+ if (!match.empty ()) {
3246+ return match;
3247+ }
31673248 }
31683249
31693250 if (systemheader && filedata.find (header) != filedata.end ())
3170- return header;
3251+ return header;// system header that its file wasn't found in the included paths but alreasy in the filedata - return this as is
31713252
31723253 return " " ;
31733254}
31743255
31753256static bool hasFile (const std::map<std::string, simplecpp::TokenList *> &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader)
31763257{
3177- return !getFileName (filedata, sourcefile, header, dui, systemheader).empty ();
3258+ return !getFileIdPath (filedata, sourcefile, header, dui, systemheader).empty ();
31783259}
31793260
31803261std::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 +3611,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
35303611
35313612 const bool systemheader = (inctok->str ()[0 ] == ' <' );
35323613 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);
3614+ std::string header2 = getFileIdPath (filedata, rawtok->location .file (), header, dui, systemheader);
35343615 if (header2.empty ()) {
35353616 // try to load file..
35363617 std::ifstream f;
0 commit comments