forked from OSchip/llvm-project
1051 lines
38 KiB
C++
1051 lines
38 KiB
C++
//===-- CommandObjectSettings.cpp -------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CommandObjectSettings.h"
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
// Project includes
|
|
#include "lldb/Host/OptionParser.h"
|
|
#include "lldb/Interpreter/CommandCompletions.h"
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
#include "lldb/Interpreter/CommandReturnObject.h"
|
|
#include "lldb/Interpreter/OptionValueProperties.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsSet
|
|
//-------------------------------------------------------------------------
|
|
|
|
static OptionDefinition g_settings_set_options[] = {
|
|
// clang-format off
|
|
{ LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value." }
|
|
// clang-format on
|
|
};
|
|
|
|
class CommandObjectSettingsSet : public CommandObjectRaw {
|
|
public:
|
|
CommandObjectSettingsSet(CommandInterpreter &interpreter)
|
|
: CommandObjectRaw(interpreter, "settings set",
|
|
"Set the value of the specified debugger setting."),
|
|
m_options() {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentEntry arg2;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData value_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
value_arg.arg_type = eArgTypeValue;
|
|
value_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg2.push_back(value_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
m_arguments.push_back(arg2);
|
|
|
|
SetHelpLong(
|
|
"\nWhen setting a dictionary or array variable, you can set multiple entries \
|
|
at once by giving the values to the set command. For example:"
|
|
R"(
|
|
|
|
(lldb) settings set target.run-args value1 value2 value3
|
|
(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=12345
|
|
|
|
(lldb) settings show target.run-args
|
|
[0]: 'value1'
|
|
[1]: 'value2'
|
|
[3]: 'value3'
|
|
(lldb) settings show target.env-vars
|
|
'MYPATH=~/.:/usr/bin'
|
|
'SOME_ENV_VAR=12345'
|
|
|
|
)"
|
|
"Warning: The 'set' command re-sets the entire array or dictionary. If you \
|
|
just want to add, remove or update individual values (or add something to \
|
|
the end), use one of the other settings sub-commands: append, replace, \
|
|
insert-before or insert-after.");
|
|
}
|
|
|
|
~CommandObjectSettingsSet() override = default;
|
|
|
|
// Overrides base class's behavior where WantsCompletion =
|
|
// !WantsRawCommandString.
|
|
bool WantsCompletion() override { return true; }
|
|
|
|
Options *GetOptions() override { return &m_options; }
|
|
|
|
class CommandOptions : public Options {
|
|
public:
|
|
CommandOptions() : Options(), m_global(false) {}
|
|
|
|
~CommandOptions() override = default;
|
|
|
|
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
|
|
ExecutionContext *execution_context) override {
|
|
Status error;
|
|
const int short_option = m_getopt_table[option_idx].val;
|
|
|
|
switch (short_option) {
|
|
case 'g':
|
|
m_global = true;
|
|
break;
|
|
default:
|
|
error.SetErrorStringWithFormat("unrecognized options '%c'",
|
|
short_option);
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
void OptionParsingStarting(ExecutionContext *execution_context) override {
|
|
m_global = false;
|
|
}
|
|
|
|
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
|
|
return llvm::makeArrayRef(g_settings_set_options);
|
|
}
|
|
|
|
// Instance variables to hold the values for command options.
|
|
|
|
bool m_global;
|
|
};
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
const size_t argc = input.GetArgumentCount();
|
|
const char *arg = nullptr;
|
|
int setting_var_idx;
|
|
for (setting_var_idx = 0; setting_var_idx < static_cast<int>(argc);
|
|
++setting_var_idx) {
|
|
arg = input.GetArgumentAtIndex(setting_var_idx);
|
|
if (arg && arg[0] != '-')
|
|
break; // We found our setting variable name index
|
|
}
|
|
if (cursor_index == setting_var_idx) {
|
|
// Attempting to complete setting variable name
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
} else {
|
|
arg = input.GetArgumentAtIndex(cursor_index);
|
|
|
|
if (arg) {
|
|
if (arg[0] == '-') {
|
|
// Complete option name
|
|
} else {
|
|
// Complete setting value
|
|
const char *setting_var_name =
|
|
input.GetArgumentAtIndex(setting_var_idx);
|
|
Status error;
|
|
lldb::OptionValueSP value_sp(
|
|
m_interpreter.GetDebugger().GetPropertyValue(
|
|
&m_exe_ctx, setting_var_name, false, error));
|
|
if (value_sp) {
|
|
value_sp->AutoComplete(m_interpreter, completion_str.c_str(),
|
|
match_start_point, max_return_elements,
|
|
word_complete, matches);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(const char *command, CommandReturnObject &result) override {
|
|
Args cmd_args(command);
|
|
|
|
// Process possible options.
|
|
if (!ParseOptions(cmd_args, result))
|
|
return false;
|
|
|
|
const size_t argc = cmd_args.GetArgumentCount();
|
|
if ((argc < 2) && (!m_options.m_global)) {
|
|
result.AppendError("'settings set' takes more arguments");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
const char *var_name = cmd_args.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError(
|
|
"'settings set' command requires a valid variable name");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
// Split the raw command into var_name and value pair.
|
|
llvm::StringRef raw_str(command);
|
|
std::string var_value_string = raw_str.split(var_name).second.str();
|
|
const char *var_value_cstr =
|
|
Args::StripSpaces(var_value_string, true, false, false);
|
|
|
|
Status error;
|
|
if (m_options.m_global) {
|
|
error = m_interpreter.GetDebugger().SetPropertyValue(
|
|
nullptr, eVarSetOperationAssign, var_name, var_value_cstr);
|
|
}
|
|
|
|
if (error.Success()) {
|
|
// FIXME this is the same issue as the one in commands script import
|
|
// we could be setting target.load-script-from-symbol-file which would
|
|
// cause Python scripts to be loaded, which could run LLDB commands (e.g.
|
|
// settings set target.process.python-os-plugin-path) and cause a crash
|
|
// if we did not clear the command's exe_ctx first
|
|
ExecutionContext exe_ctx(m_exe_ctx);
|
|
m_exe_ctx.Clear();
|
|
error = m_interpreter.GetDebugger().SetPropertyValue(
|
|
&exe_ctx, eVarSetOperationAssign, var_name, var_value_cstr);
|
|
}
|
|
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
} else {
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
|
|
private:
|
|
CommandOptions m_options;
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsShow -- Show current values
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsShow : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectSettingsShow(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "settings show",
|
|
"Show matching debugger settings and their current "
|
|
"values. Defaults to showing all settings.",
|
|
nullptr) {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentData var_name_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatOptional;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
}
|
|
|
|
~CommandObjectSettingsShow() override = default;
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements, nullptr,
|
|
word_complete, matches);
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(Args &args, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
|
|
if (!args.empty()) {
|
|
for (const auto &arg : args) {
|
|
Status error(m_interpreter.GetDebugger().DumpPropertyValue(
|
|
&m_exe_ctx, result.GetOutputStream(), arg.ref,
|
|
OptionValue::eDumpGroupValue));
|
|
if (error.Success()) {
|
|
result.GetOutputStream().EOL();
|
|
} else {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
}
|
|
}
|
|
} else {
|
|
m_interpreter.GetDebugger().DumpAllPropertyValues(
|
|
&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsList -- List settable variables
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsList : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectSettingsList(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(interpreter, "settings list",
|
|
"List and describe matching debugger settings. "
|
|
"Defaults to all listing all settings.",
|
|
nullptr) {
|
|
CommandArgumentEntry arg;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData prefix_name_arg;
|
|
|
|
// Define the first variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatOptional;
|
|
|
|
// Define the second variant of this arg.
|
|
prefix_name_arg.arg_type = eArgTypeSettingPrefix;
|
|
prefix_name_arg.arg_repetition = eArgRepeatOptional;
|
|
|
|
arg.push_back(var_name_arg);
|
|
arg.push_back(prefix_name_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg);
|
|
}
|
|
|
|
~CommandObjectSettingsList() override = default;
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements, nullptr,
|
|
word_complete, matches);
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(Args &args, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishResult);
|
|
|
|
const bool will_modify = false;
|
|
const size_t argc = args.GetArgumentCount();
|
|
if (argc > 0) {
|
|
const bool dump_qualified_name = true;
|
|
|
|
// TODO: Convert to StringRef based enumeration. Requires converting
|
|
// GetPropertyAtPath first.
|
|
for (size_t i = 0; i < argc; ++i) {
|
|
const char *property_path = args.GetArgumentAtIndex(i);
|
|
|
|
const Property *property =
|
|
m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath(
|
|
&m_exe_ctx, will_modify, property_path);
|
|
|
|
if (property) {
|
|
property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
|
|
dump_qualified_name);
|
|
} else {
|
|
result.AppendErrorWithFormat("invalid property path '%s'",
|
|
property_path);
|
|
result.SetStatus(eReturnStatusFailed);
|
|
}
|
|
}
|
|
} else {
|
|
m_interpreter.GetDebugger().DumpAllDescriptions(m_interpreter,
|
|
result.GetOutputStream());
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsRemove
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsRemove : public CommandObjectRaw {
|
|
public:
|
|
CommandObjectSettingsRemove(CommandInterpreter &interpreter)
|
|
: CommandObjectRaw(interpreter, "settings remove",
|
|
"Remove a value from a setting, specified by array "
|
|
"index or dictionary key.") {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentEntry arg2;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData index_arg;
|
|
CommandArgumentData key_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Define the first variant of this arg.
|
|
index_arg.arg_type = eArgTypeSettingIndex;
|
|
index_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// Define the second variant of this arg.
|
|
key_arg.arg_type = eArgTypeSettingKey;
|
|
key_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// Push both variants into this arg
|
|
arg2.push_back(index_arg);
|
|
arg2.push_back(key_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
m_arguments.push_back(arg2);
|
|
}
|
|
|
|
~CommandObjectSettingsRemove() override = default;
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
// Attempting to complete variable name
|
|
if (cursor_index < 2)
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(const char *command, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
|
|
Args cmd_args(command);
|
|
|
|
// Process possible options.
|
|
if (!ParseOptions(cmd_args, result))
|
|
return false;
|
|
|
|
const size_t argc = cmd_args.GetArgumentCount();
|
|
if (argc == 0) {
|
|
result.AppendError("'settings set' takes an array or dictionary item, or "
|
|
"an array followed by one or more indexes, or a "
|
|
"dictionary followed by one or more key names to "
|
|
"remove");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
const char *var_name = cmd_args.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError(
|
|
"'settings set' command requires a valid variable name");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
// Split the raw command into var_name and value pair.
|
|
llvm::StringRef raw_str(command);
|
|
std::string var_value_string = raw_str.split(var_name).second.str();
|
|
const char *var_value_cstr =
|
|
Args::StripSpaces(var_value_string, true, true, false);
|
|
|
|
Status error(m_interpreter.GetDebugger().SetPropertyValue(
|
|
&m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr));
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsReplace
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsReplace : public CommandObjectRaw {
|
|
public:
|
|
CommandObjectSettingsReplace(CommandInterpreter &interpreter)
|
|
: CommandObjectRaw(interpreter, "settings replace",
|
|
"Replace the debugger setting value specified by "
|
|
"array index or dictionary key.") {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentEntry arg2;
|
|
CommandArgumentEntry arg3;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData index_arg;
|
|
CommandArgumentData key_arg;
|
|
CommandArgumentData value_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Define the first (variant of this arg.
|
|
index_arg.arg_type = eArgTypeSettingIndex;
|
|
index_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// Define the second (variant of this arg.
|
|
key_arg.arg_type = eArgTypeSettingKey;
|
|
key_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// Put both variants into this arg
|
|
arg2.push_back(index_arg);
|
|
arg2.push_back(key_arg);
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
value_arg.arg_type = eArgTypeValue;
|
|
value_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg3.push_back(value_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
m_arguments.push_back(arg2);
|
|
m_arguments.push_back(arg3);
|
|
}
|
|
|
|
~CommandObjectSettingsReplace() override = default;
|
|
|
|
// Overrides base class's behavior where WantsCompletion =
|
|
// !WantsRawCommandString.
|
|
bool WantsCompletion() override { return true; }
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
// Attempting to complete variable name
|
|
if (cursor_index < 2)
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(const char *command, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
|
|
Args cmd_args(command);
|
|
const char *var_name = cmd_args.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError("'settings replace' command requires a valid variable "
|
|
"name; No value supplied");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
// Split the raw command into var_name, index_value, and value triple.
|
|
llvm::StringRef raw_str(command);
|
|
std::string var_value_string = raw_str.split(var_name).second.str();
|
|
const char *var_value_cstr =
|
|
Args::StripSpaces(var_value_string, true, true, false);
|
|
|
|
Status error(m_interpreter.GetDebugger().SetPropertyValue(
|
|
&m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr));
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
} else {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsInsertBefore
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
|
|
public:
|
|
CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
|
|
: CommandObjectRaw(interpreter, "settings insert-before",
|
|
"Insert one or more values into an debugger array "
|
|
"setting immediately before the specified element "
|
|
"index.") {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentEntry arg2;
|
|
CommandArgumentEntry arg3;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData index_arg;
|
|
CommandArgumentData value_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Define the first (variant of this arg.
|
|
index_arg.arg_type = eArgTypeSettingIndex;
|
|
index_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg2.push_back(index_arg);
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
value_arg.arg_type = eArgTypeValue;
|
|
value_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg3.push_back(value_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
m_arguments.push_back(arg2);
|
|
m_arguments.push_back(arg3);
|
|
}
|
|
|
|
~CommandObjectSettingsInsertBefore() override = default;
|
|
|
|
// Overrides base class's behavior where WantsCompletion =
|
|
// !WantsRawCommandString.
|
|
bool WantsCompletion() override { return true; }
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
// Attempting to complete variable name
|
|
if (cursor_index < 2)
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(const char *command, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
|
|
Args cmd_args(command);
|
|
const size_t argc = cmd_args.GetArgumentCount();
|
|
|
|
if (argc < 3) {
|
|
result.AppendError("'settings insert-before' takes more arguments");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
const char *var_name = cmd_args.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError("'settings insert-before' command requires a valid "
|
|
"variable name; No value supplied");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
// Split the raw command into var_name, index_value, and value triple.
|
|
llvm::StringRef raw_str(command);
|
|
std::string var_value_string = raw_str.split(var_name).second.str();
|
|
const char *var_value_cstr =
|
|
Args::StripSpaces(var_value_string, true, true, false);
|
|
|
|
Status error(m_interpreter.GetDebugger().SetPropertyValue(
|
|
&m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr));
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingInsertAfter
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
|
|
public:
|
|
CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
|
|
: CommandObjectRaw(interpreter, "settings insert-after",
|
|
"Insert one or more values into a debugger array "
|
|
"settings after the specified element index.") {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentEntry arg2;
|
|
CommandArgumentEntry arg3;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData index_arg;
|
|
CommandArgumentData value_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Define the first (variant of this arg.
|
|
index_arg.arg_type = eArgTypeSettingIndex;
|
|
index_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg2.push_back(index_arg);
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
value_arg.arg_type = eArgTypeValue;
|
|
value_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg3.push_back(value_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
m_arguments.push_back(arg2);
|
|
m_arguments.push_back(arg3);
|
|
}
|
|
|
|
~CommandObjectSettingsInsertAfter() override = default;
|
|
|
|
// Overrides base class's behavior where WantsCompletion =
|
|
// !WantsRawCommandString.
|
|
bool WantsCompletion() override { return true; }
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
// Attempting to complete variable name
|
|
if (cursor_index < 2)
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(const char *command, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
|
|
Args cmd_args(command);
|
|
const size_t argc = cmd_args.GetArgumentCount();
|
|
|
|
if (argc < 3) {
|
|
result.AppendError("'settings insert-after' takes more arguments");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
const char *var_name = cmd_args.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError("'settings insert-after' command requires a valid "
|
|
"variable name; No value supplied");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
// Split the raw command into var_name, index_value, and value triple.
|
|
llvm::StringRef raw_str(command);
|
|
std::string var_value_string = raw_str.split(var_name).second.str();
|
|
const char *var_value_cstr =
|
|
Args::StripSpaces(var_value_string, true, true, false);
|
|
|
|
Status error(m_interpreter.GetDebugger().SetPropertyValue(
|
|
&m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr));
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsAppend
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsAppend : public CommandObjectRaw {
|
|
public:
|
|
CommandObjectSettingsAppend(CommandInterpreter &interpreter)
|
|
: CommandObjectRaw(interpreter, "settings append",
|
|
"Append one or more values to a debugger array, "
|
|
"dictionary, or string setting.") {
|
|
CommandArgumentEntry arg1;
|
|
CommandArgumentEntry arg2;
|
|
CommandArgumentData var_name_arg;
|
|
CommandArgumentData value_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg1.push_back(var_name_arg);
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
value_arg.arg_type = eArgTypeValue;
|
|
value_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg2.push_back(value_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg1);
|
|
m_arguments.push_back(arg2);
|
|
}
|
|
|
|
~CommandObjectSettingsAppend() override = default;
|
|
|
|
// Overrides base class's behavior where WantsCompletion =
|
|
// !WantsRawCommandString.
|
|
bool WantsCompletion() override { return true; }
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
// Attempting to complete variable name
|
|
if (cursor_index < 2)
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(const char *command, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
Args cmd_args(command);
|
|
const size_t argc = cmd_args.GetArgumentCount();
|
|
|
|
if (argc < 2) {
|
|
result.AppendError("'settings append' takes more arguments");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
const char *var_name = cmd_args.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError("'settings append' command requires a valid variable "
|
|
"name; No value supplied");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
// Do not perform cmd_args.Shift() since StringRef is manipulating the raw
|
|
// character string later on.
|
|
|
|
// Split the raw command into var_name and value pair.
|
|
llvm::StringRef raw_str(command);
|
|
std::string var_value_string = raw_str.split(var_name).second.str();
|
|
const char *var_value_cstr =
|
|
Args::StripSpaces(var_value_string, true, true, false);
|
|
|
|
Status error(m_interpreter.GetDebugger().SetPropertyValue(
|
|
&m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr));
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectSettingsClear
|
|
//-------------------------------------------------------------------------
|
|
|
|
class CommandObjectSettingsClear : public CommandObjectParsed {
|
|
public:
|
|
CommandObjectSettingsClear(CommandInterpreter &interpreter)
|
|
: CommandObjectParsed(
|
|
interpreter, "settings clear",
|
|
"Clear a debugger setting array, dictionary, or string.", nullptr) {
|
|
CommandArgumentEntry arg;
|
|
CommandArgumentData var_name_arg;
|
|
|
|
// Define the first (and only) variant of this arg.
|
|
var_name_arg.arg_type = eArgTypeSettingVariableName;
|
|
var_name_arg.arg_repetition = eArgRepeatPlain;
|
|
|
|
// There is only one variant this argument could be; put it into the
|
|
// argument entry.
|
|
arg.push_back(var_name_arg);
|
|
|
|
// Push the data for the first argument into the m_arguments vector.
|
|
m_arguments.push_back(arg);
|
|
}
|
|
|
|
~CommandObjectSettingsClear() override = default;
|
|
|
|
int HandleArgumentCompletion(Args &input, int &cursor_index,
|
|
int &cursor_char_position,
|
|
OptionElementVector &opt_element_vector,
|
|
int match_start_point, int max_return_elements,
|
|
bool &word_complete,
|
|
StringList &matches) override {
|
|
std::string completion_str(input.GetArgumentAtIndex(cursor_index),
|
|
cursor_char_position);
|
|
|
|
// Attempting to complete variable name
|
|
if (cursor_index < 2)
|
|
CommandCompletions::InvokeCommonCompletionCallbacks(
|
|
GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
|
|
completion_str.c_str(), match_start_point, max_return_elements,
|
|
nullptr, word_complete, matches);
|
|
|
|
return matches.GetSize();
|
|
}
|
|
|
|
protected:
|
|
bool DoExecute(Args &command, CommandReturnObject &result) override {
|
|
result.SetStatus(eReturnStatusSuccessFinishNoResult);
|
|
const size_t argc = command.GetArgumentCount();
|
|
|
|
if (argc != 1) {
|
|
result.AppendError("'settings clear' takes exactly one argument");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
const char *var_name = command.GetArgumentAtIndex(0);
|
|
if ((var_name == nullptr) || (var_name[0] == '\0')) {
|
|
result.AppendError("'settings clear' command requires a valid variable "
|
|
"name; No value supplied");
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
Status error(m_interpreter.GetDebugger().SetPropertyValue(
|
|
&m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
|
|
if (error.Fail()) {
|
|
result.AppendError(error.AsCString());
|
|
result.SetStatus(eReturnStatusFailed);
|
|
return false;
|
|
}
|
|
|
|
return result.Succeeded();
|
|
}
|
|
};
|
|
|
|
//-------------------------------------------------------------------------
|
|
// CommandObjectMultiwordSettings
|
|
//-------------------------------------------------------------------------
|
|
|
|
CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
|
|
CommandInterpreter &interpreter)
|
|
: CommandObjectMultiword(interpreter, "settings",
|
|
"Commands for managing LLDB settings.",
|
|
"settings <subcommand> [<command-options>]") {
|
|
LoadSubCommand("set",
|
|
CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
|
|
LoadSubCommand("show",
|
|
CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
|
|
LoadSubCommand("list",
|
|
CommandObjectSP(new CommandObjectSettingsList(interpreter)));
|
|
LoadSubCommand("remove",
|
|
CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
|
|
LoadSubCommand("replace", CommandObjectSP(
|
|
new CommandObjectSettingsReplace(interpreter)));
|
|
LoadSubCommand(
|
|
"insert-before",
|
|
CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
|
|
LoadSubCommand(
|
|
"insert-after",
|
|
CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
|
|
LoadSubCommand("append",
|
|
CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
|
|
LoadSubCommand("clear",
|
|
CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
|
|
}
|
|
|
|
CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
|