Index: include/lldb/Host/FileSpec.h =================================================================== --- include/lldb/Host/FileSpec.h +++ include/lldb/Host/FileSpec.h @@ -51,6 +51,13 @@ eFileTypeOther } FileType; + enum PathSyntax + { + ePathSyntaxPosix, + ePathSyntaxWindows, + ePathSyntaxHostNative + }; + FileSpec(); //------------------------------------------------------------------ @@ -69,7 +76,7 @@ /// /// @see FileSpec::SetFile (const char *path, bool resolve) //------------------------------------------------------------------ - explicit FileSpec (const char *path, bool resolve_path); + explicit FileSpec (const char *path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); //------------------------------------------------------------------ /// Copy constructor @@ -291,6 +298,9 @@ uint64_t GetByteSize() const; + PathSyntax + GetPathSyntax() const; + //------------------------------------------------------------------ /// Directory string get accessor. /// @@ -375,7 +385,7 @@ /// still NULL terminated). //------------------------------------------------------------------ size_t - GetPath (char *path, size_t max_path_length) const; + GetPath (char *path, size_t max_path_length, bool denormalize = true) const; //------------------------------------------------------------------ /// Extract the full path to the file. @@ -387,7 +397,7 @@ /// concatenated. //------------------------------------------------------------------ std::string - GetPath () const; + GetPath (bool denormalize = true) const; //------------------------------------------------------------------ /// Extract the extension of the file. @@ -559,6 +569,11 @@ //------------------------------------------------------------------ lldb::DataBufferSP ReadFileContentsAsCString(Error *error_ptr = NULL); + + static std::string Normalize(const char *path, PathSyntax syntax); + static std::string DeNormalize(const char *path, PathSyntax syntax); + static void DeNormalize(char *path, PathSyntax syntax); + //------------------------------------------------------------------ /// Change the file specified with a new path. /// @@ -574,7 +589,7 @@ /// the static FileSpec::Resolve. //------------------------------------------------------------------ void - SetFile (const char *path, bool resolve_path); + SetFile (const char *path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); bool IsResolved () const @@ -709,6 +724,7 @@ ConstString m_directory; ///< The uniqued directory path ConstString m_filename; ///< The uniqued filename path mutable bool m_is_resolved; ///< True if this path has been resolved. + PathSyntax m_syntax; ///< The syntax that this path uses (e.g. Windows / Posix) }; //---------------------------------------------------------------------- Index: include/lldb/Host/Host.h =================================================================== --- include/lldb/Host/Host.h +++ include/lldb/Host/Host.h @@ -362,6 +362,15 @@ SetShortThreadName (lldb::pid_t pid, lldb::tid_t tid, const char *name, size_t len); //------------------------------------------------------------------ + /// Gets the host environment's native path syntax (Windows / Posix). + /// + /// @return + /// \b One of {FileSpec::ePathSyntaxWindows, FileSpec::ePathSyntaxPosix} + //------------------------------------------------------------------ + static FileSpec::PathSyntax + GetHostPathSyntax(); + + //------------------------------------------------------------------ /// Gets the FileSpec of the user profile directory. On Posix-platforms /// this is ~, and on windows this is generally something like /// C:\Users\Alice. Index: source/Host/common/FileSpec.cpp =================================================================== --- source/Host/common/FileSpec.cpp +++ source/Host/common/FileSpec.cpp @@ -237,13 +237,13 @@ // Default constructor that can take an optional full path to a // file on disk. //------------------------------------------------------------------ -FileSpec::FileSpec(const char *pathname, bool resolve_path) : +FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) : m_directory(), m_filename(), m_is_resolved(false) { if (pathname && pathname[0]) - SetFile(pathname, resolve_path); + SetFile(pathname, resolve_path, syntax); } //------------------------------------------------------------------ @@ -289,42 +289,71 @@ return *this; } +std::string FileSpec::Normalize(const char *path, PathSyntax syntax) +{ + if (syntax == ePathSyntaxPosix || (syntax == ePathSyntaxHostNative && Host::GetHostPathSyntax() == ePathSyntaxPosix)) + return path; + std::string result(path); + std::replace(result.begin(), result.end(), '\\', '/'); + return result; +} + +std::string FileSpec::DeNormalize(const char *path, PathSyntax syntax) +{ + if (syntax == ePathSyntaxPosix || (syntax == ePathSyntaxHostNative && Host::GetHostPathSyntax() == ePathSyntaxPosix)) + return path; + std::string result(path); + std::replace(result.begin(), result.end(), '/', '\\'); + return result; +} + +void FileSpec::DeNormalize(char *path, PathSyntax syntax) +{ + if (syntax == ePathSyntaxPosix || (syntax == ePathSyntaxHostNative && Host::GetHostPathSyntax() == ePathSyntaxPosix)) + return; + int len = ::strlen(path); + std::replace(path, path+len, '/', '\\'); +} + //------------------------------------------------------------------ // Update the contents of this object with a new path. The path will // be split up into a directory and filename and stored as uniqued // string values for quick comparison and efficient memory usage. //------------------------------------------------------------------ void -FileSpec::SetFile (const char *pathname, bool resolve) +FileSpec::SetFile (const char *pathname, bool resolve, PathSyntax syntax) { m_filename.Clear(); m_directory.Clear(); m_is_resolved = false; + m_syntax = (syntax == ePathSyntaxHostNative) ? Host::GetHostPathSyntax() : syntax; + if (pathname == NULL || pathname[0] == '\0') return; - char resolved_path[PATH_MAX]; + std::string normalized(Normalize(pathname, syntax)); + + std::vector resolved_path(PATH_MAX); bool path_fit = true; if (resolve) { - path_fit = (FileSpec::Resolve (pathname, resolved_path, sizeof(resolved_path)) < sizeof(resolved_path) - 1); + path_fit = (FileSpec::Resolve (normalized.c_str(), &resolved_path[0], resolved_path.size()) < resolved_path.size() - 1); m_is_resolved = path_fit; } else { // Copy the path because "basename" and "dirname" want to muck with the // path buffer - if (::strlen (pathname) > sizeof(resolved_path) - 1) + if (normalized.length() > resolved_path.size() - 1) path_fit = false; else - ::strcpy (resolved_path, pathname); + ::strcpy (&resolved_path[0], normalized.c_str()); } - if (path_fit) { - llvm::StringRef resolve_path_ref(resolved_path); + llvm::StringRef resolve_path_ref(&resolved_path[0]); llvm::StringRef filename_ref = llvm::sys::path::filename(resolve_path_ref); if (!filename_ref.empty()) { @@ -334,7 +363,7 @@ m_directory.SetString(directory_ref); } else - m_directory.SetCString(resolved_path); + m_directory.SetCString(&resolved_path[0]); } } @@ -580,7 +609,7 @@ return true; // We have already resolved this path char path_buf[PATH_MAX]; - if (!GetPath (path_buf, PATH_MAX)) + if (!GetPath (path_buf, PATH_MAX, false)) return false; // SetFile(...) will set m_is_resolved correctly if it can resolve the path SetFile (path_buf, true); @@ -681,8 +710,9 @@ // values. //------------------------------------------------------------------ size_t -FileSpec::GetPath(char *path, size_t path_max_len) const +FileSpec::GetPath(char *path, size_t path_max_len, bool denormalize) const { + size_t result = 0; if (path_max_len) { const char *dirname = m_directory.GetCString(); @@ -690,22 +720,24 @@ if (dirname) { if (filename) - return ::snprintf (path, path_max_len, "%s/%s", dirname, filename); + result = ::snprintf (path, path_max_len, "%s/%s", dirname, filename); else - return ::snprintf (path, path_max_len, "%s", dirname); + result = ::snprintf (path, path_max_len, "%s", dirname); } else if (filename) { - return ::snprintf (path, path_max_len, "%s", filename); + result = ::snprintf (path, path_max_len, "%s", filename); } } - if (path) + if (result == 0 && path) path[0] = '\0'; - return 0; + if (denormalize) + DeNormalize(path, m_syntax); + return result; } std::string -FileSpec::GetPath (void) const +FileSpec::GetPath (bool denormalize) const { static ConstString g_slash_only ("/"); std::string path; @@ -719,6 +751,10 @@ } if (filename) path.append (filename); + + if (denormalize) + path = DeNormalize(path.c_str(), m_syntax); + return path; } Index: source/Host/common/Host.cpp =================================================================== --- source/Host/common/Host.cpp +++ source/Host/common/Host.cpp @@ -825,6 +825,16 @@ #endif +FileSpec::PathSyntax +Host::GetHostPathSyntax() +{ +#if defined(_WIN32) + return FileSpec::ePathSyntaxWindows; +#else + return FileSpec::ePathSyntaxPosix; +#endif +} + FileSpec Host::GetUserProfileFileSpec () { @@ -881,7 +891,7 @@ #elif defined(_WIN32) std::vector buffer(PATH_MAX); ::GetModuleFileName(NULL, &buffer[0], buffer.size()); - g_program_filespec.SetFile(&buffer[0], false, FileSpec::ePathSyntaxWindows); + g_program_filespec.SetFile(&buffer[0], false); #endif } return g_program_filespec;