Index: examples/plugins/commands/fooplugin.cpp =================================================================== --- examples/plugins/commands/fooplugin.cpp +++ examples/plugins/commands/fooplugin.cpp @@ -25,8 +25,8 @@ class ChildCommand : public lldb::SBCommandPluginInterface { public: - virtual bool DoExecute(lldb::SBDebugger debugger, char **command, - lldb::SBCommandReturnObject &result) { + bool DoExecute(lldb::SBDebugger debugger, const char **command, + lldb::SBCommandReturnObject &result) override { if (command) { const char *arg = *command; while (arg) { Index: include/lldb/API/SBCommandInterpreter.h =================================================================== --- include/lldb/API/SBCommandInterpreter.h +++ include/lldb/API/SBCommandInterpreter.h @@ -233,7 +233,8 @@ public: virtual ~SBCommandPluginInterface() = default; - virtual bool DoExecute(lldb::SBDebugger /*debugger*/, char ** /*command*/, + virtual bool DoExecute(lldb::SBDebugger /*debugger*/, + const char ** /*command*/, lldb::SBCommandReturnObject & /*result*/) { return false; } Index: include/lldb/Host/FileSpec.h =================================================================== --- include/lldb/Host/FileSpec.h +++ include/lldb/Host/FileSpec.h @@ -80,16 +80,10 @@ /// /// @see FileSpec::SetFile (const char *path, bool resolve) //------------------------------------------------------------------ - // TODO: Convert this constructor to use a StringRef. - explicit FileSpec(const char *path, bool resolve_path, + explicit FileSpec(llvm::StringRef path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); - explicit FileSpec(const char *path, bool resolve_path, ArchSpec arch); - - explicit FileSpec(const std::string &path, bool resolve_path, - PathSyntax syntax = ePathSyntaxHostNative); - - explicit FileSpec(const std::string &path, bool resolve_path, ArchSpec arch); + explicit FileSpec(llvm::StringRef path, bool resolve_path, ArchSpec arch); //------------------------------------------------------------------ /// Copy constructor @@ -657,15 +651,10 @@ /// If \b true, then we will try to resolve links the path using /// the static FileSpec::Resolve. //------------------------------------------------------------------ - void SetFile(const char *path, bool resolve_path, - PathSyntax syntax = ePathSyntaxHostNative); - - void SetFile(const char *path, bool resolve_path, ArchSpec arch); - - void SetFile(const std::string &path, bool resolve_path, + void SetFile(llvm::StringRef path, bool resolve_path, PathSyntax syntax = ePathSyntaxHostNative); - void SetFile(const std::string &path, bool resolve_path, ArchSpec arch); + void SetFile(llvm::StringRef path, bool resolve_path, ArchSpec arch); bool IsResolved() const { return m_is_resolved; } @@ -709,20 +698,13 @@ //------------------------------------------------------------------ static void Resolve(llvm::SmallVectorImpl &path); - FileSpec CopyByAppendingPathComponent(const char *new_path) const; - + FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const; FileSpec CopyByRemovingLastPathComponent() const; - void PrependPathComponent(const char *new_path); - - void PrependPathComponent(const std::string &new_path); - + void PrependPathComponent(llvm::StringRef component); void PrependPathComponent(const FileSpec &new_path); - void AppendPathComponent(const char *new_path); - - void AppendPathComponent(const std::string &new_path); - + void AppendPathComponent(llvm::StringRef component); void AppendPathComponent(const FileSpec &new_path); void RemoveLastPathComponent(); @@ -746,7 +728,7 @@ //------------------------------------------------------------------ static void ResolveUsername(llvm::SmallVectorImpl &path); - static size_t ResolvePartialUsername(const char *partial_name, + static size_t ResolvePartialUsername(llvm::StringRef partial_name, StringList &matches); enum EnumerateDirectoryResult { @@ -763,7 +745,7 @@ void *baton, FileType file_type, const FileSpec &spec); static EnumerateDirectoryResult - EnumerateDirectory(const char *dir_path, bool find_directories, + EnumerateDirectory(llvm::StringRef dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton); @@ -773,7 +755,7 @@ DirectoryCallback; static EnumerateDirectoryResult - ForEachItemInDirectory(const char *dir_path, + ForEachItemInDirectory(llvm::StringRef dir_path, DirectoryCallback const &callback); protected: Index: include/lldb/Host/OptionParser.h =================================================================== --- include/lldb/Host/OptionParser.h +++ include/lldb/Host/OptionParser.h @@ -36,7 +36,7 @@ static void EnableError(bool error); - static int Parse(int argc, char *const argv[], const char *optstring, + static int Parse(int argc, char const *const argv[], const char *optstring, const Option *longopts, int *longindex); static char *GetOptionArgument(); Index: include/lldb/Interpreter/Args.h =================================================================== --- include/lldb/Interpreter/Args.h +++ include/lldb/Interpreter/Args.h @@ -18,7 +18,9 @@ #include // Other libraries and framework includes +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" + // Project includes #include "lldb/Core/Error.h" #include "lldb/Host/OptionParser.h" @@ -146,26 +148,10 @@ /// \endcode /// /// @return - /// An array of NULL terminated C string argument pointers that - /// also has a terminating NULL C string pointer - //------------------------------------------------------------------ - char **GetArgumentVector(); - - //------------------------------------------------------------------ - /// Gets the argument vector. - /// - /// The value returned by this function can be used by any function - /// that takes and vector. The return value is just like \a argv - /// in the standard C entry point function: - /// \code - /// int main (int argc, const char **argv); - /// \endcode - /// - /// @return /// An array of NULL terminate C string argument pointers that /// also has a terminating NULL C string pointer //------------------------------------------------------------------ - const char **GetConstArgumentVector() const; + void GetArgumentVector(std::vector &args) const; //------------------------------------------------------------------ /// Appends a new argument to the end of the list argument list. @@ -183,52 +169,7 @@ char quote_char = '\0'); void AppendArguments(const Args &rhs); - - void AppendArguments(const char **argv); - - // Delete const char* versions of StringRef functions. Normally this would - // not be necessary, as const char * is implicitly convertible to StringRef. - // However, since the use of const char* is so pervasive, and since StringRef - // will assert if you try to construct one from nullptr, this allows the - // compiler to catch instances of the function being invoked with a - // const char *, allowing us to replace them with explicit conversions at each - // call-site. This ensures that no callsites slip through the cracks where - // we would be trying to implicitly convert from nullptr, since it will force - // us to evaluate and explicitly convert each one. - // - // Once StringRef use becomes more pervasive, there will be fewer - // implicit conversions because we will be using StringRefs across the whole - // pipeline, so we won't have to have this "glue" that converts between the - // two, and at that point it becomes easy to just make sure you don't pass - // nullptr into the function on the odd occasion that you do pass a - // const char *. - // Call-site fixing methodology: - // 1. If you know the string cannot be null (e.g. it's a const char[], or - // it's been checked for null), use llvm::StringRef(ptr). - // 2. If you don't know if it can be null (e.g. it's returned from a - // function whose semantics are unclear), use - // llvm::StringRef::withNullAsEmpty(ptr). - // 3. If it's .c_str() of a std::string, just pass the std::string directly. - // 4. If it's .str().c_str() of a StringRef, just pass the StringRef - // directly. - void ReplaceArgumentAtIndex(size_t, const char *, char = '\0') = delete; - void AppendArgument(const char *arg_str, char quote_char = '\0') = delete; - void InsertArgumentAtIndex(size_t, const char *, char = '\0') = delete; - static bool StringToBoolean(const char *, bool, bool *) = delete; - static lldb::ScriptLanguage - StringToScriptLanguage(const char *, lldb::ScriptLanguage, bool *) = delete; - static lldb::Encoding - StringToEncoding(const char *, - lldb::Encoding = lldb::eEncodingInvalid) = delete; - static uint32_t StringToGenericRegister(const char *) = delete; - static bool StringToVersion(const char *, uint32_t &, uint32_t &, - uint32_t &) = delete; - const char *Unshift(const char *, char = '\0') = delete; - void AddOrReplaceEnvironmentVariable(const char *, const char *) = delete; - bool ContainsEnvironmentVariable(const char *, - size_t * = nullptr) const = delete; - static int64_t StringToOptionEnum(const char *, OptionEnumValueElement *, - int32_t, Error &) = delete; + void AppendArguments(llvm::ArrayRef args); //------------------------------------------------------------------ /// Insert the argument value at index \a idx to \a arg_cstr. @@ -287,9 +228,8 @@ // // FIXME: Handle the quote character somehow. //------------------------------------------------------------------ - void SetArguments(size_t argc, const char **argv); - - void SetArguments(const char **argv); + void SetArguments(llvm::ArrayRef args); + void SetArguments(const Args &other); //------------------------------------------------------------------ /// Shifts the first argument C string value of the array off the @@ -413,6 +353,8 @@ OptionEnumValueElement *enum_values, int32_t fail_value, Error &error); + static llvm::ArrayRef ArgvToArrayRef(const char **args); + static lldb::ScriptLanguage StringToScriptLanguage(llvm::StringRef s, lldb::ScriptLanguage fail_value, bool *success_ptr); @@ -497,16 +439,12 @@ //------------------------------------------------------------------ // Classes that inherit from Args can see and modify these //------------------------------------------------------------------ - typedef std::list arg_sstr_collection; - typedef std::vector arg_cstr_collection; + typedef std::vector arg_sstr_collection; typedef std::vector arg_quote_char_collection; arg_sstr_collection m_args; - arg_cstr_collection m_argv; ///< The current argument vector. arg_quote_char_collection m_args_quote_char; - void UpdateArgsAfterOptionParsing(); - - void UpdateArgvFromArgs(); + void UpdateArgsAfterOptionParsing(llvm::ArrayRef new_argv); llvm::StringRef ParseSingleArgument(llvm::StringRef command); }; Index: source/API/SBCommandInterpreter.cpp =================================================================== --- source/API/SBCommandInterpreter.cpp +++ source/API/SBCommandInterpreter.cpp @@ -115,8 +115,9 @@ SBCommandReturnObject sb_return(&result); SBCommandInterpreter sb_interpreter(&m_interpreter); SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); - bool ret = m_backend->DoExecute( - debugger_sb, (char **)command.GetArgumentVector(), sb_return); + std::vector argv; + command.GetArgumentVector(argv); + bool ret = m_backend->DoExecute(debugger_sb, &argv[0], sb_return); sb_return.Release(); return ret; } Index: source/API/SBLaunchInfo.cpp =================================================================== --- source/API/SBLaunchInfo.cpp +++ source/API/SBLaunchInfo.cpp @@ -19,8 +19,9 @@ SBLaunchInfo::SBLaunchInfo(const char **argv) : m_opaque_sp(new ProcessLaunchInfo()) { m_opaque_sp->GetFlags().Reset(eLaunchFlagDebug | eLaunchFlagDisableASLR); - if (argv && argv[0]) - m_opaque_sp->GetArguments().SetArguments(argv); + if (argv) { + m_opaque_sp->GetArguments().SetArguments(Args::ArgvToArrayRef(argv)); + } } SBLaunchInfo::~SBLaunchInfo() {} @@ -71,15 +72,11 @@ } void SBLaunchInfo::SetArguments(const char **argv, bool append) { - if (append) { - if (argv) - m_opaque_sp->GetArguments().AppendArguments(argv); - } else { - if (argv) - m_opaque_sp->GetArguments().SetArguments(argv); - else - m_opaque_sp->GetArguments().Clear(); - } + if (!append) + m_opaque_sp->GetArguments().Clear(); + + if (argv) + m_opaque_sp->GetArguments().AppendArguments(Args::ArgvToArrayRef(argv)); } uint32_t SBLaunchInfo::GetNumEnvironmentEntries() { @@ -91,15 +88,12 @@ } void SBLaunchInfo::SetEnvironmentEntries(const char **envp, bool append) { - if (append) { - if (envp) - m_opaque_sp->GetEnvironmentEntries().AppendArguments(envp); - } else { - if (envp) - m_opaque_sp->GetEnvironmentEntries().SetArguments(envp); - else - m_opaque_sp->GetEnvironmentEntries().Clear(); - } + if (!append) + m_opaque_sp->GetEnvironmentEntries().Clear(); + + if (envp) + m_opaque_sp->GetEnvironmentEntries().AppendArguments( + Args::ArgvToArrayRef(envp)); } void SBLaunchInfo::Clear() { m_opaque_sp->Clear(); } Index: source/API/SBProcess.cpp =================================================================== --- source/API/SBProcess.cpp +++ source/API/SBProcess.cpp @@ -136,9 +136,10 @@ if (exe_module) launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); if (argv) - launch_info.GetArguments().AppendArguments(argv); + launch_info.GetArguments().AppendArguments(Args::ArgvToArrayRef(argv)); if (envp) - launch_info.GetEnvironmentEntries().SetArguments(envp); + launch_info.GetEnvironmentEntries().SetArguments( + Args::ArgvToArrayRef(envp)); error.SetError(process_sp->Launch(launch_info)); } else { error.SetErrorString("must be in eStateConnected to call RemoteLaunch"); Index: source/API/SBTarget.cpp =================================================================== --- source/API/SBTarget.cpp +++ source/API/SBTarget.cpp @@ -287,9 +287,10 @@ if (exe_module) launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); if (argv) - launch_info.GetArguments().AppendArguments(argv); + launch_info.GetArguments().AppendArguments(Args::ArgvToArrayRef(argv)); if (envp) - launch_info.GetEnvironmentEntries().SetArguments(envp); + launch_info.GetEnvironmentEntries().SetArguments( + Args::ArgvToArrayRef(envp)); if (listener.IsValid()) launch_info.SetListener(listener.GetSP()); Index: source/Commands/CommandObjectBreakpoint.cpp =================================================================== --- source/Commands/CommandObjectBreakpoint.cpp +++ source/Commands/CommandObjectBreakpoint.cpp @@ -2423,8 +2423,9 @@ // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual // BreakpointIDList: - valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(), - temp_args.GetArgumentCount(), result); + std::vector argv; + temp_args.GetArgumentVector(argv); + valid_ids->InsertStringArray(&argv[0], temp_args.GetArgumentCount(), result); // At this point, all of the breakpoint ids that the user passed in have been // converted to breakpoint IDs Index: source/Commands/CommandObjectLog.cpp =================================================================== --- source/Commands/CommandObjectLog.cpp +++ source/Commands/CommandObjectLog.cpp @@ -190,9 +190,11 @@ m_options.log_file.GetPath(log_file, sizeof(log_file)); else log_file[0] = '\0'; + std::vector argv; + args.GetArgumentVector(argv); bool success = m_interpreter.GetDebugger().EnableLog( - channel.c_str(), args.GetConstArgumentVector(), log_file, - m_options.log_options, result.GetErrorStream()); + channel.c_str(), &argv[0], log_file, m_options.log_options, + result.GetErrorStream()); if (success) result.SetStatus(eReturnStatusSuccessFinishNoResult); else @@ -250,18 +252,19 @@ std::string channel(args.GetArgumentAtIndex(0)); args.Shift(); // Shift off the channel + std::vector argv; + args.GetArgumentVector(argv); + if (Log::GetLogChannelCallbacks(ConstString(channel.c_str()), log_callbacks)) { - log_callbacks.disable(args.GetConstArgumentVector(), - &result.GetErrorStream()); + log_callbacks.disable(&argv[0], &result.GetErrorStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else if (channel == "all") { Log::DisableAllLogChannels(&result.GetErrorStream()); } else { LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel.c_str())); if (log_channel_sp) { - log_channel_sp->Disable(args.GetConstArgumentVector(), - &result.GetErrorStream()); + log_channel_sp->Disable(&argv[0], &result.GetErrorStream()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } else result.AppendErrorWithFormat("Invalid log channel '%s'.\n", Index: source/Host/common/FileSpec.cpp =================================================================== --- source/Host/common/FileSpec.cpp +++ source/Host/common/FileSpec.cpp @@ -37,6 +37,7 @@ #include "lldb/Host/Host.h" #include "lldb/Utility/CleanUp.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/FileSystem.h" @@ -228,27 +229,27 @@ #endif } -size_t FileSpec::ResolvePartialUsername(const char *partial_name, +size_t FileSpec::ResolvePartialUsername(llvm::StringRef partial_name, StringList &matches) { #ifdef LLDB_CONFIG_TILDE_RESOLVES_TO_USER size_t extant_entries = matches.GetSize(); setpwent(); struct passwd *user_entry; - const char *name_start = partial_name + 1; + partial_name = partial_name.drop_front(); std::set name_list; while ((user_entry = getpwent()) != NULL) { - if (strstr(user_entry->pw_name, name_start) == user_entry->pw_name) { + if (llvm::StringRef(user_entry->pw_name).startswith(partial_name)) { std::string tmp_buf("~"); tmp_buf.append(user_entry->pw_name); tmp_buf.push_back('/'); name_list.insert(tmp_buf); } } - std::set::iterator pos, end = name_list.end(); - for (pos = name_list.begin(); pos != end; pos++) { - matches.AppendString((*pos).c_str()); + + for (auto &name : name_list) { + matches.AppendString(name); } return matches.GetSize() - extant_entries; #else @@ -284,23 +285,15 @@ // Default constructor that can take an optional full path to a // file on disk. //------------------------------------------------------------------ -FileSpec::FileSpec(const char *pathname, bool resolve_path, PathSyntax syntax) +FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, PathSyntax syntax) : m_directory(), m_filename(), m_is_resolved(false), m_syntax(syntax) { - if (pathname && pathname[0]) - SetFile(pathname, resolve_path, syntax); + SetFile(path, resolve_path, syntax); } -FileSpec::FileSpec(const char *pathname, bool resolve_path, ArchSpec arch) - : FileSpec{pathname, resolve_path, arch.GetTriple().isOSWindows() - ? ePathSyntaxWindows - : ePathSyntaxPosix} {} - -FileSpec::FileSpec(const std::string &path, bool resolve_path, - PathSyntax syntax) - : FileSpec{path.c_str(), resolve_path, syntax} {} - -FileSpec::FileSpec(const std::string &path, bool resolve_path, ArchSpec arch) - : FileSpec{path.c_str(), resolve_path, arch} {} +FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, ArchSpec arch) + : FileSpec{path, resolve_path, arch.GetTriple().isOSWindows() + ? ePathSyntaxWindows + : ePathSyntaxPosix} {} //------------------------------------------------------------------ // Copy constructor @@ -340,7 +333,12 @@ // 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, PathSyntax syntax) { +void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, + PathSyntax syntax) { + // CLEANUP: Use StringRef for string handling. This function is kind of a + // mess and the unclear semantics of RootDirStart and ParentPathEnd make + // it very difficult to understand this function. There's no reason this + // function should be particularly complicated or difficult to understand. m_filename.Clear(); m_directory.Clear(); m_is_resolved = false; @@ -348,7 +346,7 @@ ? FileSystem::GetNativePathSyntax() : syntax; - if (pathname == NULL || pathname[0] == '\0') + if (pathname.empty()) return; llvm::SmallString<64> resolved(pathname); @@ -382,20 +380,10 @@ : resolve_path_ref.substr(filename_begin)); } -void FileSpec::SetFile(const char *pathname, bool resolve, ArchSpec arch) { - return SetFile(pathname, resolve, arch.GetTriple().isOSWindows() - ? ePathSyntaxWindows - : ePathSyntaxPosix); -} - -void FileSpec::SetFile(const std::string &pathname, bool resolve, - PathSyntax syntax) { - return SetFile(pathname.c_str(), resolve, syntax); -} - -void FileSpec::SetFile(const std::string &pathname, bool resolve, - ArchSpec arch) { - return SetFile(pathname.c_str(), resolve, arch); +void FileSpec::SetFile(llvm::StringRef path, bool resolve, ArchSpec arch) { + return SetFile(path, resolve, arch.GetTriple().isOSWindows() + ? ePathSyntaxWindows + : ePathSyntaxPosix); } //---------------------------------------------------------------------- @@ -692,6 +680,7 @@ } bool FileSpec::ResolveExecutableLocation() { + // CLEANUP: Use StringRef for string handling. if (!m_directory) { const char *file_cstr = m_filename.GetCString(); if (file_cstr) { @@ -1023,9 +1012,11 @@ } FileSpec::EnumerateDirectoryResult -FileSpec::ForEachItemInDirectory(const char *dir_path, +FileSpec::ForEachItemInDirectory(llvm::StringRef dir_path, DirectoryCallback const &callback) { - if (dir_path && dir_path[0]) { + if (dir_path.empty()) + return eEnumerateDirectoryResultNext; + #ifdef _WIN32 std::string szDir(dir_path); szDir += "\\*"; @@ -1065,55 +1056,51 @@ continue; } - std::vector child_path(PATH_MAX); - const int child_path_len = - ::snprintf(child_path.data(), child_path.size(), "%s\\%s", dir_path, - fileName.c_str()); - if (child_path_len < (int)(child_path.size() - 1)) { - // Don't resolve the file type or path - FileSpec child_path_spec(child_path.data(), false); - - EnumerateDirectoryResult result = callback(file_type, child_path_spec); - - switch (result) { - case eEnumerateDirectoryResultNext: - // Enumerate next entry in the current directory. We just - // exit this switch and will continue enumerating the - // current directory as we currently are... - break; + std::string child_path = llvm::join_items("\\", dir_path, fileName); + // Don't resolve the file type or path + FileSpec child_path_spec(child_path.data(), false); - case eEnumerateDirectoryResultEnter: // Recurse into the current entry - // if it is a directory or symlink, - // or next if not - if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == - eEnumerateDirectoryResultQuit) { - // The subdirectory returned Quit, which means to - // stop all directory enumerations at all levels. - return eEnumerateDirectoryResultQuit; - } - break; + EnumerateDirectoryResult result = callback(file_type, child_path_spec); - case eEnumerateDirectoryResultExit: // Exit from the current directory - // at the current level. - // Exit from this directory level and tell parent to - // keep enumerating. - return eEnumerateDirectoryResultNext; + switch (result) { + case eEnumerateDirectoryResultNext: + // Enumerate next entry in the current directory. We just + // exit this switch and will continue enumerating the + // current directory as we currently are... + break; - case eEnumerateDirectoryResultQuit: // Stop directory enumerations at - // any level + case eEnumerateDirectoryResultEnter: // Recurse into the current entry + // if it is a directory or symlink, + // or next if not + if (FileSpec::ForEachItemInDirectory(child_path.data(), callback) == + eEnumerateDirectoryResultQuit) { + // The subdirectory returned Quit, which means to + // stop all directory enumerations at all levels. return eEnumerateDirectoryResultQuit; } + break; + + case eEnumerateDirectoryResultExit: // Exit from the current directory + // at the current level. + // Exit from this directory level and tell parent to + // keep enumerating. + return eEnumerateDirectoryResultNext; + + case eEnumerateDirectoryResultQuit: // Stop directory enumerations at + // any level + return eEnumerateDirectoryResultQuit; } } while (FindNextFileW(hFind, &ffd) != 0); FindClose(hFind); #else - lldb_utility::CleanUp dir_path_dir(opendir(dir_path), NULL, - closedir); - if (dir_path_dir.is_valid()) { - char dir_path_last_char = dir_path[strlen(dir_path) - 1]; + std::string dir_string(dir_path); + lldb_utility::CleanUp dir_path_dir(opendir(dir_string.c_str()), + NULL, closedir); + if (dir_path_dir.is_valid()) { + char dir_path_last_char = dir_path.back(); - long path_max = fpathconf(dirfd(dir_path_dir.get()), _PC_NAME_MAX); + long path_max = fpathconf(dirfd(dir_path_dir.get()), _PC_NAME_MAX); #if defined(__APPLE_) && defined(__DARWIN_MAXPATHLEN) if (path_max < __DARWIN_MAXPATHLEN) path_max = __DARWIN_MAXPATHLEN; @@ -1169,18 +1156,13 @@ #endif } - char child_path[PATH_MAX]; - + std::string child_path; // Don't make paths with "/foo//bar", that just confuses everybody. - int child_path_len; if (dir_path_last_char == '/') - child_path_len = ::snprintf(child_path, sizeof(child_path), "%s%s", - dir_path, dp->d_name); + child_path = llvm::join_items("", dir_path, dp->d_name); else - child_path_len = ::snprintf(child_path, sizeof(child_path), "%s/%s", - dir_path, dp->d_name); + child_path = llvm::join_items('/', dir_path, dp->d_name); - if (child_path_len < (int)(sizeof(child_path) - 1)) { // Don't resolve the file type or path FileSpec child_path_spec(child_path, false); @@ -1221,21 +1203,19 @@ free(buf); return eEnumerateDirectoryResultQuit; } - } } if (buf) { free(buf); } } #endif - } // By default when exiting a directory, we tell the parent enumeration // to continue enumerating. return eEnumerateDirectoryResultNext; } FileSpec::EnumerateDirectoryResult -FileSpec::EnumerateDirectory(const char *dir_path, bool find_directories, +FileSpec::EnumerateDirectory(llvm::StringRef dir_path, bool find_directories, bool find_files, bool find_other, EnumerateDirectoryCallbackType callback, void *callback_baton) { @@ -1261,13 +1241,15 @@ }); } -FileSpec FileSpec::CopyByAppendingPathComponent(const char *new_path) const { +FileSpec +FileSpec::CopyByAppendingPathComponent(llvm::StringRef component) const { FileSpec ret = *this; - ret.AppendPathComponent(new_path); + ret.AppendPathComponent(component); return ret; } FileSpec FileSpec::CopyByRemovingLastPathComponent() const { + // CLEANUP: Use StringRef for string handling. const bool resolve = false; if (m_filename.IsEmpty() && m_directory.IsEmpty()) return FileSpec("", resolve); @@ -1291,6 +1273,7 @@ } ConstString FileSpec::GetLastPathComponent() const { + // CLEANUP: Use StringRef for string handling. if (m_filename) return m_filename; if (m_directory) { @@ -1321,61 +1304,56 @@ return ConstString(); } -void FileSpec::PrependPathComponent(const char *new_path) { - if (!new_path) +void FileSpec::PrependPathComponent(llvm::StringRef component) { + if (component.empty()) return; + const bool resolve = false; if (m_filename.IsEmpty() && m_directory.IsEmpty()) { - SetFile(new_path, resolve); + SetFile(component, resolve); return; } - StreamString stream; + + char sep = GetPrefferedPathSeparator(m_syntax); + std::string result; if (m_filename.IsEmpty()) - stream.Printf("%s/%s", new_path, m_directory.GetCString()); + result = llvm::join_items(sep, component, m_directory.GetStringRef()); else if (m_directory.IsEmpty()) - stream.Printf("%s/%s", new_path, m_filename.GetCString()); + result = llvm::join_items(sep, component, m_filename.GetStringRef()); else - stream.Printf("%s/%s/%s", new_path, m_directory.GetCString(), - m_filename.GetCString()); - SetFile(stream.GetData(), resolve); -} + result = llvm::join_items(sep, component, m_directory.GetStringRef(), + m_filename.GetStringRef()); -void FileSpec::PrependPathComponent(const std::string &new_path) { - return PrependPathComponent(new_path.c_str()); + SetFile(result, resolve); } void FileSpec::PrependPathComponent(const FileSpec &new_path) { return PrependPathComponent(new_path.GetPath(false)); } -void FileSpec::AppendPathComponent(const char *new_path) { - if (!new_path) +void FileSpec::AppendPathComponent(llvm::StringRef component) { + if (component.empty()) return; - StreamString stream; + std::string result; if (!m_directory.IsEmpty()) { - stream.PutCString(m_directory.GetCString()); + result += m_directory.GetStringRef(); if (!IsPathSeparator(m_directory.GetStringRef().back(), m_syntax)) - stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + result += GetPrefferedPathSeparator(m_syntax); } if (!m_filename.IsEmpty()) { - stream.PutCString(m_filename.GetCString()); + result += m_filename.GetStringRef(); if (!IsPathSeparator(m_filename.GetStringRef().back(), m_syntax)) - stream.PutChar(GetPrefferedPathSeparator(m_syntax)); + result += GetPrefferedPathSeparator(m_syntax); } - while (IsPathSeparator(new_path[0], m_syntax)) - new_path++; + component = component.drop_while( + [this](char c) { return IsPathSeparator(c, m_syntax); }); - stream.PutCString(new_path); + result += component; - const bool resolve = false; - SetFile(stream.GetData(), resolve, m_syntax); -} - -void FileSpec::AppendPathComponent(const std::string &new_path) { - return AppendPathComponent(new_path.c_str()); + SetFile(result, false, m_syntax); } void FileSpec::AppendPathComponent(const FileSpec &new_path) { @@ -1383,6 +1361,8 @@ } void FileSpec::RemoveLastPathComponent() { + // CLEANUP: Use StringRef for string handling. + const bool resolve = false; if (m_filename.IsEmpty() && m_directory.IsEmpty()) { SetFile("", resolve); Index: source/Host/common/OptionParser.cpp =================================================================== --- source/Host/common/OptionParser.cpp +++ source/Host/common/OptionParser.cpp @@ -28,8 +28,9 @@ void OptionParser::EnableError(bool error) { opterr = error ? 1 : 0; } -int OptionParser::Parse(int argc, char *const argv[], const char *optstring, - const Option *longopts, int *longindex) { +int OptionParser::Parse(int argc, char const *const argv[], + const char *optstring, const Option *longopts, + int *longindex) { std::vector