forked from OSchip/llvm-project
Add the new Args / entry-access API.
The long-term goal here is to get rid of the functions GetArgumentAtIndex() and GetQuoteCharAtIndex(), instead replacing them with operator based access and range-based for enumeration. There are a lot of callsites, though, so the changes will be done incrementally, starting with this one. Differential Revision: https://reviews.llvm.org/D26883 llvm-svn: 287597
This commit is contained in:
parent
c2cd4e004c
commit
1c55c9b5bf
|
@ -150,9 +150,14 @@ public:
|
|||
const char *GetArgumentAtIndex(size_t idx) const;
|
||||
|
||||
llvm::ArrayRef<ArgEntry> entries() const { return m_entries; }
|
||||
|
||||
char GetArgumentQuoteCharAtIndex(size_t idx) const;
|
||||
|
||||
auto begin() const { return m_entries.begin(); }
|
||||
auto end() const { return m_entries.end(); }
|
||||
|
||||
size_t size() const { return GetArgumentCount(); }
|
||||
const ArgEntry &operator[](size_t n) const { return m_entries[n]; }
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Gets the argument vector.
|
||||
///
|
||||
|
|
|
@ -122,13 +122,12 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
|
|||
llvm::StringRef range_from;
|
||||
llvm::StringRef range_to;
|
||||
llvm::StringRef current_arg;
|
||||
const size_t num_old_args = old_args.GetArgumentCount();
|
||||
std::set<std::string> names_found;
|
||||
|
||||
for (size_t i = 0; i < num_old_args; ++i) {
|
||||
for (size_t i = 0; i < old_args.size(); ++i) {
|
||||
bool is_range = false;
|
||||
|
||||
current_arg = old_args.GetArgumentAtIndex(i);
|
||||
current_arg = old_args[i].ref;
|
||||
if (!allow_locations && current_arg.contains('.')) {
|
||||
result.AppendErrorWithFormat(
|
||||
"Breakpoint locations not allowed, saw location: %s.",
|
||||
|
@ -152,19 +151,17 @@ void BreakpointIDList::FindAndReplaceIDRanges(Args &old_args, Target *target,
|
|||
return;
|
||||
} else
|
||||
names_found.insert(current_arg);
|
||||
} else if ((i + 2 < num_old_args) &&
|
||||
BreakpointID::IsRangeIdentifier(
|
||||
old_args.GetArgumentAtIndex(i + 1)) &&
|
||||
} else if ((i + 2 < old_args.size()) &&
|
||||
BreakpointID::IsRangeIdentifier(old_args[i + 1].ref) &&
|
||||
BreakpointID::IsValidIDExpression(current_arg) &&
|
||||
BreakpointID::IsValidIDExpression(
|
||||
old_args.GetArgumentAtIndex(i + 2))) {
|
||||
BreakpointID::IsValidIDExpression(old_args[i + 2].ref)) {
|
||||
range_from = current_arg;
|
||||
range_to = old_args.GetArgumentAtIndex(i + 2);
|
||||
range_to = old_args[i + 2].ref;
|
||||
is_range = true;
|
||||
i = i + 2;
|
||||
} else {
|
||||
// See if user has specified id.*
|
||||
llvm::StringRef tmp_str = old_args.GetArgumentAtIndex(i);
|
||||
llvm::StringRef tmp_str = old_args[i].ref;
|
||||
size_t pos = tmp_str.find('.');
|
||||
if (pos != llvm::StringRef::npos) {
|
||||
llvm::StringRef bp_id_str = tmp_str.substr(0, pos);
|
||||
|
|
|
@ -1476,12 +1476,12 @@ public:
|
|||
int match_start_point, int max_return_elements,
|
||||
bool &word_complete,
|
||||
StringList &matches) override {
|
||||
std::string completion_str(input.GetArgumentAtIndex(cursor_index));
|
||||
completion_str.erase(cursor_char_position);
|
||||
llvm::StringRef completion_str = input[cursor_index].ref;
|
||||
completion_str = completion_str.take_front(cursor_char_position);
|
||||
|
||||
CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||
GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
|
||||
completion_str.c_str(), match_start_point, max_return_elements, nullptr,
|
||||
completion_str, match_start_point, max_return_elements, nullptr,
|
||||
word_complete, matches);
|
||||
return matches.GetSize();
|
||||
}
|
||||
|
|
|
@ -473,12 +473,12 @@ public:
|
|||
bool &word_complete,
|
||||
StringList &matches) override {
|
||||
// Arguments are the standard source file completer.
|
||||
std::string completion_str(input.GetArgumentAtIndex(cursor_index));
|
||||
completion_str.erase(cursor_char_position);
|
||||
auto completion_str = input[cursor_index].ref;
|
||||
completion_str = completion_str.take_front(cursor_char_position);
|
||||
|
||||
CommandCompletions::InvokeCommonCompletionCallbacks(
|
||||
GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
|
||||
completion_str.c_str(), match_start_point, max_return_elements, nullptr,
|
||||
completion_str, match_start_point, max_return_elements, nullptr,
|
||||
word_complete, matches);
|
||||
return matches.GetSize();
|
||||
}
|
||||
|
|
|
@ -1558,9 +1558,8 @@ protected:
|
|||
int num_signals_set = 0;
|
||||
|
||||
if (num_args > 0) {
|
||||
for (size_t i = 0; i < num_args; ++i) {
|
||||
int32_t signo = signals_sp->GetSignalNumberFromName(
|
||||
signal_args.GetArgumentAtIndex(i));
|
||||
for (const auto &arg : signal_args) {
|
||||
int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
|
||||
if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
|
||||
// Casting the actions as bools here should be okay, because
|
||||
// VerifyCommandOptionValue guarantees
|
||||
|
@ -1576,7 +1575,7 @@ protected:
|
|||
++num_signals_set;
|
||||
} else {
|
||||
result.AppendErrorWithFormat("Invalid signal name '%s'\n",
|
||||
signal_args.GetArgumentAtIndex(i));
|
||||
arg.c_str());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -293,15 +293,10 @@ protected:
|
|||
bool DoExecute(Args &args, CommandReturnObject &result) override {
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
|
||||
const size_t argc = args.GetArgumentCount();
|
||||
if (!args.empty()) {
|
||||
// TODO: Convert this to StringRef based enumeration. Requires converting
|
||||
// DumpPropertyValue first.
|
||||
for (size_t i = 0; i < argc; ++i) {
|
||||
const char *property_path = args.GetArgumentAtIndex(i);
|
||||
|
||||
for (const auto &arg : args) {
|
||||
Error error(m_interpreter.GetDebugger().DumpPropertyValue(
|
||||
&m_exe_ctx, result.GetOutputStream(), property_path,
|
||||
&m_exe_ctx, result.GetOutputStream(), arg.ref,
|
||||
OptionValue::eDumpGroupValue));
|
||||
if (error.Success()) {
|
||||
result.GetOutputStream().EOL();
|
||||
|
|
|
@ -1859,9 +1859,8 @@ int CommandInterpreter::HandleCompletion(
|
|||
// put an empty string in element 0.
|
||||
std::string command_partial_str;
|
||||
if (cursor_index >= 0)
|
||||
command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index),
|
||||
parsed_line.GetArgumentAtIndex(cursor_index) +
|
||||
cursor_char_position);
|
||||
command_partial_str =
|
||||
parsed_line[cursor_index].ref.take_front(cursor_char_position);
|
||||
|
||||
std::string common_prefix;
|
||||
matches.LongestCommonPrefix(common_prefix);
|
||||
|
@ -1872,7 +1871,7 @@ int CommandInterpreter::HandleCompletion(
|
|||
// Only do this if the completer told us this was a complete word,
|
||||
// however...
|
||||
if (num_command_matches == 1 && word_complete) {
|
||||
char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index);
|
||||
char quote_char = parsed_line[cursor_index].quote;
|
||||
common_prefix =
|
||||
Args::EscapeLLDBCommandArgument(common_prefix, quote_char);
|
||||
if (quote_char != '\0')
|
||||
|
|
|
@ -101,73 +101,74 @@ Error OptionValueDictionary::SetArgs(const Args &args, VarSetOperationType op) {
|
|||
case eVarSetOperationAppend:
|
||||
case eVarSetOperationReplace:
|
||||
case eVarSetOperationAssign:
|
||||
if (argc > 0) {
|
||||
for (size_t i = 0; i < argc; ++i) {
|
||||
llvm::StringRef key_and_value(args.GetArgumentAtIndex(i));
|
||||
if (!key_and_value.empty()) {
|
||||
if (key_and_value.find('=') == llvm::StringRef::npos) {
|
||||
error.SetErrorString(
|
||||
"assign operation takes one or more key=value arguments");
|
||||
return error;
|
||||
}
|
||||
|
||||
std::pair<llvm::StringRef, llvm::StringRef> kvp(
|
||||
key_and_value.split('='));
|
||||
llvm::StringRef key = kvp.first;
|
||||
bool key_valid = false;
|
||||
if (!key.empty()) {
|
||||
if (key.front() == '[') {
|
||||
// Key name starts with '[', so the key value must be in single or
|
||||
// double quotes like:
|
||||
// ['<key>']
|
||||
// ["<key>"]
|
||||
if ((key.size() > 2) && (key.back() == ']')) {
|
||||
// Strip leading '[' and trailing ']'
|
||||
key = key.substr(1, key.size() - 2);
|
||||
const char quote_char = key.front();
|
||||
if ((quote_char == '\'') || (quote_char == '"')) {
|
||||
if ((key.size() > 2) && (key.back() == quote_char)) {
|
||||
// Strip the quotes
|
||||
key = key.substr(1, key.size() - 2);
|
||||
key_valid = true;
|
||||
}
|
||||
} else {
|
||||
// square brackets, no quotes
|
||||
key_valid = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No square brackets or quotes
|
||||
key_valid = true;
|
||||
}
|
||||
}
|
||||
if (!key_valid) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"invalid key \"%s\", the key must be a bare string or "
|
||||
"surrounded by brackets with optional quotes: [<key>] or "
|
||||
"['<key>'] or [\"<key>\"]",
|
||||
kvp.first.str().c_str());
|
||||
return error;
|
||||
}
|
||||
|
||||
lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
|
||||
kvp.second.data(), m_type_mask, error));
|
||||
if (value_sp) {
|
||||
if (error.Fail())
|
||||
return error;
|
||||
m_value_was_set = true;
|
||||
SetValueForKey(ConstString(key), value_sp, true);
|
||||
} else {
|
||||
error.SetErrorString("dictionaries that can contain multiple types "
|
||||
"must subclass OptionValueArray");
|
||||
}
|
||||
} else {
|
||||
error.SetErrorString("empty argument");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (argc == 0) {
|
||||
error.SetErrorString(
|
||||
"assign operation takes one or more key=value arguments");
|
||||
return error;
|
||||
}
|
||||
for (const auto &entry : args) {
|
||||
if (entry.ref.empty()) {
|
||||
error.SetErrorString("empty argument");
|
||||
return error;
|
||||
}
|
||||
if (!entry.ref.contains('=')) {
|
||||
error.SetErrorString(
|
||||
"assign operation takes one or more key=value arguments");
|
||||
return error;
|
||||
}
|
||||
|
||||
llvm::StringRef key, value;
|
||||
std::tie(key, value) = entry.ref.split('=');
|
||||
bool key_valid = false;
|
||||
if (key.empty()) {
|
||||
error.SetErrorString("empty dictionary key");
|
||||
return error;
|
||||
}
|
||||
|
||||
if (key.front() == '[') {
|
||||
// Key name starts with '[', so the key value must be in single or
|
||||
// double quotes like:
|
||||
// ['<key>']
|
||||
// ["<key>"]
|
||||
if ((key.size() > 2) && (key.back() == ']')) {
|
||||
// Strip leading '[' and trailing ']'
|
||||
key = key.substr(1, key.size() - 2);
|
||||
const char quote_char = key.front();
|
||||
if ((quote_char == '\'') || (quote_char == '"')) {
|
||||
if ((key.size() > 2) && (key.back() == quote_char)) {
|
||||
// Strip the quotes
|
||||
key = key.substr(1, key.size() - 2);
|
||||
key_valid = true;
|
||||
}
|
||||
} else {
|
||||
// square brackets, no quotes
|
||||
key_valid = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No square brackets or quotes
|
||||
key_valid = true;
|
||||
}
|
||||
if (!key_valid) {
|
||||
error.SetErrorStringWithFormat(
|
||||
"invalid key \"%s\", the key must be a bare string or "
|
||||
"surrounded by brackets with optional quotes: [<key>] or "
|
||||
"['<key>'] or [\"<key>\"]",
|
||||
key.str().c_str());
|
||||
return error;
|
||||
}
|
||||
|
||||
lldb::OptionValueSP value_sp(CreateValueFromCStringForTypeMask(
|
||||
value.str().c_str(), m_type_mask, error));
|
||||
if (value_sp) {
|
||||
if (error.Fail())
|
||||
return error;
|
||||
m_value_was_set = true;
|
||||
SetValueForKey(ConstString(key), value_sp, true);
|
||||
} else {
|
||||
error.SetErrorString("dictionaries that can contain multiple types "
|
||||
"must subclass OptionValueArray");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in New Issue