aboutsummaryrefslogtreecommitdiffstats
path: root/source/Utility
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:09:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:09:23 +0000
commitf73363f1dd94996356cefbf24388f561891acf0b (patch)
treee3c31248bdb36eaec5fd833490d4278162dba2a0 /source/Utility
parent160ee69dd7ae18978f4068116777639ea98dc951 (diff)
downloadsrc-f73363f1dd94996356cefbf24388f561891acf0b.tar.gz
src-f73363f1dd94996356cefbf24388f561891acf0b.zip
Vendor import of lldb trunk r338150:vendor/lldb/lldb-trunk-r338150
Notes
Notes: svn path=/vendor/lldb/dist/; revision=336823 svn path=/vendor/lldb/lldb-trunk-r338150/; revision=336824; tag=vendor/lldb/lldb-trunk-r338150
Diffstat (limited to 'source/Utility')
-rw-r--r--source/Utility/ArchSpec.cpp101
-rw-r--r--source/Utility/Args.cpp726
-rw-r--r--source/Utility/CMakeLists.txt4
-rw-r--r--source/Utility/CompletionRequest.cpp59
-rw-r--r--source/Utility/ConstString.cpp32
-rw-r--r--source/Utility/DataBufferHeap.cpp21
-rw-r--r--source/Utility/DataEncoder.cpp78
-rw-r--r--source/Utility/DataExtractor.cpp268
-rw-r--r--source/Utility/Environment.cpp50
-rw-r--r--source/Utility/FastDemangle.cpp126
-rw-r--r--source/Utility/FileSpec.cpp698
-rw-r--r--source/Utility/History.cpp24
-rw-r--r--source/Utility/JSON.cpp6
-rw-r--r--source/Utility/Log.cpp21
-rw-r--r--source/Utility/PPC64_DWARF_Registers.h127
-rw-r--r--source/Utility/RegularExpression.cpp43
-rw-r--r--source/Utility/SelectHelper.cpp9
-rw-r--r--source/Utility/SharingPtr.cpp8
-rw-r--r--source/Utility/Status.cpp41
-rw-r--r--source/Utility/Stream.cpp25
-rw-r--r--source/Utility/StringExtractor.cpp23
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp15
-rw-r--r--source/Utility/StringExtractorGDBRemote.h204
-rw-r--r--source/Utility/StructuredData.cpp7
-rw-r--r--source/Utility/TildeExpressionResolver.cpp5
-rw-r--r--source/Utility/UUID.cpp176
-rw-r--r--source/Utility/VASprintf.cpp4
27 files changed, 1652 insertions, 1249 deletions
diff --git a/source/Utility/ArchSpec.cpp b/source/Utility/ArchSpec.cpp
index a10fe78260bb..320f2d9d1144 100644
--- a/source/Utility/ArchSpec.cpp
+++ b/source/Utility/ArchSpec.cpp
@@ -9,6 +9,7 @@
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/Stream.h" // for Stream
#include "lldb/Utility/StringList.h"
@@ -223,8 +224,8 @@ static const CoreDefinition g_core_definitions[] = {
"kalimba5"}};
// Ensure that we have an entry in the g_core_definitions for each core. If you
-// comment out an entry above,
-// you will need to comment out the corresponding ArchSpec::Core enumeration.
+// comment out an entry above, you will need to comment out the corresponding
+// ArchSpec::Core enumeration.
static_assert(sizeof(g_core_definitions) / sizeof(CoreDefinition) ==
ArchSpec::kNumCores,
"make sure we have one core definition for each core");
@@ -244,17 +245,22 @@ struct ArchDefinition {
const char *name;
};
-size_t ArchSpec::AutoComplete(llvm::StringRef name, StringList &matches) {
- if (!name.empty()) {
+void ArchSpec::ListSupportedArchNames(StringList &list) {
+ for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
+ list.AppendString(g_core_definitions[i].name);
+}
+
+size_t ArchSpec::AutoComplete(CompletionRequest &request) {
+ if (!request.GetCursorArgumentPrefix().empty()) {
for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) {
- if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith, name))
- matches.AppendString(g_core_definitions[i].name);
+ if (NameMatches(g_core_definitions[i].name, NameMatch::StartsWith,
+ request.GetCursorArgumentPrefix()))
+ request.GetMatches().AppendString(g_core_definitions[i].name);
}
} else {
- for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i)
- matches.AppendString(g_core_definitions[i].name);
+ ListSupportedArchNames(request.GetMatches());
}
- return matches.GetSize();
+ return request.GetMatches().GetSize();
}
#define CPU_ANY (UINT32_MAX)
@@ -890,7 +896,12 @@ void ArchSpec::MergeFrom(const ArchSpec &other) {
GetTriple().setOS(other.GetTriple().getOS());
if (GetTriple().getArch() == llvm::Triple::UnknownArch) {
GetTriple().setArch(other.GetTriple().getArch());
- UpdateCore();
+
+ // MachO unknown64 isn't really invalid as the debugger can still obtain
+ // information from the binary, e.g. line tables. As such, we don't update
+ // the core here.
+ if (other.GetCore() != eCore_uknownMach64)
+ UpdateCore();
}
if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
!TripleVendorWasSpecified()) {
@@ -898,9 +909,8 @@ void ArchSpec::MergeFrom(const ArchSpec &other) {
GetTriple().setEnvironment(other.GetTriple().getEnvironment());
}
// If this and other are both arm ArchSpecs and this ArchSpec is a generic
- // "some kind of arm"
- // spec but the other ArchSpec is a specific arm core, adopt the specific arm
- // core.
+ // "some kind of arm" spec but the other ArchSpec is a specific arm core,
+ // adopt the specific arm core.
if (GetTriple().getArch() == llvm::Triple::arm &&
other.GetTriple().getArch() == llvm::Triple::arm &&
IsCompatibleMatch(other) && GetCore() == ArchSpec::eCore_arm_generic &&
@@ -926,24 +936,21 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu,
if (core_def) {
m_core = core_def->core;
update_triple = false;
- // Always use the architecture name because it might be more descriptive
- // than the architecture enum ("armv7" -> llvm::Triple::arm).
+ // Always use the architecture name because it might be more
+ // descriptive than the architecture enum ("armv7" ->
+ // llvm::Triple::arm).
m_triple.setArchName(llvm::StringRef(core_def->name));
if (arch_type == eArchTypeMachO) {
m_triple.setVendor(llvm::Triple::Apple);
// Don't set the OS. It could be simulator, macosx, ios, watchos,
- // tvos. We could
- // get close with the cpu type - but we can't get it right all of the
- // time. Better
- // to leave this unset so other sections of code will set it when they
- // have more
- // information.
+ // tvos. We could get close with the cpu type - but we can't get it
+ // right all of the time. Better to leave this unset so other
+ // sections of code will set it when they have more information.
// NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets
// the OSName to
// "unknown" and the ArchSpec::TripleVendorWasSpecified() method says
- // that any
- // OSName setting means it was specified.
+ // that any OSName setting means it was specified.
} else if (arch_type == eArchTypeELF) {
switch (os) {
case llvm::ELF::ELFOSABI_AIX:
@@ -972,10 +979,15 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu,
m_triple.setVendor(llvm::Triple::UnknownVendor);
m_triple.setOS(llvm::Triple::UnknownOS);
}
- // Fall back onto setting the machine type if the arch by name failed...
+ // Fall back onto setting the machine type if the arch by name
+ // failed...
if (m_triple.getArch() == llvm::Triple::UnknownArch)
m_triple.setArch(core_def->machine);
}
+ } else {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_TARGET | LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Unable to find a core definition for cpu 0x%" PRIx32 " sub %" PRId32, cpu, sub);
}
}
CoreUpdated(update_triple);
@@ -1015,10 +1027,9 @@ static bool isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs,
return true;
// If one of the environment is Android and the other one is EABI then they
- // are considered to
- // be compatible. This is required as a workaround for shared libraries
- // compiled for Android
- // without the NOTE section indicating that they are using the Android ABI.
+ // are considered to be compatible. This is required as a workaround for
+ // shared libraries compiled for Android without the NOTE section indicating
+ // that they are using the Android ABI.
if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) ||
(rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) ||
(lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) ||
@@ -1050,8 +1061,8 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
if (lhs_triple_vendor != rhs_triple_vendor) {
const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified();
const bool lhs_vendor_specified = TripleVendorWasSpecified();
- // Both architectures had the vendor specified, so if they aren't
- // equal then we return false
+ // Both architectures had the vendor specified, so if they aren't equal
+ // then we return false
if (rhs_vendor_specified && lhs_vendor_specified)
return false;
@@ -1066,8 +1077,8 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
if (lhs_triple_os != rhs_triple_os) {
const bool rhs_os_specified = rhs.TripleOSWasSpecified();
const bool lhs_os_specified = TripleOSWasSpecified();
- // Both architectures had the OS specified, so if they aren't
- // equal then we return false
+ // Both architectures had the OS specified, so if they aren't equal then
+ // we return false
if (rhs_os_specified && lhs_os_specified)
return false;
@@ -1094,9 +1105,9 @@ void ArchSpec::UpdateCore() {
const CoreDefinition *core_def = FindCoreDefinition(arch_name);
if (core_def) {
m_core = core_def->core;
- // Set the byte order to the default byte order for an architecture.
- // This can be modified if needed for cases when cores handle both
- // big and little endian
+ // Set the byte order to the default byte order for an architecture. This
+ // can be modified if needed for cases when cores handle both big and
+ // little endian
m_byte_order = core_def->default_byte_order;
} else {
Clear();
@@ -1193,9 +1204,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
break;
// v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- // Cortex-M0 - ARMv6-M - armv6m
- // Cortex-M3 - ARMv7-M - armv7m
- // Cortex-M4 - ARMv7E-M - armv7em
+ // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 -
+ // ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7em:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
@@ -1211,9 +1221,8 @@ static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2,
break;
// v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization
- // Cortex-M0 - ARMv6-M - armv6m
- // Cortex-M3 - ARMv7-M - armv7m
- // Cortex-M4 - ARMv7E-M - armv7em
+ // Cortex-M0 - ARMv6-M - armv6m Cortex-M3 - ARMv7-M - armv7m Cortex-M4 -
+ // ARMv7E-M - armv7em
case ArchSpec::eCore_arm_armv7m:
if (!enforce_exact_match) {
if (core2 == ArchSpec::eCore_arm_generic)
@@ -1411,6 +1420,11 @@ bool lldb_private::operator<(const ArchSpec &lhs, const ArchSpec &rhs) {
return lhs_core < rhs_core;
}
+
+bool lldb_private::operator==(const ArchSpec &lhs, const ArchSpec &rhs) {
+ return lhs.GetCore() == rhs.GetCore();
+}
+
bool ArchSpec::IsFullySpecifiedTriple() const {
const auto &user_specified_triple = GetTriple();
@@ -1456,9 +1470,8 @@ bool ArchSpec::IsAlwaysThumbInstructions() const {
// Cortex-M0 through Cortex-M7 are ARM processor cores which can only
// execute thumb instructions. We map the cores to arch names like this:
//
- // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m
- // Cortex-M3: armv7m
- // Cortex-M4, Cortex-M7: armv7em
+ // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m Cortex-M3: armv7m Cortex-M4,
+ // Cortex-M7: armv7em
if (GetCore() == ArchSpec::Core::eCore_arm_armv7m ||
GetCore() == ArchSpec::Core::eCore_arm_armv7em ||
diff --git a/source/Utility/Args.cpp b/source/Utility/Args.cpp
new file mode 100644
index 000000000000..3b5cf1715fb3
--- /dev/null
+++ b/source/Utility/Args.cpp
@@ -0,0 +1,726 @@
+//===-- Args.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StringList.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// A helper function for argument parsing.
+// Parses the initial part of the first argument using normal double quote
+// rules: backslash escapes the double quote and itself. The parsed string is
+// appended to the second argument. The function returns the unparsed portion
+// of the string, starting at the closing quote.
+static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
+ std::string &result) {
+ // Inside double quotes, '\' and '"' are special.
+ static const char *k_escapable_characters = "\"\\";
+ while (true) {
+ // Skip over over regular characters and append them.
+ size_t regular = quoted.find_first_of(k_escapable_characters);
+ result += quoted.substr(0, regular);
+ quoted = quoted.substr(regular);
+
+ // If we have reached the end of string or the closing quote, we're done.
+ if (quoted.empty() || quoted.front() == '"')
+ break;
+
+ // We have found a backslash.
+ quoted = quoted.drop_front();
+
+ if (quoted.empty()) {
+ // A lone backslash at the end of string, let's just append it.
+ result += '\\';
+ break;
+ }
+
+ // If the character after the backslash is not a whitelisted escapable
+ // character, we leave the character sequence untouched.
+ if (strchr(k_escapable_characters, quoted.front()) == nullptr)
+ result += '\\';
+
+ result += quoted.front();
+ quoted = quoted.drop_front();
+ }
+
+ return quoted;
+}
+
+static size_t ArgvToArgc(const char **argv) {
+ if (!argv)
+ return 0;
+ size_t count = 0;
+ while (*argv++)
+ ++count;
+ return count;
+}
+
+// Trims all whitespace that can separate command line arguments from the left
+// side of the string.
+static llvm::StringRef ltrimForArgs(llvm::StringRef str) {
+ static const char *k_space_separators = " \t";
+ return str.ltrim(k_space_separators);
+}
+
+// A helper function for SetCommandString. Parses a single argument from the
+// command string, processing quotes and backslashes in a shell-like manner.
+// The function returns a tuple consisting of the parsed argument, the quote
+// char used, and the unparsed portion of the string starting at the first
+// unqouted, unescaped whitespace character.
+static std::tuple<std::string, char, llvm::StringRef>
+ParseSingleArgument(llvm::StringRef command) {
+ // Argument can be split into multiple discontiguous pieces, for example:
+ // "Hello ""World"
+ // this would result in a single argument "Hello World" (without the quotes)
+ // since the quotes would be removed and there is not space between the
+ // strings.
+ std::string arg;
+
+ // Since we can have multiple quotes that form a single command in a command
+ // like: "Hello "world'!' (which will make a single argument "Hello world!")
+ // we remember the first quote character we encounter and use that for the
+ // quote character.
+ char first_quote_char = '\0';
+
+ bool arg_complete = false;
+ do {
+ // Skip over over regular characters and append them.
+ size_t regular = command.find_first_of(" \t\"'`\\");
+ arg += command.substr(0, regular);
+ command = command.substr(regular);
+
+ if (command.empty())
+ break;
+
+ char special = command.front();
+ command = command.drop_front();
+ switch (special) {
+ case '\\':
+ if (command.empty()) {
+ arg += '\\';
+ break;
+ }
+
+ // If the character after the backslash is not a whitelisted escapable
+ // character, we leave the character sequence untouched.
+ if (strchr(" \t\\'\"`", command.front()) == nullptr)
+ arg += '\\';
+
+ arg += command.front();
+ command = command.drop_front();
+
+ break;
+
+ case ' ':
+ case '\t':
+ // We are not inside any quotes, we just found a space after an argument.
+ // We are done.
+ arg_complete = true;
+ break;
+
+ case '"':
+ case '\'':
+ case '`':
+ // We found the start of a quote scope.
+ if (first_quote_char == '\0')
+ first_quote_char = special;
+
+ if (special == '"')
+ command = ParseDoubleQuotes(command, arg);
+ else {
+ // For single quotes, we simply skip ahead to the matching quote
+ // character (or the end of the string).
+ size_t quoted = command.find(special);
+ arg += command.substr(0, quoted);
+ command = command.substr(quoted);
+ }
+
+ // If we found a closing quote, skip it.
+ if (!command.empty())
+ command = command.drop_front();
+
+ break;
+ }
+ } while (!arg_complete);
+
+ return std::make_tuple(arg, first_quote_char, command);
+}
+
+Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) {
+ size_t size = str.size();
+ ptr.reset(new char[size + 1]);
+
+ ::memcpy(data(), str.data() ? str.data() : "", size);
+ ptr[size] = 0;
+ ref = llvm::StringRef(c_str(), size);
+}
+
+//----------------------------------------------------------------------
+// Args constructor
+//----------------------------------------------------------------------
+Args::Args(llvm::StringRef command) { SetCommandString(command); }
+
+Args::Args(const Args &rhs) { *this = rhs; }
+
+Args::Args(const StringList &list) : Args() {
+ for (size_t i = 0; i < list.GetSize(); ++i)
+ AppendArgument(list[i]);
+}
+
+Args &Args::operator=(const Args &rhs) {
+ Clear();
+
+ m_argv.clear();
+ m_entries.clear();
+ for (auto &entry : rhs.m_entries) {
+ m_entries.emplace_back(entry.ref, entry.quote);
+ m_argv.push_back(m_entries.back().data());
+ }
+ m_argv.push_back(nullptr);
+ return *this;
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Args::~Args() {}
+
+void Args::Dump(Stream &s, const char *label_name) const {
+ if (!label_name)
+ return;
+
+ int i = 0;
+ for (auto &entry : m_entries) {
+ s.Indent();
+ s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref);
+ }
+ s.Format("{0}[{1}]=NULL\n", label_name, i);
+ s.EOL();
+}
+
+bool Args::GetCommandString(std::string &command) const {
+ command.clear();
+
+ for (size_t i = 0; i < m_entries.size(); ++i) {
+ if (i > 0)
+ command += ' ';
+ command += m_entries[i].ref;
+ }
+
+ return !m_entries.empty();
+}
+
+bool Args::GetQuotedCommandString(std::string &command) const {
+ command.clear();
+
+ for (size_t i = 0; i < m_entries.size(); ++i) {
+ if (i > 0)
+ command += ' ';
+
+ if (m_entries[i].quote) {
+ command += m_entries[i].quote;
+ command += m_entries[i].ref;
+ command += m_entries[i].quote;
+ } else {
+ command += m_entries[i].ref;
+ }
+ }
+
+ return !m_entries.empty();
+}
+
+void Args::SetCommandString(llvm::StringRef command) {
+ Clear();
+ m_argv.clear();
+
+ command = ltrimForArgs(command);
+ std::string arg;
+ char quote;
+ while (!command.empty()) {
+ std::tie(arg, quote, command) = ParseSingleArgument(command);
+ m_entries.emplace_back(arg, quote);
+ m_argv.push_back(m_entries.back().data());
+ command = ltrimForArgs(command);
+ }
+ m_argv.push_back(nullptr);
+}
+
+size_t Args::GetArgumentCount() const { return m_entries.size(); }
+
+const char *Args::GetArgumentAtIndex(size_t idx) const {
+ if (idx < m_argv.size())
+ return m_argv[idx];
+ return nullptr;
+}
+
+char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
+ if (idx < m_entries.size())
+ return m_entries[idx].quote;
+ return '\0';
+}
+
+char **Args::GetArgumentVector() {
+ assert(!m_argv.empty());
+ // TODO: functions like execve and posix_spawnp exhibit undefined behavior
+ // when argv or envp is null. So the code below is actually wrong. However,
+ // other code in LLDB depends on it being null. The code has been acting
+ // this way for some time, so it makes sense to leave it this way until
+ // someone has the time to come along and fix it.
+ return (m_argv.size() > 1) ? m_argv.data() : nullptr;
+}
+
+const char **Args::GetConstArgumentVector() const {
+ assert(!m_argv.empty());
+ return (m_argv.size() > 1) ? const_cast<const char **>(m_argv.data())
+ : nullptr;
+}
+
+void Args::Shift() {
+ // Don't pop the last NULL terminator from the argv array
+ if (m_entries.empty())
+ return;
+ m_argv.erase(m_argv.begin());
+ m_entries.erase(m_entries.begin());
+}
+
+void Args::Unshift(llvm::StringRef arg_str, char quote_char) {
+ InsertArgumentAtIndex(0, arg_str, quote_char);
+}
+
+void Args::AppendArguments(const Args &rhs) {
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+ m_argv.pop_back();
+ for (auto &entry : rhs.m_entries) {
+ m_entries.emplace_back(entry.ref, entry.quote);
+ m_argv.push_back(m_entries.back().data());
+ }
+ m_argv.push_back(nullptr);
+}
+
+void Args::AppendArguments(const char **argv) {
+ size_t argc = ArgvToArgc(argv);
+
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+ m_argv.pop_back();
+ for (auto arg : llvm::makeArrayRef(argv, argc)) {
+ m_entries.emplace_back(arg, '\0');
+ m_argv.push_back(m_entries.back().data());
+ }
+
+ m_argv.push_back(nullptr);
+}
+
+void Args::AppendArgument(llvm::StringRef arg_str, char quote_char) {
+ InsertArgumentAtIndex(GetArgumentCount(), arg_str, quote_char);
+}
+
+void Args::InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
+ char quote_char) {
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+
+ if (idx > m_entries.size())
+ return;
+ m_entries.emplace(m_entries.begin() + idx, arg_str, quote_char);
+ m_argv.insert(m_argv.begin() + idx, m_entries[idx].data());
+}
+
+void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
+ char quote_char) {
+ assert(m_argv.size() == m_entries.size() + 1);
+ assert(m_argv.back() == nullptr);
+
+ if (idx >= m_entries.size())
+ return;
+
+ if (arg_str.size() > m_entries[idx].ref.size()) {
+ m_entries[idx] = ArgEntry(arg_str, quote_char);
+ m_argv[idx] = m_entries[idx].data();
+ } else {
+ const char *src_data = arg_str.data() ? arg_str.data() : "";
+ ::memcpy(m_entries[idx].data(), src_data, arg_str.size());
+ m_entries[idx].ptr[arg_str.size()] = 0;
+ m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size());
+ }
+}
+
+void Args::DeleteArgumentAtIndex(size_t idx) {
+ if (idx >= m_entries.size())
+ return;
+
+ m_argv.erase(m_argv.begin() + idx);
+ m_entries.erase(m_entries.begin() + idx);
+}
+
+void Args::SetArguments(size_t argc, const char **argv) {
+ Clear();
+
+ auto args = llvm::makeArrayRef(argv, argc);
+ m_entries.resize(argc);
+ m_argv.resize(argc + 1);
+ for (size_t i = 0; i < args.size(); ++i) {
+ char quote =
+ ((args[i][0] == '\'') || (args[i][0] == '"') || (args[i][0] == '`'))
+ ? args[i][0]
+ : '\0';
+
+ m_entries[i] = ArgEntry(args[i], quote);
+ m_argv[i] = m_entries[i].data();
+ }
+}
+
+void Args::SetArguments(const char **argv) {
+ SetArguments(ArgvToArgc(argv), argv);
+}
+
+void Args::Clear() {
+ m_entries.clear();
+ m_argv.clear();
+ m_argv.push_back(nullptr);
+}
+
+const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
+ bool return_null_if_empty) {
+ static const char *k_white_space = " \t\v";
+ if (!s.empty()) {
+ if (leading) {
+ size_t pos = s.find_first_not_of(k_white_space);
+ if (pos == std::string::npos)
+ s.clear();
+ else if (pos > 0)
+ s.erase(0, pos);
+ }
+
+ if (trailing) {
+ size_t rpos = s.find_last_not_of(k_white_space);
+ if (rpos != std::string::npos && rpos + 1 < s.size())
+ s.erase(rpos + 1);
+ }
+ }
+ if (return_null_if_empty && s.empty())
+ return nullptr;
+ return s.c_str();
+}
+
+const char *Args::GetShellSafeArgument(const FileSpec &shell,
+ const char *unsafe_arg,
+ std::string &safe_arg) {
+ struct ShellDescriptor {
+ ConstString m_basename;
+ const char *m_escapables;
+ };
+
+ static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
+ {ConstString("tcsh"), " '\"<>()&$"},
+ {ConstString("sh"), " '\"<>()&"}};
+
+ // safe minimal set
+ const char *escapables = " '\"";
+
+ if (auto basename = shell.GetFilename()) {
+ for (const auto &Shell : g_Shells) {
+ if (Shell.m_basename == basename) {
+ escapables = Shell.m_escapables;
+ break;
+ }
+ }
+ }
+
+ safe_arg.assign(unsafe_arg);
+ size_t prev_pos = 0;
+ while (prev_pos < safe_arg.size()) {
+ // Escape spaces and quotes
+ size_t pos = safe_arg.find_first_of(escapables, prev_pos);
+ if (pos != std::string::npos) {
+ safe_arg.insert(pos, 1, '\\');
+ prev_pos = pos + 2;
+ } else
+ break;
+ }
+ return safe_arg.c_str();
+}
+
+lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
+ lldb::Encoding fail_value) {
+ return llvm::StringSwitch<lldb::Encoding>(s)
+ .Case("uint", eEncodingUint)
+ .Case("sint", eEncodingSint)
+ .Case("ieee754", eEncodingIEEE754)
+ .Case("vector", eEncodingVector)
+ .Default(fail_value);
+}
+
+uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
+ if (s.empty())
+ return LLDB_INVALID_REGNUM;
+ uint32_t result = llvm::StringSwitch<uint32_t>(s)
+ .Case("pc", LLDB_REGNUM_GENERIC_PC)
+ .Case("sp", LLDB_REGNUM_GENERIC_SP)
+ .Case("fp", LLDB_REGNUM_GENERIC_FP)
+ .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
+ .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
+ .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
+ .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
+ .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
+ .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
+ .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
+ .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
+ .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
+ .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
+ .Default(LLDB_INVALID_REGNUM);
+ return result;
+}
+
+void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
+ dst.clear();
+ if (src) {
+ for (const char *p = src; *p != '\0'; ++p) {
+ size_t non_special_chars = ::strcspn(p, "\\");
+ if (non_special_chars > 0) {
+ dst.append(p, non_special_chars);
+ p += non_special_chars;
+ if (*p == '\0')
+ break;
+ }
+
+ if (*p == '\\') {
+ ++p; // skip the slash
+ switch (*p) {
+ case 'a':
+ dst.append(1, '\a');
+ break;
+ case 'b':
+ dst.append(1, '\b');
+ break;
+ case 'f':
+ dst.append(1, '\f');
+ break;
+ case 'n':
+ dst.append(1, '\n');
+ break;
+ case 'r':
+ dst.append(1, '\r');
+ break;
+ case 't':
+ dst.append(1, '\t');
+ break;
+ case 'v':
+ dst.append(1, '\v');
+ break;
+ case '\\':
+ dst.append(1, '\\');
+ break;
+ case '\'':
+ dst.append(1, '\'');
+ break;
+ case '"':
+ dst.append(1, '"');
+ break;
+ case '0':
+ // 1 to 3 octal chars
+ {
+ // Make a string that can hold onto the initial zero char, up to 3
+ // octal digits, and a terminating NULL.
+ char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
+
+ int i;
+ for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
+ oct_str[i] = p[i];
+
+ // We don't want to consume the last octal character since the main
+ // for loop will do this for us, so we advance p by one less than i
+ // (even if i is zero)
+ p += i - 1;
+ unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
+ if (octal_value <= UINT8_MAX) {
+ dst.append(1, (char)octal_value);
+ }
+ }
+ break;
+
+ case 'x':
+ // hex number in the format
+ if (isxdigit(p[1])) {
+ ++p; // Skip the 'x'
+
+ // Make a string that can hold onto two hex chars plus a
+ // NULL terminator
+ char hex_str[3] = {*p, '\0', '\0'};
+ if (isxdigit(p[1])) {
+ ++p; // Skip the first of the two hex chars
+ hex_str[1] = *p;
+ }
+
+ unsigned long hex_value = strtoul(hex_str, nullptr, 16);
+ if (hex_value <= UINT8_MAX)
+ dst.append(1, (char)hex_value);
+ } else {
+ dst.append(1, 'x');
+ }
+ break;
+
+ default:
+ // Just desensitize any other character by just printing what came
+ // after the '\'
+ dst.append(1, *p);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
+ dst.clear();
+ if (src) {
+ for (const char *p = src; *p != '\0'; ++p) {
+ if (isprint(*p))
+ dst.append(1, *p);
+ else {
+ switch (*p) {
+ case '\a':
+ dst.append("\\a");
+ break;
+ case '\b':
+ dst.append("\\b");
+ break;
+ case '\f':
+ dst.append("\\f");
+ break;
+ case '\n':
+ dst.append("\\n");
+ break;
+ case '\r':
+ dst.append("\\r");
+ break;
+ case '\t':
+ dst.append("\\t");
+ break;
+ case '\v':
+ dst.append("\\v");
+ break;
+ case '\'':
+ dst.append("\\'");
+ break;
+ case '"':
+ dst.append("\\\"");
+ break;
+ case '\\':
+ dst.append("\\\\");
+ break;
+ default: {
+ // Just encode as octal
+ dst.append("\\0");
+ char octal_str[32];
+ snprintf(octal_str, sizeof(octal_str), "%o", *p);
+ dst.append(octal_str);
+ } break;
+ }
+ }
+ }
+ }
+}
+
+std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
+ char quote_char) {
+ const char *chars_to_escape = nullptr;
+ switch (quote_char) {
+ case '\0':
+ chars_to_escape = " \t\\'\"`";
+ break;
+ case '\'':
+ chars_to_escape = "";
+ break;
+ case '"':
+ chars_to_escape = "$\"`\\";
+ break;
+ default:
+ assert(false && "Unhandled quote character");
+ }
+
+ std::string res;
+ res.reserve(arg.size());
+ for (char c : arg) {
+ if (::strchr(chars_to_escape, c))
+ res.push_back('\\');
+ res.push_back(c);
+ }
+ return res;
+}
+
+OptionsWithRaw::OptionsWithRaw(llvm::StringRef arg_string) {
+ SetFromString(arg_string);
+}
+
+void OptionsWithRaw::SetFromString(llvm::StringRef arg_string) {
+ const llvm::StringRef original_args = arg_string;
+
+ arg_string = ltrimForArgs(arg_string);
+ std::string arg;
+ char quote;
+
+ // If the string doesn't start with a dash, we just have no options and just
+ // a raw part.
+ if (!arg_string.startswith("-")) {
+ m_suffix = original_args;
+ return;
+ }
+
+ bool found_suffix = false;
+
+ while (!arg_string.empty()) {
+ // The length of the prefix before parsing.
+ std::size_t prev_prefix_length = original_args.size() - arg_string.size();
+
+ // Parse the next argument from the remaining string.
+ std::tie(arg, quote, arg_string) = ParseSingleArgument(arg_string);
+
+ // If we get an unquoted '--' argument, then we reached the suffix part
+ // of the command.
+ Args::ArgEntry entry(arg, quote);
+ if (!entry.IsQuoted() && arg == "--") {
+ // The remaining line is the raw suffix, and the line we parsed so far
+ // needs to be interpreted as arguments.
+ m_has_args = true;
+ m_suffix = arg_string;
+ found_suffix = true;
+
+ // The length of the prefix after parsing.
+ std::size_t prefix_length = original_args.size() - arg_string.size();
+
+ // Take the string we know contains all the arguments and actually parse
+ // it as proper arguments.
+ llvm::StringRef prefix = original_args.take_front(prev_prefix_length);
+ m_args = Args(prefix);
+ m_arg_string = prefix;
+
+ // We also record the part of the string that contains the arguments plus
+ // the delimiter.
+ m_arg_string_with_delimiter = original_args.take_front(prefix_length);
+
+ // As the rest of the string became the raw suffix, we are done here.
+ break;
+ }
+
+ arg_string = ltrimForArgs(arg_string);
+ }
+
+ // If we didn't find a suffix delimiter, the whole string is the raw suffix.
+ if (!found_suffix) {
+ found_suffix = true;
+ m_suffix = original_args;
+ }
+}
diff --git a/source/Utility/CMakeLists.txt b/source/Utility/CMakeLists.txt
index 1a0fb6f86c57..91f3c8773731 100644
--- a/source/Utility/CMakeLists.txt
+++ b/source/Utility/CMakeLists.txt
@@ -41,16 +41,18 @@ endif()
add_lldb_library(lldbUtility
ArchSpec.cpp
+ Args.cpp
Baton.cpp
Connection.cpp
ConstString.cpp
+ CompletionRequest.cpp
DataBufferHeap.cpp
DataBufferLLVM.cpp
DataEncoder.cpp
DataExtractor.cpp
+ Environment.cpp
FastDemangle.cpp
FileSpec.cpp
- History.cpp
IOObject.cpp
JSON.cpp
LLDBAssert.cpp
diff --git a/source/Utility/CompletionRequest.cpp b/source/Utility/CompletionRequest.cpp
new file mode 100644
index 000000000000..1b7697a35860
--- /dev/null
+++ b/source/Utility/CompletionRequest.cpp
@@ -0,0 +1,59 @@
+//===-- CompletionRequest.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/CompletionRequest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CompletionRequest::CompletionRequest(llvm::StringRef command_line,
+ unsigned raw_cursor_pos,
+ int match_start_point,
+ int max_return_elements,
+ StringList &matches)
+ : m_command(command_line), m_raw_cursor_pos(raw_cursor_pos),
+ m_match_start_point(match_start_point),
+ m_max_return_elements(max_return_elements), m_matches(&matches) {
+
+ // We parse the argument up to the cursor, so the last argument in
+ // parsed_line is the one containing the cursor, and the cursor is after the
+ // last character.
+ m_parsed_line = Args(command_line);
+ m_partial_parsed_line = Args(command_line.substr(0, raw_cursor_pos));
+
+ m_cursor_index = m_partial_parsed_line.GetArgumentCount() - 1;
+
+ if (m_cursor_index == -1)
+ m_cursor_char_position = 0;
+ else
+ m_cursor_char_position =
+ strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index));
+
+ matches.Clear();
+
+ const char *cursor = command_line.data() + raw_cursor_pos;
+ if (raw_cursor_pos > 0 && cursor[-1] == ' ') {
+ // We are just after a space. If we are in an argument, then we will
+ // continue parsing, but if we are between arguments, then we have to
+ // complete whatever the next element would be. We can distinguish the two
+ // cases because if we are in an argument (e.g. because the space is
+ // protected by a quote) then the space will also be in the parsed
+ // argument...
+
+ const char *current_elem =
+ m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index);
+ if (m_cursor_char_position == 0 ||
+ current_elem[m_cursor_char_position - 1] != ' ') {
+ m_parsed_line.InsertArgumentAtIndex(m_cursor_index + 1, llvm::StringRef(),
+ '\0');
+ m_cursor_index++;
+ m_cursor_char_position = 0;
+ }
+ }
+}
diff --git a/source/Utility/ConstString.cpp b/source/Utility/ConstString.cpp
index 49cf8a6d864d..5ef4b2faa3b8 100644
--- a/source/Utility/ConstString.cpp
+++ b/source/Utility/ConstString.cpp
@@ -11,10 +11,10 @@
#include "lldb/Utility/Stream.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator.h" // for iterator_facade_base
#include "llvm/Support/Allocator.h" // for BumpPtrAllocator
+#include "llvm/Support/DJB.h" // for djbHash
#include "llvm/Support/FormatProviders.h" // for format_provider
#include "llvm/Support/RWMutex.h"
#include "llvm/Support/Threading.h"
@@ -43,8 +43,8 @@ public:
static size_t GetConstCStringLength(const char *ccstr) {
if (ccstr != nullptr) {
- // Since the entry is read only, and we derive the entry entirely from the
- // pointer, we don't need the lock.
+ // Since the entry is read only, and we derive the entry entirely from
+ // the pointer, we don't need the lock.
const StringPoolEntryType &entry = GetStringMapEntryFromKeyData(ccstr);
return entry.getKey().size();
}
@@ -155,9 +155,8 @@ public:
}
//------------------------------------------------------------------
- // Return the size in bytes that this object and any items in its
- // collection of uniqued strings + data count values takes in
- // memory.
+ // Return the size in bytes that this object and any items in its collection
+ // of uniqued strings + data count values takes in memory.
//------------------------------------------------------------------
size_t MemorySize() const {
size_t mem_size = sizeof(Pool);
@@ -171,7 +170,7 @@ public:
protected:
uint8_t hash(const llvm::StringRef &s) const {
- uint32_t h = llvm::HashString(s);
+ uint32_t h = llvm::djbHash(s);
return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff;
}
@@ -184,15 +183,14 @@ protected:
};
//----------------------------------------------------------------------
-// Frameworks and dylibs aren't supposed to have global C++
-// initializers so we hide the string pool in a static function so
-// that it will get initialized on the first call to this static
-// function.
+// Frameworks and dylibs aren't supposed to have global C++ initializers so we
+// hide the string pool in a static function so that it will get initialized on
+// the first call to this static function.
//
-// Note, for now we make the string pool a pointer to the pool, because
-// we can't guarantee that some objects won't get destroyed after the
-// global destructor chain is run, and trying to make sure no destructors
-// touch ConstStrings is difficult. So we leak the pool instead.
+// Note, for now we make the string pool a pointer to the pool, because we
+// can't guarantee that some objects won't get destroyed after the global
+// destructor chain is run, and trying to make sure no destructors touch
+// ConstStrings is difficult. So we leak the pool instead.
//----------------------------------------------------------------------
static Pool &StringPool() {
static llvm::once_flag g_pool_initialization_flag;
@@ -246,8 +244,8 @@ bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs,
return true;
// Since the pointers weren't equal, and identical ConstStrings always have
- // identical pointers,
- // the result must be false for case sensitive equality test.
+ // identical pointers, the result must be false for case sensitive equality
+ // test.
if (case_sensitive)
return false;
diff --git a/source/Utility/DataBufferHeap.cpp b/source/Utility/DataBufferHeap.cpp
index aa1c3d37ae62..e686ee8d35e5 100644
--- a/source/Utility/DataBufferHeap.cpp
+++ b/source/Utility/DataBufferHeap.cpp
@@ -22,8 +22,7 @@ using namespace lldb_private;
DataBufferHeap::DataBufferHeap() : m_data() {}
//----------------------------------------------------------------------
-// Initialize this class with "n" characters and fill the buffer
-// with "ch".
+// Initialize this class with "n" characters and fill the buffer with "ch".
//----------------------------------------------------------------------
DataBufferHeap::DataBufferHeap(lldb::offset_t n, uint8_t ch) : m_data() {
if (n < m_data.max_size())
@@ -31,8 +30,7 @@ DataBufferHeap::DataBufferHeap(lldb::offset_t n, uint8_t ch) : m_data() {
}
//----------------------------------------------------------------------
-// Initialize this class with a copy of the "n" bytes from the "bytes"
-// buffer.
+// Initialize this class with a copy of the "n" bytes from the "bytes" buffer.
//----------------------------------------------------------------------
DataBufferHeap::DataBufferHeap(const void *src, lldb::offset_t src_len)
: m_data() {
@@ -40,22 +38,21 @@ DataBufferHeap::DataBufferHeap(const void *src, lldb::offset_t src_len)
}
//----------------------------------------------------------------------
-// Virtual destructor since this class inherits from a pure virtual
-// base class.
+// Virtual destructor since this class inherits from a pure virtual base class.
//----------------------------------------------------------------------
DataBufferHeap::~DataBufferHeap() = default;
//----------------------------------------------------------------------
-// Return a pointer to the bytes owned by this object, or nullptr if
-// the object contains no bytes.
+// Return a pointer to the bytes owned by this object, or nullptr if the object
+// contains no bytes.
//----------------------------------------------------------------------
uint8_t *DataBufferHeap::GetBytes() {
return (m_data.empty() ? nullptr : m_data.data());
}
//----------------------------------------------------------------------
-// Return a const pointer to the bytes owned by this object, or nullptr
-// if the object contains no bytes.
+// Return a const pointer to the bytes owned by this object, or nullptr if the
+// object contains no bytes.
//----------------------------------------------------------------------
const uint8_t *DataBufferHeap::GetBytes() const {
return (m_data.empty() ? nullptr : m_data.data());
@@ -67,8 +64,8 @@ const uint8_t *DataBufferHeap::GetBytes() const {
uint64_t DataBufferHeap::GetByteSize() const { return m_data.size(); }
//----------------------------------------------------------------------
-// Sets the number of bytes that this object should be able to
-// contain. This can be used prior to copying data into the buffer.
+// Sets the number of bytes that this object should be able to contain. This
+// can be used prior to copying data into the buffer.
//----------------------------------------------------------------------
uint64_t DataBufferHeap::SetByteSize(uint64_t new_size) {
m_data.resize(new_size);
diff --git a/source/Utility/DataEncoder.cpp b/source/Utility/DataEncoder.cpp
index 433a15bc9523..7edee3c2f279 100644
--- a/source/Utility/DataEncoder.cpp
+++ b/source/Utility/DataEncoder.cpp
@@ -34,8 +34,8 @@ DataEncoder::DataEncoder()
m_data_sp() {}
//----------------------------------------------------------------------
-// This constructor allows us to use data that is owned by someone else.
-// The data must stay around as long as this object is valid.
+// This constructor allows us to use data that is owned by someone else. The
+// data must stay around as long as this object is valid.
//----------------------------------------------------------------------
DataEncoder::DataEncoder(void *data, uint32_t length, ByteOrder endian,
uint8_t addr_size)
@@ -43,11 +43,10 @@ DataEncoder::DataEncoder(void *data, uint32_t length, ByteOrder endian,
m_byte_order(endian), m_addr_size(addr_size), m_data_sp() {}
//----------------------------------------------------------------------
-// Make a shared pointer reference to the shared data in "data_sp" and
-// set the endian swapping setting to "swap", and the address size to
-// "addr_size". The shared data reference will ensure the data lives
-// as long as any DataEncoder objects exist that have a reference to
-// this data.
+// Make a shared pointer reference to the shared data in "data_sp" and set the
+// endian swapping setting to "swap", and the address size to "addr_size". The
+// shared data reference will ensure the data lives as long as any DataEncoder
+// objects exist that have a reference to this data.
//----------------------------------------------------------------------
DataEncoder::DataEncoder(const DataBufferSP &data_sp, ByteOrder endian,
uint8_t addr_size)
@@ -59,9 +58,8 @@ DataEncoder::DataEncoder(const DataBufferSP &data_sp, ByteOrder endian,
DataEncoder::~DataEncoder() = default;
//------------------------------------------------------------------
-// Clears the object contents back to a default invalid state, and
-// release any references to shared data that this object may
-// contain.
+// Clears the object contents back to a default invalid state, and release any
+// references to shared data that this object may contain.
//------------------------------------------------------------------
void DataEncoder::Clear() {
m_start = nullptr;
@@ -72,8 +70,8 @@ void DataEncoder::Clear() {
}
//------------------------------------------------------------------
-// If this object contains shared data, this function returns the
-// offset into that shared data. Else zero is returned.
+// If this object contains shared data, this function returns the offset into
+// that shared data. Else zero is returned.
//------------------------------------------------------------------
size_t DataEncoder::GetSharedDataOffset() const {
if (m_start != nullptr) {
@@ -90,13 +88,12 @@ size_t DataEncoder::GetSharedDataOffset() const {
}
//----------------------------------------------------------------------
-// Set the data with which this object will extract from to data
-// starting at BYTES and set the length of the data to LENGTH bytes
-// long. The data is externally owned must be around at least as
-// long as this object points to the data. No copy of the data is
-// made, this object just refers to this data and can extract from
-// it. If this object refers to any shared data upon entry, the
-// reference to that data will be released. Is SWAP is set to true,
+// Set the data with which this object will extract from to data starting at
+// BYTES and set the length of the data to LENGTH bytes long. The data is
+// externally owned must be around at least as long as this object points to
+// the data. No copy of the data is made, this object just refers to this data
+// and can extract from it. If this object refers to any shared data upon
+// entry, the reference to that data will be released. Is SWAP is set to true,
// any data extracted will be endian swapped.
//----------------------------------------------------------------------
uint32_t DataEncoder::SetData(void *bytes, uint32_t length, ByteOrder endian) {
@@ -113,18 +110,17 @@ uint32_t DataEncoder::SetData(void *bytes, uint32_t length, ByteOrder endian) {
}
//----------------------------------------------------------------------
-// Assign the data for this object to be a subrange of the shared
-// data in "data_sp" starting "data_offset" bytes into "data_sp"
-// and ending "data_length" bytes later. If "data_offset" is not
-// a valid offset into "data_sp", then this object will contain no
-// bytes. If "data_offset" is within "data_sp" yet "data_length" is
-// too large, the length will be capped at the number of bytes
-// remaining in "data_sp". A ref counted pointer to the data in
-// "data_sp" will be made in this object IF the number of bytes this
-// object refers to in greater than zero (if at least one byte was
-// available starting at "data_offset") to ensure the data stays
-// around as long as it is needed. The address size and endian swap
-// settings will remain unchanged from their current settings.
+// Assign the data for this object to be a subrange of the shared data in
+// "data_sp" starting "data_offset" bytes into "data_sp" and ending
+// "data_length" bytes later. If "data_offset" is not a valid offset into
+// "data_sp", then this object will contain no bytes. If "data_offset" is
+// within "data_sp" yet "data_length" is too large, the length will be capped
+// at the number of bytes remaining in "data_sp". A ref counted pointer to the
+// data in "data_sp" will be made in this object IF the number of bytes this
+// object refers to in greater than zero (if at least one byte was available
+// starting at "data_offset") to ensure the data stays around as long as it is
+// needed. The address size and endian swap settings will remain unchanged from
+// their current settings.
//----------------------------------------------------------------------
uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset,
uint32_t data_length) {
@@ -149,8 +145,8 @@ uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset,
uint32_t new_size = GetByteSize();
- // Don't hold a shared pointer to the data buffer if we don't share
- // any valid bytes in the shared buffer.
+ // Don't hold a shared pointer to the data buffer if we don't share any valid
+ // bytes in the shared buffer.
if (new_size == 0)
m_data_sp.reset();
@@ -158,8 +154,8 @@ uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset,
}
//----------------------------------------------------------------------
-// Extract a single unsigned char from the binary data and update
-// the offset pointed to by "offset_ptr".
+// Extract a single unsigned char from the binary data and update the offset
+// pointed to by "offset_ptr".
//
// RETURNS the byte that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -208,12 +204,12 @@ uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) {
}
//----------------------------------------------------------------------
-// Extract a single integer value from the data and update the offset
-// pointed to by "offset_ptr". The size of the extracted integer
-// is specified by the "byte_size" argument. "byte_size" should have
-// a value >= 1 and <= 8 since the return value is only 64 bits
-// wide. Any "byte_size" values less than 1 or greater than 8 will
-// result in nothing being extracted, and zero being returned.
+// Extract a single integer value from the data and update the offset pointed
+// to by "offset_ptr". The size of the extracted integer is specified by the
+// "byte_size" argument. "byte_size" should have a value >= 1 and <= 8 since
+// the return value is only 64 bits wide. Any "byte_size" values less than 1 or
+// greater than 8 will result in nothing being extracted, and zero being
+// returned.
//
// RETURNS the integer value that was extracted, or zero on failure.
//----------------------------------------------------------------------
diff --git a/source/Utility/DataExtractor.cpp b/source/Utility/DataExtractor.cpp
index 84c5f8191521..947232943aa7 100644
--- a/source/Utility/DataExtractor.cpp
+++ b/source/Utility/DataExtractor.cpp
@@ -126,8 +126,8 @@ DataExtractor::DataExtractor()
m_data_sp(), m_target_byte_size(1) {}
//----------------------------------------------------------------------
-// This constructor allows us to use data that is owned by someone else.
-// The data must stay around as long as this object is valid.
+// This constructor allows us to use data that is owned by someone else. The
+// data must stay around as long as this object is valid.
//----------------------------------------------------------------------
DataExtractor::DataExtractor(const void *data, offset_t length,
ByteOrder endian, uint32_t addr_size,
@@ -143,11 +143,10 @@ DataExtractor::DataExtractor(const void *data, offset_t length,
}
//----------------------------------------------------------------------
-// Make a shared pointer reference to the shared data in "data_sp" and
-// set the endian swapping setting to "swap", and the address size to
-// "addr_size". The shared data reference will ensure the data lives
-// as long as any DataExtractor objects exist that have a reference to
-// this data.
+// Make a shared pointer reference to the shared data in "data_sp" and set the
+// endian swapping setting to "swap", and the address size to "addr_size". The
+// shared data reference will ensure the data lives as long as any
+// DataExtractor objects exist that have a reference to this data.
//----------------------------------------------------------------------
DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
uint32_t addr_size,
@@ -162,11 +161,11 @@ DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian,
}
//----------------------------------------------------------------------
-// Initialize this object with a subset of the data bytes in "data".
-// If "data" contains shared data, then a reference to this shared
-// data will added and the shared data will stay around as long
-// as any object contains a reference to that data. The endian
-// swap and address size settings are copied from "data".
+// Initialize this object with a subset of the data bytes in "data". If "data"
+// contains shared data, then a reference to this shared data will added and
+// the shared data will stay around as long as any object contains a reference
+// to that data. The endian swap and address size settings are copied from
+// "data".
//----------------------------------------------------------------------
DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset,
offset_t length, uint32_t target_byte_size /*=1*/)
@@ -210,9 +209,8 @@ const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) {
DataExtractor::~DataExtractor() = default;
//------------------------------------------------------------------
-// Clears the object contents back to a default invalid state, and
-// release any references to shared data that this object may
-// contain.
+// Clears the object contents back to a default invalid state, and release any
+// references to shared data that this object may contain.
//------------------------------------------------------------------
void DataExtractor::Clear() {
m_start = nullptr;
@@ -223,8 +221,8 @@ void DataExtractor::Clear() {
}
//------------------------------------------------------------------
-// If this object contains shared data, this function returns the
-// offset into that shared data. Else zero is returned.
+// If this object contains shared data, this function returns the offset into
+// that shared data. Else zero is returned.
//------------------------------------------------------------------
size_t DataExtractor::GetSharedDataOffset() const {
if (m_start != nullptr) {
@@ -241,13 +239,12 @@ size_t DataExtractor::GetSharedDataOffset() const {
}
//----------------------------------------------------------------------
-// Set the data with which this object will extract from to data
-// starting at BYTES and set the length of the data to LENGTH bytes
-// long. The data is externally owned must be around at least as
-// long as this object points to the data. No copy of the data is
-// made, this object just refers to this data and can extract from
-// it. If this object refers to any shared data upon entry, the
-// reference to that data will be released. Is SWAP is set to true,
+// Set the data with which this object will extract from to data starting at
+// BYTES and set the length of the data to LENGTH bytes long. The data is
+// externally owned must be around at least as long as this object points to
+// the data. No copy of the data is made, this object just refers to this data
+// and can extract from it. If this object refers to any shared data upon
+// entry, the reference to that data will be released. Is SWAP is set to true,
// any data extracted will be endian swapped.
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
@@ -265,18 +262,16 @@ lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length,
}
//----------------------------------------------------------------------
-// Assign the data for this object to be a subrange in "data"
-// starting "data_offset" bytes into "data" and ending "data_length"
-// bytes later. If "data_offset" is not a valid offset into "data",
-// then this object will contain no bytes. If "data_offset" is
-// within "data" yet "data_length" is too large, the length will be
-// capped at the number of bytes remaining in "data". If "data"
-// contains a shared pointer to other data, then a ref counted
-// pointer to that data will be made in this object. If "data"
-// doesn't contain a shared pointer to data, then the bytes referred
-// to in "data" will need to exist at least as long as this object
-// refers to those bytes. The address size and endian swap settings
-// are copied from the current values in "data".
+// Assign the data for this object to be a subrange in "data" starting
+// "data_offset" bytes into "data" and ending "data_length" bytes later. If
+// "data_offset" is not a valid offset into "data", then this object will
+// contain no bytes. If "data_offset" is within "data" yet "data_length" is too
+// large, the length will be capped at the number of bytes remaining in "data".
+// If "data" contains a shared pointer to other data, then a ref counted
+// pointer to that data will be made in this object. If "data" doesn't contain
+// a shared pointer to data, then the bytes referred to in "data" will need to
+// exist at least as long as this object refers to those bytes. The address
+// size and endian swap settings are copied from the current values in "data".
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
offset_t data_offset,
@@ -303,18 +298,17 @@ lldb::offset_t DataExtractor::SetData(const DataExtractor &data,
}
//----------------------------------------------------------------------
-// Assign the data for this object to be a subrange of the shared
-// data in "data_sp" starting "data_offset" bytes into "data_sp"
-// and ending "data_length" bytes later. If "data_offset" is not
-// a valid offset into "data_sp", then this object will contain no
-// bytes. If "data_offset" is within "data_sp" yet "data_length" is
-// too large, the length will be capped at the number of bytes
-// remaining in "data_sp". A ref counted pointer to the data in
-// "data_sp" will be made in this object IF the number of bytes this
-// object refers to in greater than zero (if at least one byte was
-// available starting at "data_offset") to ensure the data stays
-// around as long as it is needed. The address size and endian swap
-// settings will remain unchanged from their current settings.
+// Assign the data for this object to be a subrange of the shared data in
+// "data_sp" starting "data_offset" bytes into "data_sp" and ending
+// "data_length" bytes later. If "data_offset" is not a valid offset into
+// "data_sp", then this object will contain no bytes. If "data_offset" is
+// within "data_sp" yet "data_length" is too large, the length will be capped
+// at the number of bytes remaining in "data_sp". A ref counted pointer to the
+// data in "data_sp" will be made in this object IF the number of bytes this
+// object refers to in greater than zero (if at least one byte was available
+// starting at "data_offset") to ensure the data stays around as long as it is
+// needed. The address size and endian swap settings will remain unchanged from
+// their current settings.
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
offset_t data_offset,
@@ -340,8 +334,8 @@ lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
size_t new_size = GetByteSize();
- // Don't hold a shared pointer to the data buffer if we don't share
- // any valid bytes in the shared buffer.
+ // Don't hold a shared pointer to the data buffer if we don't share any valid
+ // bytes in the shared buffer.
if (new_size == 0)
m_data_sp.reset();
@@ -349,8 +343,8 @@ lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp,
}
//----------------------------------------------------------------------
-// Extract a single unsigned char from the binary data and update
-// the offset pointed to by "offset_ptr".
+// Extract a single unsigned char from the binary data and update the offset
+// pointed to by "offset_ptr".
//
// RETURNS the byte that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -362,13 +356,12 @@ uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extract "count" unsigned chars from the binary data and update the
-// offset pointed to by "offset_ptr". The extracted data is copied into
-// "dst".
+// Extract "count" unsigned chars from the binary data and update the offset
+// pointed to by "offset_ptr". The extracted data is copied into "dst".
//
// RETURNS the non-nullptr buffer pointer upon successful extraction of
-// all the requested bytes, or nullptr when the data is not available in
-// the buffer due to being out of bounds, or insufficient data.
+// all the requested bytes, or nullptr when the data is not available in the
+// buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
uint32_t count) const {
@@ -384,8 +377,8 @@ void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst,
}
//----------------------------------------------------------------------
-// Extract a single uint16_t from the data and update the offset
-// pointed to by "offset_ptr".
+// Extract a single uint16_t from the data and update the offset pointed to by
+// "offset_ptr".
//
// RETURNS the uint16_t that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -432,13 +425,12 @@ uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extract "count" uint16_t values from the binary data and update
-// the offset pointed to by "offset_ptr". The extracted data is
-// copied into "dst".
+// Extract "count" uint16_t values from the binary data and update the offset
+// pointed to by "offset_ptr". The extracted data is copied into "dst".
//
// RETURNS the non-nullptr buffer pointer upon successful extraction of
-// all the requested bytes, or nullptr when the data is not available
-// in the buffer due to being out of bounds, or insufficient data.
+// all the requested bytes, or nullptr when the data is not available in the
+// buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
uint32_t count) const {
@@ -465,8 +457,8 @@ void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst,
}
//----------------------------------------------------------------------
-// Extract a single uint32_t from the data and update the offset
-// pointed to by "offset_ptr".
+// Extract a single uint32_t from the data and update the offset pointed to by
+// "offset_ptr".
//
// RETURNS the uint32_t that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -484,13 +476,12 @@ uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extract "count" uint32_t values from the binary data and update
-// the offset pointed to by "offset_ptr". The extracted data is
-// copied into "dst".
+// Extract "count" uint32_t values from the binary data and update the offset
+// pointed to by "offset_ptr". The extracted data is copied into "dst".
//
// RETURNS the non-nullptr buffer pointer upon successful extraction of
-// all the requested bytes, or nullptr when the data is not available
-// in the buffer due to being out of bounds, or insufficient data.
+// all the requested bytes, or nullptr when the data is not available in the
+// buffer due to being out of bounds, or insufficient data.
//----------------------------------------------------------------------
void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
uint32_t count) const {
@@ -517,8 +508,8 @@ void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst,
}
//----------------------------------------------------------------------
-// Extract a single uint64_t from the data and update the offset
-// pointed to by "offset_ptr".
+// Extract a single uint64_t from the data and update the offset pointed to by
+// "offset_ptr".
//
// RETURNS the uint64_t that was extracted, or zero on failure.
//----------------------------------------------------------------------
@@ -538,9 +529,9 @@ uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const {
//----------------------------------------------------------------------
// GetU64
//
-// Get multiple consecutive 64 bit values. Return true if the entire
-// read succeeds and increment the offset pointed to by offset_ptr, else
-// return false and leave the offset pointed to by offset_ptr unchanged.
+// Get multiple consecutive 64 bit values. Return true if the entire read
+// succeeds and increment the offset pointed to by offset_ptr, else return
+// false and leave the offset pointed to by offset_ptr unchanged.
//----------------------------------------------------------------------
void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst,
uint32_t count) const {
@@ -708,10 +699,10 @@ long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const {
}
//------------------------------------------------------------------
-// Extract a single address from the data and update the offset
-// pointed to by "offset_ptr". The size of the extracted address
-// comes from the "this->m_addr_size" member variable and should be
-// set correctly prior to extracting any address values.
+// Extract a single address from the data and update the offset pointed to by
+// "offset_ptr". The size of the extracted address comes from the
+// "this->m_addr_size" member variable and should be set correctly prior to
+// extracting any address values.
//
// RETURNS the address that was extracted, or zero on failure.
//------------------------------------------------------------------
@@ -730,10 +721,10 @@ uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const {
}
//------------------------------------------------------------------
-// Extract a single pointer from the data and update the offset
-// pointed to by "offset_ptr". The size of the extracted pointer
-// comes from the "this->m_addr_size" member variable and should be
-// set correctly prior to extracting any pointer values.
+// Extract a single pointer from the data and update the offset pointed to by
+// "offset_ptr". The size of the extracted pointer comes from the
+// "this->m_addr_size" member variable and should be set correctly prior to
+// extracting any pointer values.
//
// RETURNS the pointer that was extracted, or zero on failure.
//------------------------------------------------------------------
@@ -804,9 +795,9 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
const uint8_t *src = (const uint8_t *)PeekData(src_offset, src_len);
if (src) {
if (dst_len >= src_len) {
- // We are copying the entire value from src into dst.
- // Calculate how many, if any, zeroes we need for the most
- // significant bytes if "dst_len" is greater than "src_len"...
+ // We are copying the entire value from src into dst. Calculate how many,
+ // if any, zeroes we need for the most significant bytes if "dst_len" is
+ // greater than "src_len"...
const size_t num_zeroes = dst_len - src_len;
if (dst_byte_order == eByteOrderBig) {
// Big endian, so we lead with zeroes...
@@ -863,15 +854,13 @@ DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
}
//----------------------------------------------------------------------
-// Extracts a variable length NULL terminated C string from
-// the data at the offset pointed to by "offset_ptr". The
-// "offset_ptr" will be updated with the offset of the byte that
-// follows the NULL terminator byte.
+// Extracts a variable length NULL terminated C string from the data at the
+// offset pointed to by "offset_ptr". The "offset_ptr" will be updated with
+// the offset of the byte that follows the NULL terminator byte.
//
-// If the offset pointed to by "offset_ptr" is out of bounds, or if
-// "length" is non-zero and there aren't enough available
-// bytes, nullptr will be returned and "offset_ptr" will not be
-// updated.
+// If the offset pointed to by "offset_ptr" is out of bounds, or if "length" is
+// non-zero and there aren't enough available bytes, nullptr will be returned
+// and "offset_ptr" will not be updated.
//----------------------------------------------------------------------
const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
const char *cstr = (const char *)PeekData(*offset_ptr, 1);
@@ -890,23 +879,21 @@ const char *DataExtractor::GetCStr(offset_t *offset_ptr) const {
}
// We reached the end of the data without finding a NULL C string
- // terminator. Fall through and return nullptr otherwise anyone that
- // would have used the result as a C string can wander into
- // unknown memory...
+ // terminator. Fall through and return nullptr otherwise anyone that would
+ // have used the result as a C string can wander into unknown memory...
}
return nullptr;
}
//----------------------------------------------------------------------
-// Extracts a NULL terminated C string from the fixed length field of
-// length "len" at the offset pointed to by "offset_ptr".
-// The "offset_ptr" will be updated with the offset of the byte that
-// follows the fixed length field.
+// Extracts a NULL terminated C string from the fixed length field of length
+// "len" at the offset pointed to by "offset_ptr". The "offset_ptr" will be
+// updated with the offset of the byte that follows the fixed length field.
//
-// If the offset pointed to by "offset_ptr" is out of bounds, or if
-// the offset plus the length of the field is out of bounds, or if the
-// field does not contain a NULL terminator byte, nullptr will be returned
-// and "offset_ptr" will not be updated.
+// If the offset pointed to by "offset_ptr" is out of bounds, or if the offset
+// plus the length of the field is out of bounds, or if the field does not
+// contain a NULL terminator byte, nullptr will be returned and "offset_ptr"
+// will not be updated.
//----------------------------------------------------------------------
const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
const char *cstr = (const char *)PeekData(*offset_ptr, len);
@@ -921,22 +908,22 @@ const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const {
}
//------------------------------------------------------------------
-// Peeks at a string in the contained data. No verification is done
-// to make sure the entire string lies within the bounds of this
-// object's data, only "offset" is verified to be a valid offset.
+// Peeks at a string in the contained data. No verification is done to make
+// sure the entire string lies within the bounds of this object's data, only
+// "offset" is verified to be a valid offset.
//
-// Returns a valid C string pointer if "offset" is a valid offset in
-// this object's data, else nullptr is returned.
+// Returns a valid C string pointer if "offset" is a valid offset in this
+// object's data, else nullptr is returned.
//------------------------------------------------------------------
const char *DataExtractor::PeekCStr(offset_t offset) const {
return (const char *)PeekData(offset, 1);
}
//----------------------------------------------------------------------
-// Extracts an unsigned LEB128 number from this object's data
-// starting at the offset pointed to by "offset_ptr". The offset
-// pointed to by "offset_ptr" will be updated with the offset of the
-// byte following the last extracted byte.
+// Extracts an unsigned LEB128 number from this object's data starting at the
+// offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
+// will be updated with the offset of the byte following the last extracted
+// byte.
//
// Returned the extracted integer value.
//----------------------------------------------------------------------
@@ -968,10 +955,10 @@ uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Extracts an signed LEB128 number from this object's data
-// starting at the offset pointed to by "offset_ptr". The offset
-// pointed to by "offset_ptr" will be updated with the offset of the
-// byte following the last extracted byte.
+// Extracts an signed LEB128 number from this object's data starting at the
+// offset pointed to by "offset_ptr". The offset pointed to by "offset_ptr"
+// will be updated with the offset of the byte following the last extracted
+// byte.
//
// Returned the extracted integer value.
//----------------------------------------------------------------------
@@ -1010,10 +997,10 @@ int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const {
}
//----------------------------------------------------------------------
-// Skips a ULEB128 number (signed or unsigned) from this object's
-// data starting at the offset pointed to by "offset_ptr". The
-// offset pointed to by "offset_ptr" will be updated with the offset
-// of the byte following the last extracted byte.
+// Skips a ULEB128 number (signed or unsigned) from this object's data starting
+// at the offset pointed to by "offset_ptr". The offset pointed to by
+// "offset_ptr" will be updated with the offset of the byte following the last
+// extracted byte.
//
// Returns the number of bytes consumed during the extraction.
//----------------------------------------------------------------------
@@ -1036,15 +1023,14 @@ uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const {
//----------------------------------------------------------------------
// Dumps bytes from this object's data to the stream "s" starting
-// "start_offset" bytes into this data, and ending with the byte
-// before "end_offset". "base_addr" will be added to the offset
-// into the dumped data when showing the offset into the data in the
-// output information. "num_per_line" objects of type "type" will
-// be dumped with the option to override the format for each object
-// with "type_format". "type_format" is a printf style formatting
-// string. If "type_format" is nullptr, then an appropriate format
-// string will be used for the supplied "type". If the stream "s"
-// is nullptr, then the output will be send to Log().
+// "start_offset" bytes into this data, and ending with the byte before
+// "end_offset". "base_addr" will be added to the offset into the dumped data
+// when showing the offset into the data in the output information.
+// "num_per_line" objects of type "type" will be dumped with the option to
+// override the format for each object with "type_format". "type_format" is a
+// printf style formatting string. If "type_format" is nullptr, then an
+// appropriate format string will be used for the supplied "type". If the
+// stream "s" is nullptr, then the output will be send to Log().
//----------------------------------------------------------------------
lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
offset_t length, uint64_t base_addr,
@@ -1107,24 +1093,6 @@ lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset,
return offset; // Return the offset at which we ended up
}
-//----------------------------------------------------------------------
-// DumpUUID
-//
-// Dump out a UUID starting at 'offset' bytes into the buffer
-//----------------------------------------------------------------------
-void DataExtractor::DumpUUID(Stream *s, offset_t offset) const {
- if (s) {
- const uint8_t *uuid_data = PeekData(offset, 16);
- if (uuid_data) {
- lldb_private::UUID uuid(uuid_data, 16);
- uuid.Dump(s);
- } else {
- s->Printf("<not enough data for UUID at offset 0x%8.8" PRIx64 ">",
- offset);
- }
- }
-}
-
size_t DataExtractor::Copy(DataExtractor &dest_data) const {
if (m_data_sp) {
// we can pass along the SP to the data
diff --git a/source/Utility/Environment.cpp b/source/Utility/Environment.cpp
new file mode 100644
index 000000000000..ea20267a2362
--- /dev/null
+++ b/source/Utility/Environment.cpp
@@ -0,0 +1,50 @@
+//===-- Environment.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/Environment.h"
+
+using namespace lldb_private;
+
+char *Environment::Envp::make_entry(llvm::StringRef Key,
+ llvm::StringRef Value) {
+ const size_t size = Key.size() + 1 /*=*/ + Value.size() + 1 /*\0*/;
+ char *Result = reinterpret_cast<char *>(
+ Allocator.Allocate(sizeof(char) * size, alignof(char)));
+ char *Next = Result;
+
+ Next = std::copy(Key.begin(), Key.end(), Next);
+ *Next++ = '=';
+ Next = std::copy(Value.begin(), Value.end(), Next);
+ *Next++ = '\0';
+
+ return Result;
+}
+
+Environment::Envp::Envp(const Environment &Env) {
+ Data = reinterpret_cast<char **>(
+ Allocator.Allocate(sizeof(char *) * (Env.size() + 1), alignof(char *)));
+ char **Next = Data;
+ for (const auto &KV : Env)
+ *Next++ = make_entry(KV.first(), KV.second);
+ *Next++ = nullptr;
+}
+
+Environment::Environment(const char *const *Env) {
+ if (!Env)
+ return;
+ while (*Env)
+ insert(*Env++);
+}
+
+void Environment::insert(const_iterator first, const_iterator last) {
+ while (first != last) {
+ try_emplace(first->first(), first->second);
+ ++first;
+ }
+}
diff --git a/source/Utility/FastDemangle.cpp b/source/Utility/FastDemangle.cpp
index 90326c5f15c3..d92670a9199b 100644
--- a/source/Utility/FastDemangle.cpp
+++ b/source/Utility/FastDemangle.cpp
@@ -25,7 +25,7 @@
namespace {
-/// @brief Represents the collection of qualifiers on a type
+/// Represents the collection of qualifiers on a type
enum Qualifiers {
QualifierNone = 0,
@@ -37,7 +37,7 @@ enum Qualifiers {
QualifierPointer = 32
};
-/// @brief Categorizes the recognized operators
+/// Categorizes the recognized operators
enum class OperatorKind {
Unary,
@@ -50,23 +50,23 @@ enum class OperatorKind {
NoMatch
};
-/// @brief Represents one of the recognized two-character operator
-/// abbreviations used when parsing operators as names and expressions
+/// Represents one of the recognized two-character operator abbreviations used
+/// when parsing operators as names and expressions
struct Operator {
const char *name;
OperatorKind kind;
};
-/// @brief Represents a range of characters in the output buffer, typically for
-/// use with RewriteRange()
+/// Represents a range of characters in the output buffer, typically for use
+/// with RewriteRange()
struct BufferRange {
int offset;
int length;
};
-/// @brief Transient state required while parsing a name
+/// Transient state required while parsing a name
struct NameState {
bool parse_function_params;
@@ -75,12 +75,13 @@ struct NameState {
BufferRange last_name_range;
};
-/// @brief LLDB's fast C++ demangler
+/// LLDB's fast C++ demangler
///
/// This is an incomplete implementation designed to speed up the demangling
/// process that is often a bottleneck when LLDB stops a process for the first
/// time. Where the implementation doesn't know how to demangle a symbol it
-/// fails gracefully to allow the caller to fall back to the existing demangler.
+/// fails gracefully to allow the caller to fall back to the existing
+/// demangler.
///
/// Over time the full mangling spec should be supported without compromising
/// performance for the most common cases.
@@ -91,7 +92,7 @@ public:
// Public API
//----------------------------------------------------
- /// @brief Create a SymbolDemangler
+ /// Create a SymbolDemangler
///
/// The newly created demangler allocates and owns scratch memory sufficient
/// for demangling typical symbols. Additional memory will be allocated if
@@ -107,18 +108,18 @@ public:
m_owns_m_rewrite_ranges = true;
}
- /// @brief Create a SymbolDemangler that uses provided scratch memory
+ /// Create a SymbolDemangler that uses provided scratch memory
///
/// The provided memory is not owned by the demangler. It will be
- /// overwritten during calls to GetDemangledCopy() but can be used for
- /// other purposes between calls. The provided memory will not be freed
- /// when this instance is destroyed.
+ /// overwritten during calls to GetDemangledCopy() but can be used for other
+ /// purposes between calls. The provided memory will not be freed when this
+ /// instance is destroyed.
///
/// If demangling a symbol requires additional space it will be allocated
/// and managed by the demangler instance.
///
- /// @param storage_ptr Valid pointer to at least storage_size bytes of
- /// space that the SymbolDemangler can use during demangling
+ /// @param storage_ptr Valid pointer to at least storage_size bytes of space
+ /// that the SymbolDemangler can use during demangling
///
/// @param storage_size Number of bytes of space available scratch memory
/// referenced by storage_ptr
@@ -138,8 +139,8 @@ public:
m_owns_buffer = false;
}
- /// @brief Destroys the SymbolDemangler and deallocates any scratch
- /// memory that it owns
+ /// Destroys the SymbolDemangler and deallocates any scratch memory that it
+ /// owns
~SymbolDemangler() {
if (m_owns_buffer)
@@ -153,11 +154,11 @@ public:
int highwater_buffer = 0;
#endif
- /// @brief Parses the provided mangled name and returns a newly allocated
+ /// Parses the provided mangled name and returns a newly allocated
/// demangling
///
- /// @param mangled_name Valid null-terminated C++ mangled name following
- /// the Itanium C++ ABI mangling specification as implemented by Clang
+ /// @param mangled_name Valid null-terminated C++ mangled name following the
+ /// Itanium C++ ABI mangling specification as implemented by Clang
///
/// @result Newly allocated null-terminated demangled name when demangling
/// is successful, and nullptr when demangling fails. The caller is
@@ -200,8 +201,7 @@ private:
if (growth > 1 << 20)
growth = 1 << 20;
- // ... but never grow by less than requested,
- // or 1K, whichever is greater
+ // ... but never grow by less than requested, or 1K, whichever is greater
if (min_growth < 1024)
min_growth = 1024;
if (growth < min_growth)
@@ -282,9 +282,8 @@ private:
if (index == m_rewrite_ranges_size)
break;
- // Affected ranges are either shuffled forward when after the
- // insertion but before the source, or backward when inside the
- // source
+ // Affected ranges are either shuffled forward when after the insertion
+ // but before the source, or backward when inside the source
int candidate_offset = m_rewrite_ranges[index].offset;
if (candidate_offset >= insertion_point_cookie) {
if (candidate_offset < source_range.offset) {
@@ -402,8 +401,7 @@ private:
//----------------------------------------------------
// Rewrite methods
//
- // Write another copy of content already present
- // earlier in the output buffer
+ // Write another copy of content already present earlier in the output buffer
//----------------------------------------------------
void RewriteRange(BufferRange range) {
@@ -436,11 +434,11 @@ private:
//----------------------------------------------------
// TryParse methods
//
- // Provide information with return values instead of
- // writing to the output buffer
+ // Provide information with return values instead of writing to the output
+ // buffer
//
- // Values indicating failure guarantee that the pre-
- // call m_read_ptr is unchanged
+ // Values indicating failure guarantee that the pre- call m_read_ptr is
+ // unchanged
//----------------------------------------------------
int TryParseNumber() {
@@ -820,8 +818,8 @@ private:
}
// <CV-qualifiers> ::= [r] [V] [K]
- // <ref-qualifier> ::= R # & ref-qualifier
- // <ref-qualifier> ::= O # && ref-qualifier
+ // <ref-qualifier> ::= R # & ref-qualifier <ref-qualifier>
+ // ::= O # && ref-qualifier
int TryParseQualifiers(bool allow_cv, bool allow_ro) {
int qualifiers = QualifierNone;
@@ -890,11 +888,10 @@ private:
//----------------------------------------------------
// Parse methods
//
- // Consume input starting from m_read_ptr and produce
- // buffered output at m_write_ptr
+ // Consume input starting from m_read_ptr and produce buffered output at
+ // m_write_ptr
//
- // Failures return false and may leave m_read_ptr in an
- // indeterminate state
+ // Failures return false and may leave m_read_ptr in an indeterminate state
//----------------------------------------------------
bool Parse(char character) {
@@ -932,17 +929,14 @@ private:
// <substitution> ::= S <seq-id> _
// ::= S_
- // <substitution> ::= Sa # ::std::allocator
- // <substitution> ::= Sb # ::std::basic_string
- // <substitution> ::= Ss # ::std::basic_string < char,
+ // <substitution> ::= Sa # ::std::allocator <substitution> ::= Sb #
+ // ::std::basic_string <substitution> ::= Ss # ::std::basic_string < char,
// ::std::char_traits<char>,
// ::std::allocator<char> >
// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char>
- // >
- // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char>
- // >
- // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char>
- // >
+ // > <substitution> ::= So # ::std::basic_ostream<char,
+ // std::char_traits<char> > <substitution> ::= Sd #
+ // ::std::basic_iostream<char, std::char_traits<char> >
bool ParseSubstitution() {
const char *substitution;
@@ -967,7 +961,8 @@ private:
break;
default:
// A failed attempt to parse a number will return -1 which turns out to be
- // perfect here as S_ is the first substitution, S0_ the next and so forth
+ // perfect here as S_ is the first substitution, S0_ the next and so
+ // forth
int substitution_index = TryParseBase36Number();
if (*m_read_ptr++ != '_') {
#ifdef DEBUG_FAILURES
@@ -984,17 +979,17 @@ private:
// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
//
- // <bare-function-type> ::= <signature type>+ # types are possible return
- // type, then parameter types
+ // <bare-function-type> ::= <signature type>+ # types are possible
+ // return type, then parameter types
bool ParseFunctionType(int inner_qualifiers = QualifierNone) {
#ifdef DEBUG_FAILURES
printf("*** Function types not supported\n");
#endif
// TODO: first steps toward an implementation follow, but they're far
- // from complete. Function types tend to bracket other types eg:
- // int (*)() when used as the type for "name" becomes int (*name)().
- // This makes substitution et al ... interesting.
+ // from complete. Function types tend to bracket other types eg: int (*)()
+ // when used as the type for "name" becomes int (*name)(). This makes
+ // substitution et al ... interesting.
return false;
#if 0 // TODO
@@ -1154,8 +1149,8 @@ private:
if (!Parse('_'))
return false;
- // When no number is present we get -1, which is convenient since
- // T_ is the zeroth element T0_ is element 1, and so on
+ // When no number is present we get -1, which is convenient since T_ is the
+ // zeroth element T0_ is element 1, and so on
return RewriteTemplateArg(count + 1);
}
@@ -1193,13 +1188,13 @@ private:
// ::= G <type> # imaginary (C 2000)
// ::= Dp <type> # pack expansion (C++0x)
// ::= U <source-name> <type> # vendor extended type qualifier
- // extension := U <objc-name> <objc-type> # objc-type<identifier>
- // extension := <vector-type> # <vector-type> starts with Dv
+ // extension := U <objc-name> <objc-type> # objc-type<identifier> extension
+ // := <vector-type> # <vector-type> starts with Dv
// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 +
- // <number of digits in k1> + k1
- // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name>
- // 11objc_object -> id<source-name>
+ // <number of digits in k1> + k1 <objc-type> := <source-name> #
+ // PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-
+ // name>
bool ParseType() {
#ifdef DEBUG_FAILURES
@@ -1476,8 +1471,8 @@ private:
// ::= <unnamed-type-name>
bool ParseUnqualifiedName(NameState &name_state) {
- // Note that these are detected directly in ParseNestedName for
- // performance rather than switching on the same options twice
+ // Note that these are detected directly in ParseNestedName for performance
+ // rather than switching on the same options twice
char next = *m_read_ptr;
switch (next) {
case 'C':
@@ -1943,7 +1938,8 @@ private:
break;
}
- // Record a substitution candidate for all prefixes, but not the full name
+ // Record a substitution candidate for all prefixes, but not the full
+ // name
if (suppress_substitution)
suppress_substitution = false;
else
@@ -2247,9 +2243,9 @@ private:
if (next == 'E' || next == '\0' || next == '.')
return true;
- // Clang has a bad habit of making unique manglings by just sticking numbers
- // on the end of a symbol,
- // which is ambiguous with malformed source name manglings
+ // Clang has a bad habit of making unique manglings by just sticking
+ // numbers on the end of a symbol, which is ambiguous with malformed source
+ // name manglings
const char *before_clang_uniquing_test = m_read_ptr;
if (TryParseNumber()) {
if (*m_read_ptr == '\0')
diff --git a/source/Utility/FileSpec.cpp b/source/Utility/FileSpec.cpp
index 72f86917b813..b6952f7e3eb0 100644
--- a/source/Utility/FileSpec.cpp
+++ b/source/Utility/FileSpec.cpp
@@ -12,17 +12,15 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/TildeExpressionResolver.h"
-#include "llvm/ADT/SmallString.h" // for SmallString
-#include "llvm/ADT/SmallVector.h" // for SmallVectorTemplat...
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h" // for Triple
-#include "llvm/ADT/Twine.h" // for Twine
-#include "llvm/Config/llvm-config.h" // for LLVM_ON_WIN32
-#include "llvm/Support/ErrorOr.h" // for ErrorOr
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h" // for raw_ostream, fs
+#include "llvm/Support/raw_ostream.h"
#include <algorithm> // for replace, min, unique
#include <system_error> // for error_code
@@ -37,113 +35,35 @@ using namespace lldb_private;
namespace {
-static constexpr FileSpec::PathSyntax GetNativeSyntax() {
-#if defined(LLVM_ON_WIN32)
- return FileSpec::ePathSyntaxWindows;
+static constexpr FileSpec::Style GetNativeStyle() {
+#if defined(_WIN32)
+ return FileSpec::Style::windows;
#else
- return FileSpec::ePathSyntaxPosix;
+ return FileSpec::Style::posix;
#endif
}
-bool PathSyntaxIsPosix(FileSpec::PathSyntax syntax) {
- return (syntax == FileSpec::ePathSyntaxPosix ||
- (syntax == FileSpec::ePathSyntaxHostNative &&
- GetNativeSyntax() == FileSpec::ePathSyntaxPosix));
+bool PathStyleIsPosix(FileSpec::Style style) {
+ return (style == FileSpec::Style::posix ||
+ (style == FileSpec::Style::native &&
+ GetNativeStyle() == FileSpec::Style::posix));
}
-const char *GetPathSeparators(FileSpec::PathSyntax syntax) {
- return PathSyntaxIsPosix(syntax) ? "/" : "\\/";
+const char *GetPathSeparators(FileSpec::Style style) {
+ return llvm::sys::path::get_separator(style).data();
}
-char GetPreferredPathSeparator(FileSpec::PathSyntax syntax) {
- return GetPathSeparators(syntax)[0];
+char GetPreferredPathSeparator(FileSpec::Style style) {
+ return GetPathSeparators(style)[0];
}
-bool IsPathSeparator(char value, FileSpec::PathSyntax syntax) {
- return value == '/' || (!PathSyntaxIsPosix(syntax) && value == '\\');
-}
-
-void Normalize(llvm::SmallVectorImpl<char> &path, FileSpec::PathSyntax syntax) {
- if (PathSyntaxIsPosix(syntax))
- return;
-
- std::replace(path.begin(), path.end(), '\\', '/');
- // Windows path can have \\ slashes which can be changed by replace
- // call above to //. Here we remove the duplicate.
- auto iter = std::unique(path.begin(), path.end(), [](char &c1, char &c2) {
- return (c1 == '/' && c2 == '/');
- });
- path.erase(iter, path.end());
-}
-
-void Denormalize(llvm::SmallVectorImpl<char> &path,
- FileSpec::PathSyntax syntax) {
- if (PathSyntaxIsPosix(syntax))
+void Denormalize(llvm::SmallVectorImpl<char> &path, FileSpec::Style style) {
+ if (PathStyleIsPosix(style))
return;
std::replace(path.begin(), path.end(), '/', '\\');
}
-size_t FilenamePos(llvm::StringRef str, FileSpec::PathSyntax syntax) {
- if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1])
- return 0;
-
- if (str.size() > 0 && IsPathSeparator(str.back(), syntax))
- return str.size() - 1;
-
- size_t pos = str.find_last_of(GetPathSeparators(syntax), str.size() - 1);
-
- if (!PathSyntaxIsPosix(syntax) && pos == llvm::StringRef::npos)
- pos = str.find_last_of(':', str.size() - 2);
-
- if (pos == llvm::StringRef::npos ||
- (pos == 1 && IsPathSeparator(str[0], syntax)))
- return 0;
-
- return pos + 1;
-}
-
-size_t RootDirStart(llvm::StringRef str, FileSpec::PathSyntax syntax) {
- // case "c:/"
- if (!PathSyntaxIsPosix(syntax) &&
- (str.size() > 2 && str[1] == ':' && IsPathSeparator(str[2], syntax)))
- return 2;
-
- // case "//"
- if (str.size() == 2 && IsPathSeparator(str[0], syntax) && str[0] == str[1])
- return llvm::StringRef::npos;
-
- // case "//net"
- if (str.size() > 3 && IsPathSeparator(str[0], syntax) && str[0] == str[1] &&
- !IsPathSeparator(str[2], syntax))
- return str.find_first_of(GetPathSeparators(syntax), 2);
-
- // case "/"
- if (str.size() > 0 && IsPathSeparator(str[0], syntax))
- return 0;
-
- return llvm::StringRef::npos;
-}
-
-size_t ParentPathEnd(llvm::StringRef path, FileSpec::PathSyntax syntax) {
- size_t end_pos = FilenamePos(path, syntax);
-
- bool filename_was_sep =
- path.size() > 0 && IsPathSeparator(path[end_pos], syntax);
-
- // Skip separators except for root dir.
- size_t root_dir_pos = RootDirStart(path.substr(0, end_pos), syntax);
-
- while (end_pos > 0 && (end_pos - 1) != root_dir_pos &&
- IsPathSeparator(path[end_pos - 1], syntax))
- --end_pos;
-
- if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
- return llvm::StringRef::npos;
-
- return end_pos;
-}
-
} // end anonymous namespace
void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
@@ -164,28 +84,27 @@ void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
}
}
-FileSpec::FileSpec() : m_syntax(GetNativeSyntax()) {}
+FileSpec::FileSpec() : m_style(GetNativeStyle()) {}
//------------------------------------------------------------------
-// Default constructor that can take an optional full path to a
-// file on disk.
+// Default constructor that can take an optional full path to a file on disk.
//------------------------------------------------------------------
-FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, PathSyntax syntax)
- : m_syntax(syntax) {
- SetFile(path, resolve_path, syntax);
+FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, Style style)
+ : m_style(style) {
+ SetFile(path, resolve_path, style);
}
FileSpec::FileSpec(llvm::StringRef path, bool resolve_path,
const llvm::Triple &Triple)
: FileSpec{path, resolve_path,
- Triple.isOSWindows() ? ePathSyntaxWindows : ePathSyntaxPosix} {}
+ Triple.isOSWindows() ? Style::windows : Style::posix} {}
//------------------------------------------------------------------
// Copy constructor
//------------------------------------------------------------------
FileSpec::FileSpec(const FileSpec &rhs)
: m_directory(rhs.m_directory), m_filename(rhs.m_filename),
- m_is_resolved(rhs.m_is_resolved), m_syntax(rhs.m_syntax) {}
+ m_is_resolved(rhs.m_is_resolved), m_style(rhs.m_style) {}
//------------------------------------------------------------------
// Copy constructor
@@ -200,6 +119,100 @@ FileSpec::FileSpec(const FileSpec *rhs) : m_directory(), m_filename() {
//------------------------------------------------------------------
FileSpec::~FileSpec() {}
+namespace {
+//------------------------------------------------------------------
+/// Safely get a character at the specified index.
+///
+/// @param[in] path
+/// A full, partial, or relative path to a file.
+///
+/// @param[in] i
+/// An index into path which may or may not be valid.
+///
+/// @return
+/// The character at index \a i if the index is valid, or 0 if
+/// the index is not valid.
+//------------------------------------------------------------------
+inline char safeCharAtIndex(const llvm::StringRef &path, size_t i) {
+ if (i < path.size())
+ return path[i];
+ return 0;
+}
+
+//------------------------------------------------------------------
+/// Check if a path needs to be normalized.
+///
+/// Check if a path needs to be normalized. We currently consider a
+/// path to need normalization if any of the following are true
+/// - path contains "/./"
+/// - path contains "/../"
+/// - path contains "//"
+/// - path ends with "/"
+/// Paths that start with "./" or with "../" are not considered to
+/// need normalization since we aren't trying to resolve the path,
+/// we are just trying to remove redundant things from the path.
+///
+/// @param[in] path
+/// A full, partial, or relative path to a file.
+///
+/// @return
+/// Returns \b true if the path needs to be normalized.
+//------------------------------------------------------------------
+bool needsNormalization(const llvm::StringRef &path) {
+ if (path.empty())
+ return false;
+ // We strip off leading "." values so these paths need to be normalized
+ if (path[0] == '.')
+ return true;
+ for (auto i = path.find_first_of("\\/"); i != llvm::StringRef::npos;
+ i = path.find_first_of("\\/", i + 1)) {
+ const auto next = safeCharAtIndex(path, i+1);
+ switch (next) {
+ case 0:
+ // path separator char at the end of the string which should be
+ // stripped unless it is the one and only character
+ return i > 0;
+ case '/':
+ case '\\':
+ // two path separator chars in the middle of a path needs to be
+ // normalized
+ if (i > 0)
+ return true;
+ ++i;
+ break;
+
+ case '.': {
+ const auto next_next = safeCharAtIndex(path, i+2);
+ switch (next_next) {
+ default: break;
+ case 0: return true; // ends with "/."
+ case '/':
+ case '\\':
+ return true; // contains "/./"
+ case '.': {
+ const auto next_next_next = safeCharAtIndex(path, i+3);
+ switch (next_next_next) {
+ default: break;
+ case 0: return true; // ends with "/.."
+ case '/':
+ case '\\':
+ return true; // contains "/../"
+ }
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+
+}
//------------------------------------------------------------------
// Assignment operator.
//------------------------------------------------------------------
@@ -208,26 +221,25 @@ const FileSpec &FileSpec::operator=(const FileSpec &rhs) {
m_directory = rhs.m_directory;
m_filename = rhs.m_filename;
m_is_resolved = rhs.m_is_resolved;
- m_syntax = rhs.m_syntax;
+ m_style = rhs.m_style;
}
return *this;
}
+void FileSpec::SetFile(llvm::StringRef pathname, bool resolve) {
+ SetFile(pathname, resolve, m_style);
+}
+
//------------------------------------------------------------------
-// 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.
+// 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(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.
+void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, Style style) {
m_filename.Clear();
m_directory.Clear();
m_is_resolved = false;
- m_syntax = (syntax == ePathSyntaxHostNative) ? GetNativeSyntax() : syntax;
+ m_style = (style == Style::native) ? GetNativeStyle() : style;
if (pathname.empty())
return;
@@ -239,39 +251,41 @@ void FileSpec::SetFile(llvm::StringRef pathname, bool resolve,
m_is_resolved = true;
}
- Normalize(resolved, m_syntax);
+ // Normalize the path by removing ".", ".." and other redundant components.
+ if (needsNormalization(resolved))
+ llvm::sys::path::remove_dots(resolved, true, m_style);
- llvm::StringRef resolve_path_ref(resolved.c_str());
- size_t dir_end = ParentPathEnd(resolve_path_ref, m_syntax);
- if (dir_end == 0) {
- m_filename.SetString(resolve_path_ref);
+ // Normalize back slashes to forward slashes
+ if (m_style == Style::windows)
+ std::replace(resolved.begin(), resolved.end(), '\\', '/');
+
+ if (resolved.empty()) {
+ // If we have no path after normalization set the path to the current
+ // directory. This matches what python does and also a few other path
+ // utilities.
+ m_filename.SetString(".");
return;
}
- m_directory.SetString(resolve_path_ref.substr(0, dir_end));
-
- size_t filename_begin = dir_end;
- size_t root_dir_start = RootDirStart(resolve_path_ref, m_syntax);
- while (filename_begin != llvm::StringRef::npos &&
- filename_begin < resolve_path_ref.size() &&
- filename_begin != root_dir_start &&
- IsPathSeparator(resolve_path_ref[filename_begin], m_syntax))
- ++filename_begin;
- m_filename.SetString((filename_begin == llvm::StringRef::npos ||
- filename_begin >= resolve_path_ref.size())
- ? "."
- : resolve_path_ref.substr(filename_begin));
+ // Split path into filename and directory. We rely on the underlying char
+ // pointer to be nullptr when the components are empty.
+ llvm::StringRef filename = llvm::sys::path::filename(resolved, m_style);
+ if(!filename.empty())
+ m_filename.SetString(filename);
+ llvm::StringRef directory = llvm::sys::path::parent_path(resolved, m_style);
+ if(!directory.empty())
+ m_directory.SetString(directory);
}
void FileSpec::SetFile(llvm::StringRef path, bool resolve,
const llvm::Triple &Triple) {
return SetFile(path, resolve,
- Triple.isOSWindows() ? ePathSyntaxWindows : ePathSyntaxPosix);
+ Triple.isOSWindows() ? Style::windows : Style::posix);
}
//----------------------------------------------------------------------
-// Convert to pointer operator. This allows code to check any FileSpec
-// objects to see if they contain anything valid using code such as:
+// Convert to pointer operator. This allows code to check any FileSpec objects
+// to see if they contain anything valid using code such as:
//
// if (file_spec)
// {}
@@ -279,8 +293,8 @@ void FileSpec::SetFile(llvm::StringRef path, bool resolve,
FileSpec::operator bool() const { return m_filename || m_directory; }
//----------------------------------------------------------------------
-// Logical NOT operator. This allows code to check any FileSpec
-// objects to see if they are invalid using code such as:
+// Logical NOT operator. This allows code to check any FileSpec objects to see
+// if they are invalid using code such as:
//
// if (!file_spec)
// {}
@@ -307,12 +321,10 @@ bool FileSpec::operator==(const FileSpec &rhs) const {
return true;
// TODO: determine if we want to keep this code in here.
- // The code below was added to handle a case where we were
- // trying to set a file and line breakpoint and one path
- // was resolved, and the other not and the directory was
- // in a mount point that resolved to a more complete path:
- // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling
- // this out...
+ // The code below was added to handle a case where we were trying to set a
+ // file and line breakpoint and one path was resolved, and the other not and
+ // the directory was in a mount point that resolved to a more complete path:
+ // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling this out...
if (IsResolved() && rhs.IsResolved()) {
// Both paths are resolved, no need to look further...
return false;
@@ -324,8 +336,8 @@ bool FileSpec::operator==(const FileSpec &rhs) const {
if (!IsResolved()) {
if (resolved_lhs.ResolvePath()) {
// This path wasn't resolved but now it is. Check if the resolved
- // directory is the same as our unresolved directory, and if so,
- // we can mark this object as resolved to avoid more future resolves
+ // directory is the same as our unresolved directory, and if so, we can
+ // mark this object as resolved to avoid more future resolves
m_is_resolved = (m_directory == resolved_lhs.m_directory);
} else
return false;
@@ -335,16 +347,16 @@ bool FileSpec::operator==(const FileSpec &rhs) const {
if (!rhs.IsResolved()) {
if (resolved_rhs.ResolvePath()) {
// rhs's path wasn't resolved but now it is. Check if the resolved
- // directory is the same as rhs's unresolved directory, and if so,
- // we can mark this object as resolved to avoid more future resolves
+ // directory is the same as rhs's unresolved directory, and if so, we can
+ // mark this object as resolved to avoid more future resolves
rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory);
} else
return false;
}
- // If we reach this point in the code we were able to resolve both paths
- // and since we only resolve the paths if the basenames are equal, then
- // we can just check if both directories are equal...
+ // If we reach this point in the code we were able to resolve both paths and
+ // since we only resolve the paths if the basenames are equal, then we can
+ // just check if both directories are equal...
return DirectoryEquals(rhs);
}
@@ -369,8 +381,8 @@ Stream &lldb_private::operator<<(Stream &s, const FileSpec &f) {
}
//------------------------------------------------------------------
-// Clear this object by releasing both the directory and filename
-// string values and making them both the empty string.
+// Clear this object by releasing both the directory and filename string values
+// and making them both the empty string.
//------------------------------------------------------------------
void FileSpec::Clear() {
m_directory.Clear();
@@ -378,15 +390,14 @@ void FileSpec::Clear() {
}
//------------------------------------------------------------------
-// Compare two FileSpec objects. If "full" is true, then both
-// the directory and the filename must match. If "full" is false,
-// then the directory names for "a" and "b" are only compared if
-// they are both non-empty. This allows a FileSpec object to only
-// contain a filename and it can match FileSpec objects that have
-// matching filenames with different paths.
+// Compare two FileSpec objects. If "full" is true, then both the directory and
+// the filename must match. If "full" is false, then the directory names for
+// "a" and "b" are only compared if they are both non-empty. This allows a
+// FileSpec object to only contain a filename and it can match FileSpec objects
+// that have matching filenames with different paths.
//
-// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b"
-// and "1" if "a" is greater than "b".
+// Return -1 if the "a" is less than "b", 0 if "a" is equal to "b" and "1" if
+// "a" is greater than "b".
//------------------------------------------------------------------
int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
int result = 0;
@@ -396,10 +407,10 @@ int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
// If full is true, then we must compare both the directory and filename.
- // If full is false, then if either directory is empty, then we match on
- // the basename only, and if both directories have valid values, we still
- // do a full compare. This allows for matching when we just have a filename
- // in one of the FileSpec objects.
+ // If full is false, then if either directory is empty, then we match on the
+ // basename only, and if both directories have valid values, we still do a
+ // full compare. This allows for matching when we just have a filename in one
+ // of the FileSpec objects.
if (full || (a.m_directory && b.m_directory)) {
result = ConstString::Compare(a.m_directory, b.m_directory, case_sensitive);
@@ -409,118 +420,33 @@ int FileSpec::Compare(const FileSpec &a, const FileSpec &b, bool full) {
return ConstString::Compare(a.m_filename, b.m_filename, case_sensitive);
}
-bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full,
- bool remove_backups) {
- static ConstString g_dot_string(".");
- static ConstString g_dot_dot_string("..");
-
+bool FileSpec::Equal(const FileSpec &a, const FileSpec &b, bool full) {
// case sensitivity of equality test
const bool case_sensitive = a.IsCaseSensitive() || b.IsCaseSensitive();
-
- bool filenames_equal = ConstString::Equals(a.m_filename,
- b.m_filename,
- case_sensitive);
-
- // The only way two FileSpecs can be equal if their filenames are
- // unequal is if we are removing backups and one or the other filename
- // is a backup string:
- if (!filenames_equal && !remove_backups)
- return false;
+ const bool filenames_equal = ConstString::Equals(a.m_filename,
+ b.m_filename,
+ case_sensitive);
- bool last_component_is_dot = ConstString::Equals(a.m_filename, g_dot_string)
- || ConstString::Equals(a.m_filename,
- g_dot_dot_string)
- || ConstString::Equals(b.m_filename,
- g_dot_string)
- || ConstString::Equals(b.m_filename,
- g_dot_dot_string);
-
- if (!filenames_equal && !last_component_is_dot)
+ if (!filenames_equal)
return false;
if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty()))
return filenames_equal;
- if (remove_backups == false)
- return a == b;
-
- if (a == b)
- return true;
-
- return Equal(a.GetNormalizedPath(), b.GetNormalizedPath(), full, false);
-}
-
-FileSpec FileSpec::GetNormalizedPath() const {
- // Fast path. Do nothing if the path is not interesting.
- if (!m_directory.GetStringRef().contains(".") &&
- !m_directory.GetStringRef().contains("//") &&
- m_filename.GetStringRef() != ".." && m_filename.GetStringRef() != ".")
- return *this;
-
- llvm::SmallString<64> path, result;
- const bool normalize = false;
- GetPath(path, normalize);
- llvm::StringRef rest(path);
-
- // We will not go below root dir.
- size_t root_dir_start = RootDirStart(path, m_syntax);
- const bool absolute = root_dir_start != llvm::StringRef::npos;
- if (absolute) {
- result += rest.take_front(root_dir_start + 1);
- rest = rest.drop_front(root_dir_start + 1);
- } else {
- if (m_syntax == ePathSyntaxWindows && path.size() > 2 && path[1] == ':') {
- result += rest.take_front(2);
- rest = rest.drop_front(2);
- }
- }
-
- bool anything_added = false;
- llvm::SmallVector<llvm::StringRef, 0> components, processed;
- rest.split(components, '/', -1, false);
- processed.reserve(components.size());
- for (auto component : components) {
- if (component == ".")
- continue; // Skip these.
- if (component != "..") {
- processed.push_back(component);
- continue; // Regular file name.
- }
- if (!processed.empty()) {
- processed.pop_back();
- continue; // Dots. Go one level up if we can.
- }
- if (absolute)
- continue; // We're at the top level. Cannot go higher than that. Skip.
-
- result += component; // We're a relative path. We need to keep these.
- result += '/';
- anything_added = true;
- }
- for (auto component : processed) {
- result += component;
- result += '/';
- anything_added = true;
- }
- if (anything_added)
- result.pop_back(); // Pop last '/'.
- else if (result.empty())
- result = ".";
-
- return FileSpec(result, false, m_syntax);
+ return a == b;
}
//------------------------------------------------------------------
-// Dump the object to the supplied stream. If the object contains
-// a valid directory name, it will be displayed followed by a
-// directory delimiter, and the filename.
+// Dump the object to the supplied stream. If the object contains a valid
+// directory name, it will be displayed followed by a directory delimiter, and
+// the filename.
//------------------------------------------------------------------
void FileSpec::Dump(Stream *s) const {
if (s) {
std::string path{GetPath(true)};
s->PutCString(path);
- char path_separator = GetPreferredPathSeparator(m_syntax);
+ char path_separator = GetPreferredPathSeparator(m_style);
if (!m_filename && !path.empty() && path.back() != path_separator)
s->PutChar(path_separator);
}
@@ -557,8 +483,7 @@ bool FileSpec::ResolveExecutableLocation() {
return true;
else {
// If FindProgramByName found the file, it returns the directory +
- // filename in its return results.
- // We need to separate them.
+ // filename in its return results. We need to separate them.
FileSpec tmp_file(dir_ref.data(), false);
if (tmp_file.Exists()) {
m_directory = tmp_file.m_directory;
@@ -588,7 +513,7 @@ uint64_t FileSpec::GetByteSize() const {
return Size;
}
-FileSpec::PathSyntax FileSpec::GetPathSyntax() const { return m_syntax; }
+FileSpec::Style FileSpec::GetPathStyle() const { return m_style; }
uint32_t FileSpec::GetPermissions() const {
namespace fs = llvm::sys::fs;
@@ -620,9 +545,8 @@ ConstString &FileSpec::GetFilename() { return m_filename; }
const ConstString &FileSpec::GetFilename() const { return m_filename; }
//------------------------------------------------------------------
-// Extract the directory and path into a fixed buffer. This is
-// needed as the directory and path are stored in separate string
-// values.
+// Extract the directory and path into a fixed buffer. This is needed as the
+// directory and path are stored in separate string values.
//------------------------------------------------------------------
size_t FileSpec::GetPath(char *path, size_t path_max_len,
bool denormalize) const {
@@ -648,42 +572,30 @@ void FileSpec::GetPath(llvm::SmallVectorImpl<char> &path,
bool denormalize) const {
path.append(m_directory.GetStringRef().begin(),
m_directory.GetStringRef().end());
- if (m_directory && m_filename &&
- !IsPathSeparator(m_directory.GetStringRef().back(), m_syntax))
- path.insert(path.end(), GetPreferredPathSeparator(m_syntax));
+ // Since the path was normalized and all paths use '/' when stored in these
+ // objects, we don't need to look for the actual syntax specific path
+ // separator, we just look for and insert '/'.
+ if (m_directory && m_filename && m_directory.GetStringRef().back() != '/' &&
+ m_filename.GetStringRef().back() != '/')
+ path.insert(path.end(), '/');
path.append(m_filename.GetStringRef().begin(),
m_filename.GetStringRef().end());
- Normalize(path, m_syntax);
if (denormalize && !path.empty())
- Denormalize(path, m_syntax);
+ Denormalize(path, m_style);
}
ConstString FileSpec::GetFileNameExtension() const {
- if (m_filename) {
- const char *filename = m_filename.GetCString();
- const char *dot_pos = strrchr(filename, '.');
- if (dot_pos && dot_pos[1] != '\0')
- return ConstString(dot_pos + 1);
- }
- return ConstString();
+ return ConstString(
+ llvm::sys::path::extension(m_filename.GetStringRef(), m_style));
}
ConstString FileSpec::GetFileNameStrippingExtension() const {
- const char *filename = m_filename.GetCString();
- if (filename == NULL)
- return ConstString();
-
- const char *dot_pos = strrchr(filename, '.');
- if (dot_pos == NULL)
- return m_filename;
-
- return ConstString(filename, dot_pos - filename);
+ return ConstString(llvm::sys::path::stem(m_filename.GetStringRef(), m_style));
}
//------------------------------------------------------------------
-// Return the size in bytes that this object takes in memory. This
-// returns the size in bytes of this object, not any shared string
-// values it may refer to.
+// Return the size in bytes that this object takes in memory. This returns the
+// size in bytes of this object, not any shared string values it may refer to.
//------------------------------------------------------------------
size_t FileSpec::MemorySize() const {
return m_filename.MemorySize() + m_directory.MemorySize();
@@ -730,91 +642,28 @@ FileSpec::CopyByAppendingPathComponent(llvm::StringRef component) const {
}
FileSpec FileSpec::CopyByRemovingLastPathComponent() const {
- // CLEANUP: Use StringRef for string handling.
- const bool resolve = false;
- if (m_filename.IsEmpty() && m_directory.IsEmpty())
- return FileSpec("", resolve);
- if (m_directory.IsEmpty())
- return FileSpec("", resolve);
- if (m_filename.IsEmpty()) {
- const char *dir_cstr = m_directory.GetCString();
- const char *last_slash_ptr = ::strrchr(dir_cstr, '/');
-
- // check for obvious cases before doing the full thing
- if (!last_slash_ptr)
- return FileSpec("", resolve);
- if (last_slash_ptr == dir_cstr)
- return FileSpec("/", resolve);
-
- size_t last_slash_pos = last_slash_ptr - dir_cstr + 1;
- ConstString new_path(dir_cstr, last_slash_pos);
- return FileSpec(new_path.GetCString(), resolve);
- } else
- return FileSpec(m_directory.GetCString(), resolve);
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ if (llvm::sys::path::has_parent_path(current_path, m_style))
+ return FileSpec(llvm::sys::path::parent_path(current_path, m_style), false,
+ m_style);
+ return *this;
}
ConstString FileSpec::GetLastPathComponent() const {
- // CLEANUP: Use StringRef for string handling.
- if (m_filename)
- return m_filename;
- if (m_directory) {
- const char *dir_cstr = m_directory.GetCString();
- const char *last_slash_ptr = ::strrchr(dir_cstr, '/');
- if (last_slash_ptr == NULL)
- return m_directory;
- if (last_slash_ptr == dir_cstr) {
- if (last_slash_ptr[1] == 0)
- return ConstString(last_slash_ptr);
- else
- return ConstString(last_slash_ptr + 1);
- }
- if (last_slash_ptr[1] != 0)
- return ConstString(last_slash_ptr + 1);
- const char *penultimate_slash_ptr = last_slash_ptr;
- while (*penultimate_slash_ptr) {
- --penultimate_slash_ptr;
- if (penultimate_slash_ptr == dir_cstr)
- break;
- if (*penultimate_slash_ptr == '/')
- break;
- }
- ConstString result(penultimate_slash_ptr + 1,
- last_slash_ptr - penultimate_slash_ptr);
- return result;
- }
- return ConstString();
-}
-
-static std::string
-join_path_components(FileSpec::PathSyntax syntax,
- const std::vector<llvm::StringRef> components) {
- std::string result;
- for (size_t i = 0; i < components.size(); ++i) {
- if (components[i].empty())
- continue;
- result += components[i];
- if (i != components.size() - 1 &&
- !IsPathSeparator(components[i].back(), syntax))
- result += GetPreferredPathSeparator(syntax);
- }
-
- return result;
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ return ConstString(llvm::sys::path::filename(current_path, m_style));
}
void FileSpec::PrependPathComponent(llvm::StringRef component) {
- if (component.empty())
- return;
-
- const bool resolve = false;
- if (m_filename.IsEmpty() && m_directory.IsEmpty()) {
- SetFile(component, resolve);
- return;
- }
-
- std::string result =
- join_path_components(m_syntax, {component, m_directory.GetStringRef(),
- m_filename.GetStringRef()});
- SetFile(result, resolve, m_syntax);
+ llvm::SmallString<64> new_path(component);
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ llvm::sys::path::append(new_path,
+ llvm::sys::path::begin(current_path, m_style),
+ llvm::sys::path::end(current_path), m_style);
+ SetFile(new_path, false, m_style);
}
void FileSpec::PrependPathComponent(const FileSpec &new_path) {
@@ -822,53 +671,24 @@ void FileSpec::PrependPathComponent(const FileSpec &new_path) {
}
void FileSpec::AppendPathComponent(llvm::StringRef component) {
- if (component.empty())
- return;
-
- component = component.drop_while(
- [this](char c) { return IsPathSeparator(c, m_syntax); });
-
- std::string result =
- join_path_components(m_syntax, {m_directory.GetStringRef(),
- m_filename.GetStringRef(), component});
-
- SetFile(result, false, m_syntax);
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ llvm::sys::path::append(current_path, m_style, component);
+ SetFile(current_path, false, m_style);
}
void FileSpec::AppendPathComponent(const FileSpec &new_path) {
return AppendPathComponent(new_path.GetPath(false));
}
-void FileSpec::RemoveLastPathComponent() {
- // CLEANUP: Use StringRef for string handling.
-
- const bool resolve = false;
- if (m_filename.IsEmpty() && m_directory.IsEmpty()) {
- SetFile("", resolve);
- return;
- }
- if (m_directory.IsEmpty()) {
- SetFile("", resolve);
- return;
+bool FileSpec::RemoveLastPathComponent() {
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+ if (llvm::sys::path::has_parent_path(current_path, m_style)) {
+ SetFile(llvm::sys::path::parent_path(current_path, m_style), false);
+ return true;
}
- if (m_filename.IsEmpty()) {
- const char *dir_cstr = m_directory.GetCString();
- const char *last_slash_ptr = ::strrchr(dir_cstr, '/');
-
- // check for obvious cases before doing the full thing
- if (!last_slash_ptr) {
- SetFile("", resolve);
- return;
- }
- if (last_slash_ptr == dir_cstr) {
- SetFile("/", resolve);
- return;
- }
- size_t last_slash_pos = last_slash_ptr - dir_cstr + 1;
- ConstString new_path(dir_cstr, last_slash_pos);
- SetFile(new_path.GetCString(), resolve);
- } else
- SetFile(m_directory.GetCString(), resolve);
+ return false;
}
//------------------------------------------------------------------
/// Returns true if the filespec represents an implementation source
@@ -885,7 +705,7 @@ bool FileSpec::IsSourceImplementationFile() const {
return false;
static RegularExpression g_source_file_regex(llvm::StringRef(
- "^([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|["
+ "^.([cC]|[mM]|[mM][mM]|[cC][pP][pP]|[cC]\\+\\+|[cC][xX][xX]|[cC][cC]|["
"cC][pP]|[sS]|[aA][sS][mM]|[fF]|[fF]77|[fF]90|[fF]95|[fF]03|[fF][oO]["
"rR]|[fF][tT][nN]|[fF][pP][pP]|[aA][dD][aA]|[aA][dD][bB]|[aA][dD][sS])"
"$"));
@@ -893,34 +713,23 @@ bool FileSpec::IsSourceImplementationFile() const {
}
bool FileSpec::IsRelative() const {
- const char *dir = m_directory.GetCString();
- llvm::StringRef directory(dir ? dir : "");
+ return !IsAbsolute();
+}
- if (directory.size() > 0) {
- if (PathSyntaxIsPosix(m_syntax)) {
- // If the path doesn't start with '/' or '~', return true
- switch (directory[0]) {
- case '/':
- case '~':
- return false;
- default:
- return true;
- }
- } else {
- if (directory.size() >= 2 && directory[1] == ':')
- return false;
- if (directory[0] == '/')
- return false;
- return true;
- }
- } else if (m_filename) {
- // No directory, just a basename, return true
+bool FileSpec::IsAbsolute() const {
+ llvm::SmallString<64> current_path;
+ GetPath(current_path, false);
+
+ // Early return if the path is empty.
+ if (current_path.empty())
+ return false;
+
+ // We consider paths starting with ~ to be absolute.
+ if (current_path[0] == '~')
return true;
- }
- return false;
-}
-bool FileSpec::IsAbsolute() const { return !FileSpec::IsRelative(); }
+ return llvm::sys::path::is_absolute(current_path, m_style);
+}
void llvm::format_provider<FileSpec>::format(const FileSpec &F,
raw_ostream &Stream,
@@ -944,14 +753,13 @@ void llvm::format_provider<FileSpec>::format(const FileSpec &F,
// Style is either D or empty, either way we need to print the directory.
if (!dir.empty()) {
- // Directory is stored in normalized form, which might be different
- // than preferred form. In order to handle this, we need to cut off
- // the filename, then denormalize, then write the entire denorm'ed
- // directory.
+ // Directory is stored in normalized form, which might be different than
+ // preferred form. In order to handle this, we need to cut off the
+ // filename, then denormalize, then write the entire denorm'ed directory.
llvm::SmallString<64> denormalized_dir = dir;
- Denormalize(denormalized_dir, F.GetPathSyntax());
+ Denormalize(denormalized_dir, F.GetPathStyle());
Stream << denormalized_dir;
- Stream << GetPreferredPathSeparator(F.GetPathSyntax());
+ Stream << GetPreferredPathSeparator(F.GetPathStyle());
}
if (Style.equals_lower("D")) {
diff --git a/source/Utility/History.cpp b/source/Utility/History.cpp
deleted file mode 100644
index 10344b67c635..000000000000
--- a/source/Utility/History.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-//===-- History.cpp ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/History.h"
-
-// C Includes
-#include <inttypes.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Utility/Stream.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-void HistorySourceUInt::DumpHistoryEvent(Stream &strm, HistoryEvent event) {
- strm.Printf("%s %" PRIu64, m_name.c_str(), (uint64_t)((uintptr_t)event));
-}
diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp
index 9049f596ab9a..7d70034ccabd 100644
--- a/source/Utility/JSON.cpp
+++ b/source/Utility/JSON.cpp
@@ -449,8 +449,7 @@ int JSONParser::GetEscapedChar(bool &was_escaped) {
JSONValue::SP JSONParser::ParseJSONObject() {
// The "JSONParser::Token::ObjectStart" token should have already been
- // consumed
- // by the time this function is called
+ // consumed by the time this function is called
std::unique_ptr<JSONObject> dict_up(new JSONObject());
std::string value;
@@ -481,8 +480,7 @@ JSONValue::SP JSONParser::ParseJSONObject() {
JSONValue::SP JSONParser::ParseJSONArray() {
// The "JSONParser::Token::ObjectStart" token should have already been
- // consumed
- // by the time this function is called
+ // consumed by the time this function is called
std::unique_ptr<JSONArray> array_up(new JSONArray());
std::string value;
diff --git a/source/Utility/Log.cpp b/source/Utility/Log.cpp
index f247124f8d63..eb026fb04752 100644
--- a/source/Utility/Log.cpp
+++ b/source/Utility/Log.cpp
@@ -28,7 +28,7 @@
#include <utility> // for pair
#include <assert.h> // for assert
-#if defined(LLVM_ON_WIN32)
+#if defined(_WIN32)
#include <process.h> // for getpid
#else
#include <unistd.h>
@@ -121,9 +121,9 @@ void Log::Printf(const char *format, ...) {
}
//----------------------------------------------------------------------
-// All logging eventually boils down to this function call. If we have
-// a callback registered, then we call the logging callback. If we have
-// a valid file handle, we also log to the file.
+// All logging eventually boils down to this function call. If we have a
+// callback registered, then we call the logging callback. If we have a valid
+// file handle, we also log to the file.
//----------------------------------------------------------------------
void Log::VAPrintf(const char *format, va_list args) {
llvm::SmallString<64> FinalMessage;
@@ -156,8 +156,7 @@ void Log::VAError(const char *format, va_list args) {
}
//----------------------------------------------------------------------
-// Printing of warnings that are not fatal only if verbose mode is
-// enabled.
+// Printing of warnings that are not fatal only if verbose mode is enabled.
//----------------------------------------------------------------------
void Log::Verbose(const char *format, ...) {
if (!GetVerbose())
@@ -287,7 +286,11 @@ void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
if (options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) {
llvm::SmallString<32> thread_name;
llvm::get_thread_name(thread_name);
- OS << llvm::formatv("{0,-16} ", thread_name);
+
+ llvm::SmallString<12> format_str;
+ llvm::raw_svector_ostream format_os(format_str);
+ format_os << "{0,-" << llvm::alignTo<16>(thread_name.size()) << "} ";
+ OS << llvm::formatv(format_str.c_str(), thread_name);
}
if (options.Test(LLDB_LOG_OPTION_BACKTRACE))
@@ -302,8 +305,8 @@ void Log::WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file,
}
void Log::WriteMessage(const std::string &message) {
- // Make a copy of our stream shared pointer in case someone disables our
- // log while we are logging and releases the stream
+ // Make a copy of our stream shared pointer in case someone disables our log
+ // while we are logging and releases the stream
auto stream_sp = GetStream();
if (!stream_sp)
return;
diff --git a/source/Utility/PPC64_DWARF_Registers.h b/source/Utility/PPC64_DWARF_Registers.h
new file mode 100644
index 000000000000..7e3619e0da4d
--- /dev/null
+++ b/source/Utility/PPC64_DWARF_Registers.h
@@ -0,0 +1,127 @@
+//===-- PPC64_DWARF_Registers.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef utility_PPC64_DWARF_Registers_h_
+#define utility_PPC64_DWARF_Registers_h_
+
+#include "lldb/lldb-private.h"
+
+namespace ppc64_dwarf {
+
+enum {
+ dwarf_r0_ppc64 = 0,
+ dwarf_r1_ppc64,
+ dwarf_r2_ppc64,
+ dwarf_r3_ppc64,
+ dwarf_r4_ppc64,
+ dwarf_r5_ppc64,
+ dwarf_r6_ppc64,
+ dwarf_r7_ppc64,
+ dwarf_r8_ppc64,
+ dwarf_r9_ppc64,
+ dwarf_r10_ppc64,
+ dwarf_r11_ppc64,
+ dwarf_r12_ppc64,
+ dwarf_r13_ppc64,
+ dwarf_r14_ppc64,
+ dwarf_r15_ppc64,
+ dwarf_r16_ppc64,
+ dwarf_r17_ppc64,
+ dwarf_r18_ppc64,
+ dwarf_r19_ppc64,
+ dwarf_r20_ppc64,
+ dwarf_r21_ppc64,
+ dwarf_r22_ppc64,
+ dwarf_r23_ppc64,
+ dwarf_r24_ppc64,
+ dwarf_r25_ppc64,
+ dwarf_r26_ppc64,
+ dwarf_r27_ppc64,
+ dwarf_r28_ppc64,
+ dwarf_r29_ppc64,
+ dwarf_r30_ppc64,
+ dwarf_r31_ppc64,
+ dwarf_f0_ppc64,
+ dwarf_f1_ppc64,
+ dwarf_f2_ppc64,
+ dwarf_f3_ppc64,
+ dwarf_f4_ppc64,
+ dwarf_f5_ppc64,
+ dwarf_f6_ppc64,
+ dwarf_f7_ppc64,
+ dwarf_f8_ppc64,
+ dwarf_f9_ppc64,
+ dwarf_f10_ppc64,
+ dwarf_f11_ppc64,
+ dwarf_f12_ppc64,
+ dwarf_f13_ppc64,
+ dwarf_f14_ppc64,
+ dwarf_f15_ppc64,
+ dwarf_f16_ppc64,
+ dwarf_f17_ppc64,
+ dwarf_f18_ppc64,
+ dwarf_f19_ppc64,
+ dwarf_f20_ppc64,
+ dwarf_f21_ppc64,
+ dwarf_f22_ppc64,
+ dwarf_f23_ppc64,
+ dwarf_f24_ppc64,
+ dwarf_f25_ppc64,
+ dwarf_f26_ppc64,
+ dwarf_f27_ppc64,
+ dwarf_f28_ppc64,
+ dwarf_f29_ppc64,
+ dwarf_f30_ppc64,
+ dwarf_f31_ppc64,
+ dwarf_cr_ppc64 = 64,
+ dwarf_fpscr_ppc64,
+ dwarf_msr_ppc64,
+ dwarf_xer_ppc64 = 100,
+ dwarf_lr_ppc64 = 108,
+ dwarf_ctr_ppc64,
+ dwarf_vscr_ppc64,
+ dwarf_vrsave_ppc64 = 356,
+ dwarf_pc_ppc64,
+ dwarf_vr0_ppc64 = 1124,
+ dwarf_vr1_ppc64,
+ dwarf_vr2_ppc64,
+ dwarf_vr3_ppc64,
+ dwarf_vr4_ppc64,
+ dwarf_vr5_ppc64,
+ dwarf_vr6_ppc64,
+ dwarf_vr7_ppc64,
+ dwarf_vr8_ppc64,
+ dwarf_vr9_ppc64,
+ dwarf_vr10_ppc64,
+ dwarf_vr11_ppc64,
+ dwarf_vr12_ppc64,
+ dwarf_vr13_ppc64,
+ dwarf_vr14_ppc64,
+ dwarf_vr15_ppc64,
+ dwarf_vr16_ppc64,
+ dwarf_vr17_ppc64,
+ dwarf_vr18_ppc64,
+ dwarf_vr19_ppc64,
+ dwarf_vr20_ppc64,
+ dwarf_vr21_ppc64,
+ dwarf_vr22_ppc64,
+ dwarf_vr23_ppc64,
+ dwarf_vr24_ppc64,
+ dwarf_vr25_ppc64,
+ dwarf_vr26_ppc64,
+ dwarf_vr27_ppc64,
+ dwarf_vr28_ppc64,
+ dwarf_vr29_ppc64,
+ dwarf_vr30_ppc64,
+ dwarf_vr31_ppc64,
+};
+
+} // namespace ppc64_dwarf
+
+#endif // utility_PPC64_DWARF_Registers_h_
diff --git a/source/Utility/RegularExpression.cpp b/source/Utility/RegularExpression.cpp
index d58b315d0d1d..54f773365d99 100644
--- a/source/Utility/RegularExpression.cpp
+++ b/source/Utility/RegularExpression.cpp
@@ -14,9 +14,8 @@
#include <string>
//----------------------------------------------------------------------
-// Enable enhanced mode if it is available. This allows for things like
-// \d for digit, \s for space, and many more, but it isn't available
-// everywhere.
+// Enable enhanced mode if it is available. This allows for things like \d for
+// digit, \s for space, and many more, but it isn't available everywhere.
//----------------------------------------------------------------------
#if defined(REG_ENHANCED)
#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED)
@@ -31,8 +30,8 @@ RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() {
}
//----------------------------------------------------------------------
-// Constructor that compiles "re" using "flags" and stores the
-// resulting compiled regular expression into this object.
+// Constructor that compiles "re" using "flags" and stores the resulting
+// compiled regular expression into this object.
//----------------------------------------------------------------------
RegularExpression::RegularExpression(llvm::StringRef str)
: m_re(), m_comp_err(1), m_preg() {
@@ -55,17 +54,16 @@ operator=(const RegularExpression &rhs) {
//----------------------------------------------------------------------
// Destructor
//
-// Any previously compiled regular expression contained in this
-// object will be freed.
+// Any previously compiled regular expression contained in this object will be
+// freed.
//----------------------------------------------------------------------
RegularExpression::~RegularExpression() { Free(); }
//----------------------------------------------------------------------
-// Compile a regular expression using the supplied regular
-// expression text and flags. The compiled regular expression lives
-// in this object so that it can be readily used for regular
-// expression matches. Execute() can be called after the regular
-// expression is compiled. Any previously compiled regular
+// Compile a regular expression using the supplied regular expression text and
+// flags. The compiled regular expression lives in this object so that it can
+// be readily used for regular expression matches. Execute() can be called
+// after the regular expression is compiled. Any previously compiled regular
// expression contained in this object will be freed.
//
// RETURNS
@@ -75,20 +73,19 @@ RegularExpression::~RegularExpression() { Free(); }
bool RegularExpression::Compile(llvm::StringRef str) {
Free();
- // regcomp() on darwin does not recognize "" as a valid regular expression, so
- // we substitute it with an equivalent non-empty one.
+ // regcomp() on darwin does not recognize "" as a valid regular expression,
+ // so we substitute it with an equivalent non-empty one.
m_re = str.empty() ? "()" : str;
m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS);
return m_comp_err == 0;
}
//----------------------------------------------------------------------
-// Execute a regular expression match using the compiled regular
-// expression that is already in this object against the match
-// string "s". If any parens are used for regular expression
-// matches "match_count" should indicate the number of regmatch_t
-// values that are present in "match_ptr". The regular expression
-// will be executed using the "execute_flags".
+// Execute a regular expression match using the compiled regular expression
+// that is already in this object against the match string "s". If any parens
+// are used for regular expression matches "match_count" should indicate the
+// number of regmatch_t values that are present in "match_ptr". The regular
+// expression will be executed using the "execute_flags".
//---------------------------------------------------------------------
bool RegularExpression::Execute(llvm::StringRef str, Match *match) const {
int err = 1;
@@ -159,14 +156,12 @@ bool RegularExpression::Match::GetMatchSpanningIndices(
}
//----------------------------------------------------------------------
-// Returns true if the regular expression compiled and is ready
-// for execution.
+// Returns true if the regular expression compiled and is ready for execution.
//----------------------------------------------------------------------
bool RegularExpression::IsValid() const { return m_comp_err == 0; }
//----------------------------------------------------------------------
-// Returns the text that was used to compile the current regular
-// expression.
+// Returns the text that was used to compile the current regular expression.
//----------------------------------------------------------------------
llvm::StringRef RegularExpression::GetText() const { return m_re; }
diff --git a/source/Utility/SelectHelper.cpp b/source/Utility/SelectHelper.cpp
index 200b2ae42759..0f6a96309504 100644
--- a/source/Utility/SelectHelper.cpp
+++ b/source/Utility/SelectHelper.cpp
@@ -109,8 +109,8 @@ lldb_private::Status SelectHelper::Select() {
pair.second.PrepareForSelect();
const lldb::socket_t fd = pair.first;
#if !defined(__APPLE__) && !defined(_MSC_VER)
- lldbassert(fd < FD_SETSIZE);
- if (fd >= FD_SETSIZE) {
+ lldbassert(fd < static_cast<int>(FD_SETSIZE));
+ if (fd >= static_cast<int>(FD_SETSIZE)) {
error.SetErrorStringWithFormat("%i is too large for select()", fd);
return error;
}
@@ -236,8 +236,9 @@ lldb_private::Status SelectHelper::Select() {
error.SetErrorString("timed out");
return error;
} else {
- // One or more descriptors were set, update the FDInfo::select_is_set mask
- // so users can ask the SelectHelper class so clients can call one of:
+ // One or more descriptors were set, update the FDInfo::select_is_set
+ // mask so users can ask the SelectHelper class so clients can call one
+ // of:
for (auto &pair : m_fd_map) {
const int fd = pair.first;
diff --git a/source/Utility/SharingPtr.cpp b/source/Utility/SharingPtr.cpp
index cf32b21f24a6..bdaedfb9b049 100644
--- a/source/Utility/SharingPtr.cpp
+++ b/source/Utility/SharingPtr.cpp
@@ -11,8 +11,8 @@
#if defined(ENABLE_SP_LOGGING)
-// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments
-// and allow them to be queried using a pointer by a call to:
+// If ENABLE_SP_LOGGING is defined, then log all shared pointer assignments and
+// allow them to be queried using a pointer by a call to:
#include <assert.h>
#include <execinfo.h>
@@ -96,8 +96,8 @@ extern "C" void track_sp(void *sp_this, void *ptr, long use_count) {
namespace lldb {
void dump_sp_refs(void *ptr) {
- // Use a specially crafted call to "track_sp" which will
- // dump info on all live shared pointers that reference "ptr"
+ // Use a specially crafted call to "track_sp" which will dump info on all
+ // live shared pointers that reference "ptr"
track_sp(NULL, ptr, 0);
}
}
diff --git a/source/Utility/Status.cpp b/source/Utility/Status.cpp
index a6a889a71e54..f6dc228391b3 100644
--- a/source/Utility/Status.cpp
+++ b/source/Utility/Status.cpp
@@ -107,9 +107,9 @@ const Status &Status::operator=(const Status &rhs) {
Status::~Status() = default;
//----------------------------------------------------------------------
-// Get the error value as a NULL C string. The error string will be
-// fetched and cached on demand. The cached error string value will
-// remain until the error value is changed or cleared.
+// Get the error value as a NULL C string. The error string will be fetched and
+// cached on demand. The cached error string value will remain until the error
+// value is changed or cleared.
//----------------------------------------------------------------------
const char *Status::AsCString(const char *default_error_str) const {
if (Success())
@@ -161,13 +161,13 @@ Status::ValueType Status::GetError() const { return m_code; }
ErrorType Status::GetType() const { return m_type; }
//----------------------------------------------------------------------
-// Returns true if this object contains a value that describes an
-// error or otherwise non-success result.
+// Returns true if this object contains a value that describes an error or
+// otherwise non-success result.
//----------------------------------------------------------------------
bool Status::Fail() const { return m_code != 0; }
//----------------------------------------------------------------------
-// Set accesssor for the error value to "err" and the type to
+// Set accessor for the error value to "err" and the type to
// "eErrorTypeMachKernel"
//----------------------------------------------------------------------
void Status::SetMachError(uint32_t err) {
@@ -201,7 +201,7 @@ int Status::SetExpressionErrorWithFormat(lldb::ExpressionResults result,
}
//----------------------------------------------------------------------
-// Set accesssor for the error value and type.
+// Set accessor for the error value and type.
//----------------------------------------------------------------------
void Status::SetError(ValueType err, ErrorType type) {
m_code = err;
@@ -210,8 +210,7 @@ void Status::SetError(ValueType err, ErrorType type) {
}
//----------------------------------------------------------------------
-// Update the error value to be "errno" and update the type to
-// be "POSIX".
+// Update the error value to be "errno" and update the type to be "POSIX".
//----------------------------------------------------------------------
void Status::SetErrorToErrno() {
m_code = errno;
@@ -220,8 +219,8 @@ void Status::SetErrorToErrno() {
}
//----------------------------------------------------------------------
-// Update the error value to be LLDB_GENERIC_ERROR and update the type
-// to be "Generic".
+// Update the error value to be LLDB_GENERIC_ERROR and update the type to be
+// "Generic".
//----------------------------------------------------------------------
void Status::SetErrorToGenericError() {
m_code = LLDB_GENERIC_ERROR;
@@ -230,15 +229,15 @@ void Status::SetErrorToGenericError() {
}
//----------------------------------------------------------------------
-// Set accessor for the error string value for a specific error.
-// This allows any string to be supplied as an error explanation.
-// The error string value will remain until the error value is
-// cleared or a new error value/type is assigned.
+// Set accessor for the error string value for a specific error. This allows
+// any string to be supplied as an error explanation. The error string value
+// will remain until the error value is cleared or a new error value/type is
+// assigned.
//----------------------------------------------------------------------
void Status::SetErrorString(llvm::StringRef err_str) {
if (!err_str.empty()) {
- // If we have an error string, we should always at least have an error
- // set to a generic value.
+ // If we have an error string, we should always at least have an error set
+ // to a generic value.
if (Success())
SetErrorToGenericError();
}
@@ -266,8 +265,8 @@ int Status::SetErrorStringWithFormat(const char *format, ...) {
int Status::SetErrorStringWithVarArg(const char *format, va_list args) {
if (format != nullptr && format[0]) {
- // If we have an error string, we should always at least have
- // an error set to a generic value.
+ // If we have an error string, we should always at least have an error set
+ // to a generic value.
if (Success())
SetErrorToGenericError();
@@ -282,8 +281,8 @@ int Status::SetErrorStringWithVarArg(const char *format, va_list args) {
}
//----------------------------------------------------------------------
-// Returns true if the error code in this object is considered a
-// successful return value.
+// Returns true if the error code in this object is considered a successful
+// return value.
//----------------------------------------------------------------------
bool Status::Success() const { return m_code == 0; }
diff --git a/source/Utility/Stream.cpp b/source/Utility/Stream.cpp
index 04edc25b2b09..647a0c0beb5c 100644
--- a/source/Utility/Stream.cpp
+++ b/source/Utility/Stream.cpp
@@ -41,14 +41,12 @@ ByteOrder Stream::SetByteOrder(ByteOrder byte_order) {
}
//------------------------------------------------------------------
-// Put an offset "uval" out to the stream using the printf format
-// in "format".
+// Put an offset "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
//------------------------------------------------------------------
-// Put an SLEB128 "uval" out to the stream using the printf format
-// in "format".
+// Put an SLEB128 "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
size_t Stream::PutSLEB128(int64_t sval) {
size_t bytes_written = 0;
@@ -73,8 +71,7 @@ size_t Stream::PutSLEB128(int64_t sval) {
}
//------------------------------------------------------------------
-// Put an ULEB128 "uval" out to the stream using the printf format
-// in "format".
+// Put an ULEB128 "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
size_t Stream::PutULEB128(uint64_t uval) {
size_t bytes_written = 0;
@@ -109,16 +106,16 @@ size_t Stream::PutCString(llvm::StringRef str) {
}
//------------------------------------------------------------------
-// Print a double quoted NULL terminated C string to the stream
-// using the printf format in "format".
+// Print a double quoted NULL terminated C string to the stream using the
+// printf format in "format".
//------------------------------------------------------------------
void Stream::QuotedCString(const char *cstr, const char *format) {
Printf(format, cstr);
}
//------------------------------------------------------------------
-// Put an address "addr" out to the stream with optional prefix
-// and suffix strings.
+// Put an address "addr" out to the stream with optional prefix and suffix
+// strings.
//------------------------------------------------------------------
void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
const char *suffix) {
@@ -132,8 +129,8 @@ void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
}
//------------------------------------------------------------------
-// Put an address range out to the stream with optional prefix
-// and suffix strings.
+// Put an address range out to the stream with optional prefix and suffix
+// strings.
//------------------------------------------------------------------
void Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr,
uint32_t addr_size, const char *prefix,
@@ -179,8 +176,8 @@ size_t Stream::PrintfVarArg(const char *format, va_list args) {
size_t Stream::EOL() { return PutChar('\n'); }
//------------------------------------------------------------------
-// Indent the current line using the current indentation level and
-// print an optional string following the indentation spaces.
+// Indent the current line using the current indentation level and print an
+// optional string following the indentation spaces.
//------------------------------------------------------------------
size_t Stream::Indent(const char *s) {
return Printf("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : "");
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index cf5c7e227448..7528350cf759 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -74,9 +74,8 @@ char StringExtractor::GetChar(char fail_value) {
}
//----------------------------------------------------------------------
-// If a pair of valid hex digits exist at the head of the
-// StringExtractor they are decoded into an unsigned byte and returned
-// by this function
+// If a pair of valid hex digits exist at the head of the StringExtractor they
+// are decoded into an unsigned byte and returned by this function
//
// If there is not a pair of valid hex digits at the head of the
// StringExtractor, it is left unchanged and -1 is returned
@@ -96,12 +95,12 @@ int StringExtractor::DecodeHexU8() {
}
//----------------------------------------------------------------------
-// Extract an unsigned character from two hex ASCII chars in the packet
-// string, or return fail_value on failure
+// Extract an unsigned character from two hex ASCII chars in the packet string,
+// or return fail_value on failure
//----------------------------------------------------------------------
uint8_t StringExtractor::GetHexU8(uint8_t fail_value, bool set_eof_on_fail) {
- // On success, fail_value will be overwritten with the next
- // character in the stream
+ // On success, fail_value will be overwritten with the next character in the
+ // stream
GetHexU8Ex(fail_value, set_eof_on_fail);
return fail_value;
}
@@ -307,8 +306,8 @@ size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
}
//----------------------------------------------------------------------
-// Decodes all valid hex encoded bytes at the head of the
-// StringExtractor, limited by dst_len.
+// Decodes all valid hex encoded bytes at the head of the StringExtractor,
+// limited by dst_len.
//
// Returns the number of bytes successfully decoded
//----------------------------------------------------------------------
@@ -390,9 +389,9 @@ size_t StringExtractor::GetHexByteStringTerminatedBy(std::string &str,
bool StringExtractor::GetNameColonValue(llvm::StringRef &name,
llvm::StringRef &value) {
- // Read something in the form of NNNN:VVVV; where NNNN is any character
- // that is not a colon, followed by a ':' character, then a value (one or
- // more ';' chars), followed by a ';'
+ // Read something in the form of NNNN:VVVV; where NNNN is any character that
+ // is not a colon, followed by a ':' character, then a value (one or more ';'
+ // chars), followed by a ';'
if (m_index >= m_packet.size())
return fail();
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 818347a42a2c..3cae06df3b1e 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
#include <ctype.h> // for isxdigit
#include <string.h>
@@ -482,10 +482,9 @@ lldb_private::Status StringExtractorGDBRemote::GetStatus() {
size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
// Just get the data bytes in the string as
- // GDBRemoteCommunication::CheckForPacket()
- // already removes any 0x7d escaped characters. If any 0x7d characters are
- // left in
- // the packet, then they are supposed to be there...
+ // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
+ // characters. If any 0x7d characters are left in the packet, then they are
+ // supposed to be there...
str.clear();
const size_t bytes_left = GetBytesLeft();
if (bytes_left > 0) {
@@ -526,9 +525,9 @@ static bool JSONResponseValidator(void *,
case StringExtractorGDBRemote::eResponse:
// JSON that is returned in from JSON query packets is currently always
- // either a dictionary which starts with a '{', or an array which
- // starts with a '['. This is a quick validator to just make sure the
- // response could be valid JSON without having to validate all of the
+ // either a dictionary which starts with a '{', or an array which starts
+ // with a '['. This is a quick validator to just make sure the response
+ // could be valid JSON without having to validate all of the
// JSON content.
switch (response.GetStringRef()[0]) {
case '{':
diff --git a/source/Utility/StringExtractorGDBRemote.h b/source/Utility/StringExtractorGDBRemote.h
deleted file mode 100644
index f4ed642a706e..000000000000
--- a/source/Utility/StringExtractorGDBRemote.h
+++ /dev/null
@@ -1,204 +0,0 @@
-//===-- StringExtractorGDBRemote.h ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_StringExtractorGDBRemote_h_
-#define utility_StringExtractorGDBRemote_h_
-
-#include "lldb/Utility/Status.h"
-#include "lldb/Utility/StringExtractor.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
-
-#include <string>
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint8_t
-
-class StringExtractorGDBRemote : public StringExtractor {
-public:
- typedef bool (*ResponseValidatorCallback)(
- void *baton, const StringExtractorGDBRemote &response);
-
- StringExtractorGDBRemote() : StringExtractor(), m_validator(nullptr) {}
-
- StringExtractorGDBRemote(llvm::StringRef str)
- : StringExtractor(str), m_validator(nullptr) {}
-
- StringExtractorGDBRemote(const char *cstr)
- : StringExtractor(cstr), m_validator(nullptr) {}
-
- StringExtractorGDBRemote(const StringExtractorGDBRemote &rhs)
- : StringExtractor(rhs), m_validator(rhs.m_validator) {}
-
- virtual ~StringExtractorGDBRemote() {}
-
- bool ValidateResponse() const;
-
- void CopyResponseValidator(const StringExtractorGDBRemote &rhs);
-
- void SetResponseValidator(ResponseValidatorCallback callback, void *baton);
-
- void SetResponseValidatorToOKErrorNotSupported();
-
- void SetResponseValidatorToASCIIHexBytes();
-
- void SetResponseValidatorToJSON();
-
- enum ServerPacketType {
- eServerPacketType_nack = 0,
- eServerPacketType_ack,
- eServerPacketType_invalid,
- eServerPacketType_unimplemented,
- eServerPacketType_interrupt, // CTRL+c packet or "\x03"
- eServerPacketType_A, // Program arguments packet
- eServerPacketType_qfProcessInfo,
- eServerPacketType_qsProcessInfo,
- eServerPacketType_qC,
- eServerPacketType_qEcho,
- eServerPacketType_qGroupName,
- eServerPacketType_qHostInfo,
- eServerPacketType_qLaunchGDBServer,
- eServerPacketType_qQueryGDBServer,
- eServerPacketType_qKillSpawnedProcess,
- eServerPacketType_qLaunchSuccess,
- eServerPacketType_qModuleInfo,
- eServerPacketType_qProcessInfoPID,
- eServerPacketType_qSpeedTest,
- eServerPacketType_qUserName,
- eServerPacketType_qGetWorkingDir,
- eServerPacketType_qFileLoadAddress,
- eServerPacketType_QEnvironment,
- eServerPacketType_QEnableErrorStrings,
- eServerPacketType_QLaunchArch,
- eServerPacketType_QSetDisableASLR,
- eServerPacketType_QSetDetachOnError,
- eServerPacketType_QSetSTDIN,
- eServerPacketType_QSetSTDOUT,
- eServerPacketType_QSetSTDERR,
- eServerPacketType_QSetWorkingDir,
- eServerPacketType_QStartNoAckMode,
- eServerPacketType_qPlatform_shell,
- eServerPacketType_qPlatform_mkdir,
- eServerPacketType_qPlatform_chmod,
- eServerPacketType_vFile_open,
- eServerPacketType_vFile_close,
- eServerPacketType_vFile_pread,
- eServerPacketType_vFile_pwrite,
- eServerPacketType_vFile_size,
- eServerPacketType_vFile_mode,
- eServerPacketType_vFile_exists,
- eServerPacketType_vFile_md5,
- eServerPacketType_vFile_stat,
- eServerPacketType_vFile_symlink,
- eServerPacketType_vFile_unlink,
- // debug server packages
- eServerPacketType_QEnvironmentHexEncoded,
- eServerPacketType_QListThreadsInStopReply,
- eServerPacketType_QPassSignals,
- eServerPacketType_QRestoreRegisterState,
- eServerPacketType_QSaveRegisterState,
- eServerPacketType_QSetLogging,
- eServerPacketType_QSetMaxPacketSize,
- eServerPacketType_QSetMaxPayloadSize,
- eServerPacketType_QSetEnableAsyncProfiling,
- eServerPacketType_QSyncThreadState,
- eServerPacketType_QThreadSuffixSupported,
-
- eServerPacketType_jThreadsInfo,
- eServerPacketType_qsThreadInfo,
- eServerPacketType_qfThreadInfo,
- eServerPacketType_qGetPid,
- eServerPacketType_qGetProfileData,
- eServerPacketType_qGDBServerVersion,
- eServerPacketType_qMemoryRegionInfo,
- eServerPacketType_qMemoryRegionInfoSupported,
- eServerPacketType_qProcessInfo,
- eServerPacketType_qRcmd,
- eServerPacketType_qRegisterInfo,
- eServerPacketType_qShlibInfoAddr,
- eServerPacketType_qStepPacketSupported,
- eServerPacketType_qSupported,
- eServerPacketType_qSyncThreadStateSupported,
- eServerPacketType_qThreadExtraInfo,
- eServerPacketType_qThreadStopInfo,
- eServerPacketType_qVAttachOrWaitSupported,
- eServerPacketType_qWatchpointSupportInfo,
- eServerPacketType_qWatchpointSupportInfoSupported,
- eServerPacketType_qXfer_auxv_read,
-
- eServerPacketType_jSignalsInfo,
- eServerPacketType_jModulesInfo,
-
- eServerPacketType_vAttach,
- eServerPacketType_vAttachWait,
- eServerPacketType_vAttachOrWait,
- eServerPacketType_vAttachName,
- eServerPacketType_vCont,
- eServerPacketType_vCont_actions, // vCont?
-
- eServerPacketType_stop_reason, // '?'
-
- eServerPacketType_c,
- eServerPacketType_C,
- eServerPacketType_D,
- eServerPacketType_g,
- eServerPacketType_G,
- eServerPacketType_H,
- eServerPacketType_I, // stdin notification
- eServerPacketType_k,
- eServerPacketType_m,
- eServerPacketType_M,
- eServerPacketType_p,
- eServerPacketType_P,
- eServerPacketType_s,
- eServerPacketType_S,
- eServerPacketType_T,
- eServerPacketType_x,
- eServerPacketType_X,
- eServerPacketType_Z,
- eServerPacketType_z,
-
- eServerPacketType__M,
- eServerPacketType__m,
- eServerPacketType_notify, // '%' notification
-
- eServerPacketType_jTraceStart,
- eServerPacketType_jTraceBufferRead,
- eServerPacketType_jTraceMetaRead,
- eServerPacketType_jTraceStop,
- eServerPacketType_jTraceConfigRead,
- };
-
- ServerPacketType GetServerPacketType() const;
-
- enum ResponseType { eUnsupported = 0, eAck, eNack, eError, eOK, eResponse };
-
- ResponseType GetResponseType() const;
-
- bool IsOKResponse() const;
-
- bool IsUnsupportedResponse() const;
-
- bool IsNormalResponse() const;
-
- bool IsErrorResponse() const;
-
- // Returns zero if the packet isn't a EXX packet where XX are two hex
- // digits. Otherwise the error encoded in XX is returned.
- uint8_t GetError();
-
- lldb_private::Status GetStatus();
-
- size_t GetEscapedBinaryData(std::string &str);
-
-protected:
- ResponseValidatorCallback m_validator;
- void *m_validator_baton;
-};
-
-#endif // utility_StringExtractorGDBRemote_h_
diff --git a/source/Utility/StructuredData.cpp b/source/Utility/StructuredData.cpp
index 492fc585ad07..55f003f245bf 100644
--- a/source/Utility/StructuredData.cpp
+++ b/source/Utility/StructuredData.cpp
@@ -85,8 +85,7 @@ static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) {
static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) {
// The "JSONParser::Token::ObjectStart" token should have already been
- // consumed
- // by the time this function is called
+ // consumed by the time this function is called
auto array_up = llvm::make_unique<StructuredData::Array>();
std::string value;
@@ -162,8 +161,8 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
std::string key = match.first.str();
ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
if (value.get()) {
- // Do we have additional words to descend? If not, return the
- // value we're at right now.
+ // Do we have additional words to descend? If not, return the value
+ // we're at right now.
if (match.second.empty()) {
return value;
} else {
diff --git a/source/Utility/TildeExpressionResolver.cpp b/source/Utility/TildeExpressionResolver.cpp
index 64a771118d6e..ae947059d8b9 100644
--- a/source/Utility/TildeExpressionResolver.cpp
+++ b/source/Utility/TildeExpressionResolver.cpp
@@ -14,12 +14,11 @@
#include "llvm/ADT/STLExtras.h" // for any_of
#include "llvm/ADT/SmallVector.h" // for SmallVectorImpl
-#include "llvm/Config/llvm-config.h" // for LLVM_ON_WIN32
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h" // for fs
-#if !defined(LLVM_ON_WIN32)
+#if !defined(_WIN32)
#include <pwd.h>
#endif
@@ -49,7 +48,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr,
assert(Expr.empty() || Expr[0] == '~');
Output.clear();
-#if defined(LLVM_ON_WIN32) || defined(__ANDROID__)
+#if defined(_WIN32) || defined(__ANDROID__)
return false;
#else
if (Expr.empty())
diff --git a/source/Utility/UUID.cpp b/source/Utility/UUID.cpp
index 98d4c30cc7f1..623ad69ddc76 100644
--- a/source/Utility/UUID.cpp
+++ b/source/Utility/UUID.cpp
@@ -13,62 +13,44 @@
// Project includes
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Format.h"
// C Includes
#include <ctype.h>
#include <stdio.h>
#include <string.h>
-namespace lldb_private {
-
-UUID::UUID() { Clear(); }
-
-UUID::UUID(const UUID &rhs) {
- SetBytes(rhs.m_uuid, rhs.m_num_uuid_bytes);
-}
-
-UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) {
- SetBytes(uuid_bytes, num_uuid_bytes);
-}
-
-const UUID &UUID::operator=(const UUID &rhs) {
- if (this != &rhs) {
- m_num_uuid_bytes = rhs.m_num_uuid_bytes;
- ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid));
+using namespace lldb_private;
+
+// Whether to put a separator after count uuid bytes.
+// For the first 16 bytes we follow the traditional UUID format. After that, we
+// simply put a dash after every 6 bytes.
+static inline bool separate(size_t count) {
+ if (count >= 10)
+ return (count - 10) % 6 == 0;
+
+ switch (count) {
+ case 4:
+ case 6:
+ case 8:
+ return true;
+ default:
+ return false;
}
- return *this;
}
-UUID::~UUID() {}
-
-void UUID::Clear() {
- m_num_uuid_bytes = 16;
- ::memset(m_uuid, 0, sizeof(m_uuid));
-}
+std::string UUID::GetAsString(llvm::StringRef separator) const {
+ std::string result;
+ llvm::raw_string_ostream os(result);
-const void *UUID::GetBytes() const { return m_uuid; }
+ for (auto B : llvm::enumerate(GetBytes())) {
+ if (separate(B.index()))
+ os << separator;
-std::string UUID::GetAsString(const char *separator) const {
- std::string result;
- char buf[256];
- if (!separator)
- separator = "-";
- const uint8_t *u = (const uint8_t *)GetBytes();
- if (sizeof(buf) >
- (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2."
- "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%"
- "2.2X%2.2X%2.2X",
- u[0], u[1], u[2], u[3], separator, u[4], u[5], separator,
- u[6], u[7], separator, u[8], u[9], separator, u[10],
- u[11], u[12], u[13], u[14], u[15])) {
- result.append(buf);
- if (m_num_uuid_bytes == 20) {
- if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf),
- "%s%2.2X%2.2X%2.2X%2.2X", separator,
- u[16], u[17], u[18], u[19]))
- result.append(buf);
- }
+ os << llvm::format_hex_no_prefix(B.value(), 2, true);
}
+ os.flush();
+
return result;
}
@@ -76,40 +58,6 @@ void UUID::Dump(Stream *s) const {
s->PutCString(GetAsString().c_str());
}
-bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) {
- if (uuid_bytes) {
- switch (num_uuid_bytes) {
- case 20:
- m_num_uuid_bytes = 20;
- break;
- case 16:
- m_num_uuid_bytes = 16;
- m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0;
- break;
- default:
- // Unsupported UUID byte size
- m_num_uuid_bytes = 0;
- break;
- }
-
- if (m_num_uuid_bytes > 0) {
- ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes);
- return true;
- }
- }
- ::memset(m_uuid, 0, sizeof(m_uuid));
- return false;
-}
-
-size_t UUID::GetByteSize() const { return m_num_uuid_bytes; }
-
-bool UUID::IsValid() const {
- return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] ||
- m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] ||
- m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] ||
- m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19];
-}
-
static inline int xdigit_to_int(char ch) {
ch = tolower(ch);
if (ch >= 'a' && ch <= 'f')
@@ -117,25 +65,24 @@ static inline int xdigit_to_int(char ch) {
return ch - '0';
}
-llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
- ValueType &uuid_bytes,
- uint32_t &bytes_decoded,
- uint32_t num_uuid_bytes) {
- ::memset(uuid_bytes, 0, sizeof(uuid_bytes));
- size_t uuid_byte_idx = 0;
+llvm::StringRef
+UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
+ llvm::SmallVectorImpl<uint8_t> &uuid_bytes,
+ uint32_t num_uuid_bytes) {
+ uuid_bytes.clear();
while (!p.empty()) {
if (isxdigit(p[0]) && isxdigit(p[1])) {
int hi_nibble = xdigit_to_int(p[0]);
int lo_nibble = xdigit_to_int(p[1]);
// Translate the two hex nibble characters into a byte
- uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble;
+ uuid_bytes.push_back((hi_nibble << 4) + lo_nibble);
// Skip both hex digits
p = p.drop_front(2);
- // Increment the byte that we are decoding within the UUID value
- // and break out if we are done
- if (++uuid_byte_idx == num_uuid_bytes)
+ // Increment the byte that we are decoding within the UUID value and
+ // break out if we are done
+ if (uuid_bytes.size() == num_uuid_bytes)
break;
} else if (p.front() == '-') {
// Skip dashes
@@ -145,11 +92,6 @@ llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p,
break;
}
}
-
- // Clear trailing bytes to 0.
- for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++)
- uuid_bytes[i] = 0;
- bytes_decoded = uuid_byte_idx;
return p;
}
@@ -159,57 +101,17 @@ size_t UUID::SetFromStringRef(llvm::StringRef str, uint32_t num_uuid_bytes) {
// Skip leading whitespace characters
p = p.ltrim();
- uint32_t bytes_decoded = 0;
+ llvm::SmallVector<uint8_t, 20> bytes;
llvm::StringRef rest =
- UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes);
+ UUID::DecodeUUIDBytesFromString(p, bytes, num_uuid_bytes);
// If we successfully decoded a UUID, return the amount of characters that
// were consumed
- if (bytes_decoded == num_uuid_bytes) {
- m_num_uuid_bytes = num_uuid_bytes;
+ if (bytes.size() == num_uuid_bytes) {
+ *this = fromData(bytes);
return str.size() - rest.size();
}
// Else return zero to indicate we were not able to parse a UUID value
return 0;
}
-
-size_t UUID::SetFromCString(const char *cstr, uint32_t num_uuid_bytes) {
- if (cstr == NULL)
- return 0;
-
- return SetFromStringRef(cstr, num_uuid_bytes);
-}
-}
-
-bool lldb_private::operator==(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return ::memcmp(lhs.GetBytes(), rhs.GetBytes(),
- sizeof(lldb_private::UUID::ValueType)) == 0;
-}
-
-bool lldb_private::operator!=(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return !(lhs == rhs);
-}
-
-bool lldb_private::operator<(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return ::memcmp(lhs.GetBytes(), rhs.GetBytes(),
- sizeof(lldb_private::UUID::ValueType)) < 0;
-}
-
-bool lldb_private::operator<=(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return !(lhs > rhs);
-}
-
-bool lldb_private::operator>(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return rhs < lhs;
-}
-
-bool lldb_private::operator>=(const lldb_private::UUID &lhs,
- const lldb_private::UUID &rhs) {
- return !(lhs < rhs);
-}
diff --git a/source/Utility/VASprintf.cpp b/source/Utility/VASprintf.cpp
index e950fb75cfa0..900d9754a9b4 100644
--- a/source/Utility/VASprintf.cpp
+++ b/source/Utility/VASprintf.cpp
@@ -36,8 +36,8 @@ bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
}
if (size_t(length) >= buf.size()) {
- // The error formatted string didn't fit into our buffer, resize it
- // to the exact needed size, and retry
+ // The error formatted string didn't fit into our buffer, resize it to the
+ // exact needed size, and retry
buf.resize(length + 1);
length = ::vsnprintf(buf.data(), buf.size(), fmt, copy_args);
if (length < 0) {