@@ -2719,14 +2719,42 @@ static std::string toAbsolutePath(const std::string& path) {
27192719 return simplecpp::simplifyPath (path);
27202720}
27212721
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 );
2722+ static std::string dirPath (const std::string& path, bool withTrailingSlash=true ) {
2723+ const std::size_t lastSlash = path.find_last_of (" \\ /" );
2724+ if (lastSlash == std::string::npos) {
2725+ return " " ;
27272726 }
2728- // otherwise
2729- return std::make_pair (" " , false );
2727+ return path.substr (0 , lastSlash + (withTrailingSlash ? 1U : 0U ));
2728+ }
2729+
2730+ static std::string omitPathTrailingSlash (const std::string& path) {
2731+ if (endsWith (path, " /" )) {
2732+ return path.substr (0 , path.size () - 1U );
2733+ }
2734+ return path;
2735+ }
2736+
2737+ static std::string extractRelativePathFromAbsolute (const std::string& absoluteSimplifiedPath, const std::string& prefixSimplifiedAbsoluteDir = currentDirectory()) {
2738+ const std::string normalizedAbsolutePath = omitPathTrailingSlash (absoluteSimplifiedPath);
2739+ std::string currentPrefix = omitPathTrailingSlash (prefixSimplifiedAbsoluteDir);
2740+ std::string leadingParenting;
2741+ while (!startsWith_ (normalizedAbsolutePath, currentPrefix)) {
2742+ leadingParenting = " ../" + leadingParenting;
2743+ currentPrefix = dirPath (currentPrefix, false );
2744+ }
2745+ const std::size_t size = currentPrefix.size ();
2746+ std::string relativeFromMeetingPath = normalizedAbsolutePath.substr (size, normalizedAbsolutePath.size () - size);
2747+ if (currentPrefix.empty () && !(startsWith_ (absoluteSimplifiedPath, " /" ) && startsWith_ (prefixSimplifiedAbsoluteDir, " /" ))) {
2748+ // In the case that there is no common prefix path,
2749+ // and at not both of the paths start with `/` (can happen only in Windows paths on distinct partitions),
2750+ // return the absolute simplified path as is because no relative path can match.
2751+ return absoluteSimplifiedPath;
2752+ }
2753+ if (startsWith_ (relativeFromMeetingPath, " /" )) {
2754+ // omit the leading slash
2755+ relativeFromMeetingPath = relativeFromMeetingPath.substr (1 , relativeFromMeetingPath.size ());
2756+ }
2757+ return leadingParenting + relativeFromMeetingPath;
27302758}
27312759
27322760static std::string openHeader (std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader);
@@ -3147,12 +3175,17 @@ static std::string openHeader(std::ifstream &f, const std::string &path)
31473175
31483176static std::string getRelativeFileName (const std::string &baseFile, const std::string &header)
31493177{
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);
3178+ const std::string baseFileSimplified = simplecpp::simplifyPath (baseFile);
3179+ const std::string baseFileAbsolute = isAbsolutePath (baseFileSimplified) ?
3180+ baseFileSimplified :
3181+ simplecpp::simplifyPath (currentDirectory () + " /" + baseFileSimplified);
3182+
3183+ const std::string headerSimplified = simplecpp::simplifyPath (header);
3184+ const std::string path = isAbsolutePath (headerSimplified) ?
3185+ headerSimplified :
3186+ simplecpp::simplifyPath (dirPath (baseFileAbsolute) + headerSimplified);
3187+
3188+ return extractRelativePathFromAbsolute (path);
31563189}
31573190
31583191static std::string openHeaderRelative (std::ifstream &f, const std::string &sourcefile, const std::string &header)
@@ -3174,8 +3207,9 @@ static std::string getIncludePathFileName(const std::string &includePath, const
31743207 std::string basePath = toAbsolutePath (includePath);
31753208 if (!basePath.empty () && basePath[basePath.size ()-1U ]!=' /' && basePath[basePath.size ()-1U ]!=' \\ ' )
31763209 basePath += ' /' ;
3177- const std::string absolutesimplifiedHeaderPath = basePath + simplifiedHeader;
3178- return extractRelativePathFromAbsolute (absolutesimplifiedHeaderPath).first ;
3210+ const std::string absoluteSimplifiedHeaderPath = simplecpp::simplifyPath (basePath + simplifiedHeader);
3211+ // preserve absoluteness/relativieness of the including dir
3212+ return isAbsolutePath (includePath) ? absoluteSimplifiedHeaderPath : extractRelativePathFromAbsolute (absoluteSimplifiedHeaderPath);
31793213}
31803214
31813215static std::string openHeaderIncludePath (std::ifstream &f, const simplecpp::DUI &dui, const std::string &header)
@@ -3210,22 +3244,18 @@ static std::string findPathInMapBothRelativeAndAbsolute(const std::map<std::stri
32103244 if (filedata.find (path) != filedata.end ()) {// try first to respect the exact match
32113245 return path;
32123246 }
3247+
32133248 // otherwise - try to use the normalize to the correct representation
3249+ std::string alternativePath;
32143250 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- }
3251+ alternativePath = extractRelativePathFromAbsolute (simplecpp::simplifyPath (path));
32223252 } else {
3223- const std::string absolutePath = toAbsolutePath (path);
3224- if (filedata.find (absolutePath) != filedata.end ()) {
3225- return absolutePath;
3226- }
3253+ alternativePath = toAbsolutePath (path);
3254+ }
3255+
3256+ if (filedata.find (alternativePath) != filedata.end ()) {
3257+ return alternativePath;
32273258 }
3228- // otherwise
32293259 return " " ;
32303260}
32313261
@@ -3267,6 +3297,16 @@ static bool hasFile(const std::map<std::string, simplecpp::TokenList *> &filedat
32673297 return !getFileIdPath (filedata, sourcefile, header, dui, systemheader).empty ();
32683298}
32693299
3300+ static void safeInsertTokenListToMap (std::map<std::string, simplecpp::TokenList *> &filedata, const std::string &header2, simplecpp::TokenList *tokens, const std::string &header, const std::string &sourcefile, bool systemheader, const char * contextDesc)
3301+ {
3302+ const bool inserted = filedata.insert (std::make_pair (header2, tokens)).second ;
3303+ if (!inserted) {
3304+ std::cerr << " error in " << contextDesc << " - attempt to add a tokenized file to the file map, but this file is already in the map! Details:" <<
3305+ " header: " << header << " header2: " << header2 << " source: " << sourcefile << " systemheader: " << systemheader << std::endl;
3306+ std::abort ();
3307+ }
3308+ }
3309+
32703310std::map<std::string, simplecpp::TokenList*> simplecpp::load (const simplecpp::TokenList &rawtokens, std::vector<std::string> &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList)
32713311{
32723312#ifdef SIMPLECPP_WINDOWS
@@ -3343,7 +3383,7 @@ std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::To
33433383 TokenList *tokens = new TokenList (header2, filenames, outputList);
33443384 if (dui.removeComments )
33453385 tokens->removeComments ();
3346- ret[ header2] = tokens;
3386+ safeInsertTokenListToMap ( ret, header2, tokens, header, rawtok-> location . file (), systemheader, " simplecpp::load " ) ;
33473387 if (tokens->front ())
33483388 filelist.push_back (tokens->front ());
33493389 }
@@ -3630,7 +3670,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
36303670 TokenList * const tokens = new TokenList (header2, files, outputList);
36313671 if (dui.removeComments )
36323672 tokens->removeComments ();
3633- filedata[ header2] = tokens;
3673+ safeInsertTokenListToMap ( filedata, header2, tokens, header, rawtok-> location . file (), systemheader, " simplecpp::preprocess " ) ;
36343674 }
36353675 }
36363676 if (header2.empty ()) {
0 commit comments