Path: blob/main/contrib/llvm-project/lldb/source/Commands/CommandObjectSettings.cpp
39587 views
//===-- CommandObjectSettings.cpp -----------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "CommandObjectSettings.h"910#include "llvm/ADT/StringRef.h"1112#include "lldb/Host/OptionParser.h"13#include "lldb/Interpreter/CommandCompletions.h"14#include "lldb/Interpreter/CommandInterpreter.h"15#include "lldb/Interpreter/CommandOptionArgumentTable.h"16#include "lldb/Interpreter/CommandReturnObject.h"17#include "lldb/Interpreter/OptionValueProperties.h"1819using namespace lldb;20using namespace lldb_private;2122// CommandObjectSettingsSet23#define LLDB_OPTIONS_settings_set24#include "CommandOptions.inc"2526class CommandObjectSettingsSet : public CommandObjectRaw {27public:28CommandObjectSettingsSet(CommandInterpreter &interpreter)29: CommandObjectRaw(interpreter, "settings set",30"Set the value of the specified debugger setting.") {31CommandArgumentEntry arg1;32CommandArgumentEntry arg2;33CommandArgumentData var_name_arg;34CommandArgumentData value_arg;3536// Define the first (and only) variant of this arg.37var_name_arg.arg_type = eArgTypeSettingVariableName;38var_name_arg.arg_repetition = eArgRepeatPlain;3940// There is only one variant this argument could be; put it into the41// argument entry.42arg1.push_back(var_name_arg);4344// Define the first (and only) variant of this arg.45value_arg.arg_type = eArgTypeValue;46value_arg.arg_repetition = eArgRepeatPlain;4748// There is only one variant this argument could be; put it into the49// argument entry.50arg2.push_back(value_arg);5152// Push the data for the first argument into the m_arguments vector.53m_arguments.push_back(arg1);54m_arguments.push_back(arg2);5556SetHelpLong(57"\nWhen setting a dictionary or array variable, you can set multiple entries \58at once by giving the values to the set command. For example:"59R"(6061(lldb) settings set target.run-args value1 value2 value362(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=123456364(lldb) settings show target.run-args65[0]: 'value1'66[1]: 'value2'67[3]: 'value3'68(lldb) settings show target.env-vars69'MYPATH=~/.:/usr/bin'70'SOME_ENV_VAR=12345'7172)"73"Warning: The 'set' command re-sets the entire array or dictionary. If you \74just want to add, remove or update individual values (or add something to \75the end), use one of the other settings sub-commands: append, replace, \76insert-before or insert-after.");77}7879~CommandObjectSettingsSet() override = default;8081// Overrides base class's behavior where WantsCompletion =82// !WantsRawCommandString.83bool WantsCompletion() override { return true; }8485Options *GetOptions() override { return &m_options; }8687class CommandOptions : public Options {88public:89CommandOptions() = default;9091~CommandOptions() override = default;9293Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,94ExecutionContext *execution_context) override {95Status error;96const int short_option = m_getopt_table[option_idx].val;9798switch (short_option) {99case 'f':100m_force = true;101break;102case 'g':103m_global = true;104break;105case 'e':106m_exists = true;107break;108default:109llvm_unreachable("Unimplemented option");110}111112return error;113}114115void OptionParsingStarting(ExecutionContext *execution_context) override {116m_global = false;117m_force = false;118m_exists = false;119}120121llvm::ArrayRef<OptionDefinition> GetDefinitions() override {122return llvm::ArrayRef(g_settings_set_options);123}124125// Instance variables to hold the values for command options.126bool m_global = false;127bool m_force = false;128bool m_exists = false;129};130131void132HandleArgumentCompletion(CompletionRequest &request,133OptionElementVector &opt_element_vector) override {134135const size_t argc = request.GetParsedLine().GetArgumentCount();136const char *arg = nullptr;137size_t setting_var_idx;138for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) {139arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);140if (arg && arg[0] != '-')141break; // We found our setting variable name index142}143if (request.GetCursorIndex() == setting_var_idx) {144// Attempting to complete setting variable name145lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(146GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,147nullptr);148return;149}150arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());151152if (!arg)153return;154155// Complete option name156if (arg[0] == '-')157return;158159// Complete setting value160const char *setting_var_name =161request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);162Status error;163lldb::OptionValueSP value_sp(164GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, error));165if (!value_sp)166return;167value_sp->AutoComplete(m_interpreter, request);168}169170protected:171void DoExecute(llvm::StringRef command,172CommandReturnObject &result) override {173Args cmd_args(command);174175// Process possible options.176if (!ParseOptions(cmd_args, result))177return;178179const size_t min_argc = m_options.m_force ? 1 : 2;180const size_t argc = cmd_args.GetArgumentCount();181182if ((argc < min_argc) && (!m_options.m_global)) {183result.AppendError("'settings set' takes more arguments");184return;185}186187const char *var_name = cmd_args.GetArgumentAtIndex(0);188if ((var_name == nullptr) || (var_name[0] == '\0')) {189result.AppendError(190"'settings set' command requires a valid variable name");191return;192}193194// A missing value corresponds to clearing the setting when "force" is195// specified.196if (argc == 1 && m_options.m_force) {197Status error(GetDebugger().SetPropertyValue(198&m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));199if (error.Fail()) {200result.AppendError(error.AsCString());201}202return;203}204205// Split the raw command into var_name and value pair.206llvm::StringRef var_value(command);207var_value = var_value.split(var_name).second.ltrim();208209Status error;210if (m_options.m_global)211error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign,212var_name, var_value);213214if (error.Success()) {215// FIXME this is the same issue as the one in commands script import216// we could be setting target.load-script-from-symbol-file which would217// cause Python scripts to be loaded, which could run LLDB commands (e.g.218// settings set target.process.python-os-plugin-path) and cause a crash219// if we did not clear the command's exe_ctx first220ExecutionContext exe_ctx(m_exe_ctx);221m_exe_ctx.Clear();222error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign,223var_name, var_value);224}225226if (error.Fail() && !m_options.m_exists) {227result.AppendError(error.AsCString());228return;229}230231result.SetStatus(eReturnStatusSuccessFinishResult);232}233234private:235CommandOptions m_options;236};237238// CommandObjectSettingsShow -- Show current values239240class CommandObjectSettingsShow : public CommandObjectParsed {241public:242CommandObjectSettingsShow(CommandInterpreter &interpreter)243: CommandObjectParsed(interpreter, "settings show",244"Show matching debugger settings and their current "245"values. Defaults to showing all settings.",246nullptr) {247AddSimpleArgumentList(eArgTypeSettingVariableName, eArgRepeatOptional);248}249250~CommandObjectSettingsShow() override = default;251252protected:253void DoExecute(Args &args, CommandReturnObject &result) override {254result.SetStatus(eReturnStatusSuccessFinishResult);255256if (!args.empty()) {257for (const auto &arg : args) {258Status error(GetDebugger().DumpPropertyValue(259&m_exe_ctx, result.GetOutputStream(), arg.ref(),260OptionValue::eDumpGroupValue));261if (error.Success()) {262result.GetOutputStream().EOL();263} else {264result.AppendError(error.AsCString());265}266}267} else {268GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(),269OptionValue::eDumpGroupValue);270}271}272};273274// CommandObjectSettingsWrite -- Write settings to file275#define LLDB_OPTIONS_settings_write276#include "CommandOptions.inc"277278class CommandObjectSettingsWrite : public CommandObjectParsed {279public:280CommandObjectSettingsWrite(CommandInterpreter &interpreter)281: CommandObjectParsed(282interpreter, "settings export",283"Write matching debugger settings and their "284"current values to a file that can be read in with "285"\"settings read\". Defaults to writing all settings.",286nullptr) {287AddSimpleArgumentList(eArgTypeSettingVariableName, eArgRepeatOptional);288}289290~CommandObjectSettingsWrite() override = default;291292Options *GetOptions() override { return &m_options; }293294class CommandOptions : public Options {295public:296CommandOptions() = default;297298~CommandOptions() override = default;299300Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,301ExecutionContext *execution_context) override {302Status error;303const int short_option = m_getopt_table[option_idx].val;304305switch (short_option) {306case 'f':307m_filename.assign(std::string(option_arg));308break;309case 'a':310m_append = true;311break;312default:313llvm_unreachable("Unimplemented option");314}315316return error;317}318319void OptionParsingStarting(ExecutionContext *execution_context) override {320m_filename.clear();321m_append = false;322}323324llvm::ArrayRef<OptionDefinition> GetDefinitions() override {325return llvm::ArrayRef(g_settings_write_options);326}327328// Instance variables to hold the values for command options.329std::string m_filename;330bool m_append = false;331};332333protected:334void DoExecute(Args &args, CommandReturnObject &result) override {335FileSpec file_spec(m_options.m_filename);336FileSystem::Instance().Resolve(file_spec);337std::string path(file_spec.GetPath());338auto options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;339if (m_options.m_append)340options |= File::eOpenOptionAppend;341else342options |= File::eOpenOptionTruncate;343344StreamFile out_file(path.c_str(), options,345lldb::eFilePermissionsFileDefault);346347if (!out_file.GetFile().IsValid()) {348result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());349return;350}351352// Exporting should not be context sensitive.353ExecutionContext clean_ctx;354355if (args.empty()) {356GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file,357OptionValue::eDumpGroupExport);358return;359}360361for (const auto &arg : args) {362Status error(GetDebugger().DumpPropertyValue(363&clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));364if (!error.Success()) {365result.AppendError(error.AsCString());366}367}368}369370private:371CommandOptions m_options;372};373374// CommandObjectSettingsRead -- Read settings from file375#define LLDB_OPTIONS_settings_read376#include "CommandOptions.inc"377378class CommandObjectSettingsRead : public CommandObjectParsed {379public:380CommandObjectSettingsRead(CommandInterpreter &interpreter)381: CommandObjectParsed(382interpreter, "settings read",383"Read settings previously saved to a file with \"settings write\".",384nullptr) {}385386~CommandObjectSettingsRead() override = default;387388Options *GetOptions() override { return &m_options; }389390class CommandOptions : public Options {391public:392CommandOptions() = default;393394~CommandOptions() override = default;395396Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,397ExecutionContext *execution_context) override {398Status error;399const int short_option = m_getopt_table[option_idx].val;400401switch (short_option) {402case 'f':403m_filename.assign(std::string(option_arg));404break;405default:406llvm_unreachable("Unimplemented option");407}408409return error;410}411412void OptionParsingStarting(ExecutionContext *execution_context) override {413m_filename.clear();414}415416llvm::ArrayRef<OptionDefinition> GetDefinitions() override {417return llvm::ArrayRef(g_settings_read_options);418}419420// Instance variables to hold the values for command options.421std::string m_filename;422};423424protected:425void DoExecute(Args &command, CommandReturnObject &result) override {426FileSpec file(m_options.m_filename);427FileSystem::Instance().Resolve(file);428CommandInterpreterRunOptions options;429options.SetAddToHistory(false);430options.SetEchoCommands(false);431options.SetPrintResults(true);432options.SetPrintErrors(true);433options.SetStopOnError(false);434m_interpreter.HandleCommandsFromFile(file, options, result);435}436437private:438CommandOptions m_options;439};440441// CommandObjectSettingsList -- List settable variables442443class CommandObjectSettingsList : public CommandObjectParsed {444public:445CommandObjectSettingsList(CommandInterpreter &interpreter)446: CommandObjectParsed(interpreter, "settings list",447"List and describe matching debugger settings. "448"Defaults to all listing all settings.",449nullptr) {450CommandArgumentEntry arg;451CommandArgumentData var_name_arg;452CommandArgumentData prefix_name_arg;453454// Define the first variant of this arg.455var_name_arg.arg_type = eArgTypeSettingVariableName;456var_name_arg.arg_repetition = eArgRepeatOptional;457458// Define the second variant of this arg.459prefix_name_arg.arg_type = eArgTypeSettingPrefix;460prefix_name_arg.arg_repetition = eArgRepeatOptional;461462arg.push_back(var_name_arg);463arg.push_back(prefix_name_arg);464465// Push the data for the first argument into the m_arguments vector.466m_arguments.push_back(arg);467}468469~CommandObjectSettingsList() override = default;470471void472HandleArgumentCompletion(CompletionRequest &request,473OptionElementVector &opt_element_vector) override {474lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(475GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,476nullptr);477}478479protected:480void DoExecute(Args &args, CommandReturnObject &result) override {481result.SetStatus(eReturnStatusSuccessFinishResult);482483const size_t argc = args.GetArgumentCount();484if (argc > 0) {485const bool dump_qualified_name = true;486487for (const Args::ArgEntry &arg : args) {488const char *property_path = arg.c_str();489490const Property *property =491GetDebugger().GetValueProperties()->GetPropertyAtPath(492&m_exe_ctx, property_path);493494if (property) {495property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,496dump_qualified_name);497} else {498result.AppendErrorWithFormat("invalid property path '%s'",499property_path);500}501}502} else {503GetDebugger().DumpAllDescriptions(m_interpreter,504result.GetOutputStream());505}506}507};508509// CommandObjectSettingsRemove510511class CommandObjectSettingsRemove : public CommandObjectRaw {512public:513CommandObjectSettingsRemove(CommandInterpreter &interpreter)514: CommandObjectRaw(interpreter, "settings remove",515"Remove a value from a setting, specified by array "516"index or dictionary key.") {517CommandArgumentEntry arg1;518CommandArgumentEntry arg2;519CommandArgumentData var_name_arg;520CommandArgumentData index_arg;521CommandArgumentData key_arg;522523// Define the first (and only) variant of this arg.524var_name_arg.arg_type = eArgTypeSettingVariableName;525var_name_arg.arg_repetition = eArgRepeatPlain;526527// There is only one variant this argument could be; put it into the528// argument entry.529arg1.push_back(var_name_arg);530531// Define the first variant of this arg.532index_arg.arg_type = eArgTypeSettingIndex;533index_arg.arg_repetition = eArgRepeatPlain;534535// Define the second variant of this arg.536key_arg.arg_type = eArgTypeSettingKey;537key_arg.arg_repetition = eArgRepeatPlain;538539// Push both variants into this arg540arg2.push_back(index_arg);541arg2.push_back(key_arg);542543// Push the data for the first argument into the m_arguments vector.544m_arguments.push_back(arg1);545m_arguments.push_back(arg2);546}547548~CommandObjectSettingsRemove() override = default;549550bool WantsCompletion() override { return true; }551552void553HandleArgumentCompletion(CompletionRequest &request,554OptionElementVector &opt_element_vector) override {555if (request.GetCursorIndex() < 2)556lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(557GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,558nullptr);559}560561protected:562void DoExecute(llvm::StringRef command,563CommandReturnObject &result) override {564result.SetStatus(eReturnStatusSuccessFinishNoResult);565566Args cmd_args(command);567568// Process possible options.569if (!ParseOptions(cmd_args, result))570return;571572const size_t argc = cmd_args.GetArgumentCount();573if (argc == 0) {574result.AppendError("'settings remove' takes an array or dictionary item, "575"or an array followed by one or more indexes, or a "576"dictionary followed by one or more key names to "577"remove");578return;579}580581const char *var_name = cmd_args.GetArgumentAtIndex(0);582if ((var_name == nullptr) || (var_name[0] == '\0')) {583result.AppendError(584"'settings remove' command requires a valid variable name");585return;586}587588// Split the raw command into var_name and value pair.589llvm::StringRef var_value(command);590var_value = var_value.split(var_name).second.trim();591592Status error(GetDebugger().SetPropertyValue(593&m_exe_ctx, eVarSetOperationRemove, var_name, var_value));594if (error.Fail()) {595result.AppendError(error.AsCString());596}597}598};599600// CommandObjectSettingsReplace601602class CommandObjectSettingsReplace : public CommandObjectRaw {603public:604CommandObjectSettingsReplace(CommandInterpreter &interpreter)605: CommandObjectRaw(interpreter, "settings replace",606"Replace the debugger setting value specified by "607"array index or dictionary key.") {608CommandArgumentEntry arg1;609CommandArgumentEntry arg2;610CommandArgumentEntry arg3;611CommandArgumentData var_name_arg;612CommandArgumentData index_arg;613CommandArgumentData key_arg;614CommandArgumentData value_arg;615616// Define the first (and only) variant of this arg.617var_name_arg.arg_type = eArgTypeSettingVariableName;618var_name_arg.arg_repetition = eArgRepeatPlain;619620// There is only one variant this argument could be; put it into the621// argument entry.622arg1.push_back(var_name_arg);623624// Define the first (variant of this arg.625index_arg.arg_type = eArgTypeSettingIndex;626index_arg.arg_repetition = eArgRepeatPlain;627628// Define the second (variant of this arg.629key_arg.arg_type = eArgTypeSettingKey;630key_arg.arg_repetition = eArgRepeatPlain;631632// Put both variants into this arg633arg2.push_back(index_arg);634arg2.push_back(key_arg);635636// Define the first (and only) variant of this arg.637value_arg.arg_type = eArgTypeValue;638value_arg.arg_repetition = eArgRepeatPlain;639640// There is only one variant this argument could be; put it into the641// argument entry.642arg3.push_back(value_arg);643644// Push the data for the first argument into the m_arguments vector.645m_arguments.push_back(arg1);646m_arguments.push_back(arg2);647m_arguments.push_back(arg3);648}649650~CommandObjectSettingsReplace() override = default;651652// Overrides base class's behavior where WantsCompletion =653// !WantsRawCommandString.654bool WantsCompletion() override { return true; }655656void657HandleArgumentCompletion(CompletionRequest &request,658OptionElementVector &opt_element_vector) override {659// Attempting to complete variable name660if (request.GetCursorIndex() < 2)661lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(662GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,663nullptr);664}665666protected:667void DoExecute(llvm::StringRef command,668CommandReturnObject &result) override {669result.SetStatus(eReturnStatusSuccessFinishNoResult);670671Args cmd_args(command);672const char *var_name = cmd_args.GetArgumentAtIndex(0);673if ((var_name == nullptr) || (var_name[0] == '\0')) {674result.AppendError("'settings replace' command requires a valid variable "675"name; No value supplied");676return;677}678679// Split the raw command into var_name, index_value, and value triple.680llvm::StringRef var_value(command);681var_value = var_value.split(var_name).second.trim();682683Status error(GetDebugger().SetPropertyValue(684&m_exe_ctx, eVarSetOperationReplace, var_name, var_value));685if (error.Fail()) {686result.AppendError(error.AsCString());687} else {688result.SetStatus(eReturnStatusSuccessFinishNoResult);689}690}691};692693// CommandObjectSettingsInsertBefore694695class CommandObjectSettingsInsertBefore : public CommandObjectRaw {696public:697CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)698: CommandObjectRaw(interpreter, "settings insert-before",699"Insert one or more values into an debugger array "700"setting immediately before the specified element "701"index.") {702CommandArgumentEntry arg1;703CommandArgumentEntry arg2;704CommandArgumentEntry arg3;705CommandArgumentData var_name_arg;706CommandArgumentData index_arg;707CommandArgumentData value_arg;708709// Define the first (and only) variant of this arg.710var_name_arg.arg_type = eArgTypeSettingVariableName;711var_name_arg.arg_repetition = eArgRepeatPlain;712713// There is only one variant this argument could be; put it into the714// argument entry.715arg1.push_back(var_name_arg);716717// Define the first (variant of this arg.718index_arg.arg_type = eArgTypeSettingIndex;719index_arg.arg_repetition = eArgRepeatPlain;720721// There is only one variant this argument could be; put it into the722// argument entry.723arg2.push_back(index_arg);724725// Define the first (and only) variant of this arg.726value_arg.arg_type = eArgTypeValue;727value_arg.arg_repetition = eArgRepeatPlain;728729// There is only one variant this argument could be; put it into the730// argument entry.731arg3.push_back(value_arg);732733// Push the data for the first argument into the m_arguments vector.734m_arguments.push_back(arg1);735m_arguments.push_back(arg2);736m_arguments.push_back(arg3);737}738739~CommandObjectSettingsInsertBefore() override = default;740741// Overrides base class's behavior where WantsCompletion =742// !WantsRawCommandString.743bool WantsCompletion() override { return true; }744745void746HandleArgumentCompletion(CompletionRequest &request,747OptionElementVector &opt_element_vector) override {748// Attempting to complete variable name749if (request.GetCursorIndex() < 2)750lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(751GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,752nullptr);753}754755protected:756void DoExecute(llvm::StringRef command,757CommandReturnObject &result) override {758result.SetStatus(eReturnStatusSuccessFinishNoResult);759760Args cmd_args(command);761const size_t argc = cmd_args.GetArgumentCount();762763if (argc < 3) {764result.AppendError("'settings insert-before' takes more arguments");765return;766}767768const char *var_name = cmd_args.GetArgumentAtIndex(0);769if ((var_name == nullptr) || (var_name[0] == '\0')) {770result.AppendError("'settings insert-before' command requires a valid "771"variable name; No value supplied");772return;773}774775// Split the raw command into var_name, index_value, and value triple.776llvm::StringRef var_value(command);777var_value = var_value.split(var_name).second.trim();778779Status error(GetDebugger().SetPropertyValue(780&m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));781if (error.Fail()) {782result.AppendError(error.AsCString());783}784}785};786787// CommandObjectSettingInsertAfter788789class CommandObjectSettingsInsertAfter : public CommandObjectRaw {790public:791CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)792: CommandObjectRaw(interpreter, "settings insert-after",793"Insert one or more values into a debugger array "794"settings after the specified element index.") {795CommandArgumentEntry arg1;796CommandArgumentEntry arg2;797CommandArgumentEntry arg3;798CommandArgumentData var_name_arg;799CommandArgumentData index_arg;800CommandArgumentData value_arg;801802// Define the first (and only) variant of this arg.803var_name_arg.arg_type = eArgTypeSettingVariableName;804var_name_arg.arg_repetition = eArgRepeatPlain;805806// There is only one variant this argument could be; put it into the807// argument entry.808arg1.push_back(var_name_arg);809810// Define the first (variant of this arg.811index_arg.arg_type = eArgTypeSettingIndex;812index_arg.arg_repetition = eArgRepeatPlain;813814// There is only one variant this argument could be; put it into the815// argument entry.816arg2.push_back(index_arg);817818// Define the first (and only) variant of this arg.819value_arg.arg_type = eArgTypeValue;820value_arg.arg_repetition = eArgRepeatPlain;821822// There is only one variant this argument could be; put it into the823// argument entry.824arg3.push_back(value_arg);825826// Push the data for the first argument into the m_arguments vector.827m_arguments.push_back(arg1);828m_arguments.push_back(arg2);829m_arguments.push_back(arg3);830}831832~CommandObjectSettingsInsertAfter() override = default;833834// Overrides base class's behavior where WantsCompletion =835// !WantsRawCommandString.836bool WantsCompletion() override { return true; }837838void839HandleArgumentCompletion(CompletionRequest &request,840OptionElementVector &opt_element_vector) override {841// Attempting to complete variable name842if (request.GetCursorIndex() < 2)843lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(844GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,845nullptr);846}847848protected:849void DoExecute(llvm::StringRef command,850CommandReturnObject &result) override {851result.SetStatus(eReturnStatusSuccessFinishNoResult);852853Args cmd_args(command);854const size_t argc = cmd_args.GetArgumentCount();855856if (argc < 3) {857result.AppendError("'settings insert-after' takes more arguments");858return;859}860861const char *var_name = cmd_args.GetArgumentAtIndex(0);862if ((var_name == nullptr) || (var_name[0] == '\0')) {863result.AppendError("'settings insert-after' command requires a valid "864"variable name; No value supplied");865return;866}867868// Split the raw command into var_name, index_value, and value triple.869llvm::StringRef var_value(command);870var_value = var_value.split(var_name).second.trim();871872Status error(GetDebugger().SetPropertyValue(873&m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));874if (error.Fail()) {875result.AppendError(error.AsCString());876}877}878};879880// CommandObjectSettingsAppend881882class CommandObjectSettingsAppend : public CommandObjectRaw {883public:884CommandObjectSettingsAppend(CommandInterpreter &interpreter)885: CommandObjectRaw(interpreter, "settings append",886"Append one or more values to a debugger array, "887"dictionary, or string setting.") {888CommandArgumentEntry arg1;889CommandArgumentEntry arg2;890CommandArgumentData var_name_arg;891CommandArgumentData value_arg;892893// Define the first (and only) variant of this arg.894var_name_arg.arg_type = eArgTypeSettingVariableName;895var_name_arg.arg_repetition = eArgRepeatPlain;896897// There is only one variant this argument could be; put it into the898// argument entry.899arg1.push_back(var_name_arg);900901// Define the first (and only) variant of this arg.902value_arg.arg_type = eArgTypeValue;903value_arg.arg_repetition = eArgRepeatPlain;904905// There is only one variant this argument could be; put it into the906// argument entry.907arg2.push_back(value_arg);908909// Push the data for the first argument into the m_arguments vector.910m_arguments.push_back(arg1);911m_arguments.push_back(arg2);912}913914~CommandObjectSettingsAppend() override = default;915916// Overrides base class's behavior where WantsCompletion =917// !WantsRawCommandString.918bool WantsCompletion() override { return true; }919920void921HandleArgumentCompletion(CompletionRequest &request,922OptionElementVector &opt_element_vector) override {923// Attempting to complete variable name924if (request.GetCursorIndex() < 2)925lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(926GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,927nullptr);928}929930protected:931void DoExecute(llvm::StringRef command,932CommandReturnObject &result) override {933result.SetStatus(eReturnStatusSuccessFinishNoResult);934Args cmd_args(command);935const size_t argc = cmd_args.GetArgumentCount();936937if (argc < 2) {938result.AppendError("'settings append' takes more arguments");939return;940}941942const char *var_name = cmd_args.GetArgumentAtIndex(0);943if ((var_name == nullptr) || (var_name[0] == '\0')) {944result.AppendError("'settings append' command requires a valid variable "945"name; No value supplied");946return;947}948949// Do not perform cmd_args.Shift() since StringRef is manipulating the raw950// character string later on.951952// Split the raw command into var_name and value pair.953llvm::StringRef var_value(command);954var_value = var_value.split(var_name).second.trim();955956Status error(GetDebugger().SetPropertyValue(957&m_exe_ctx, eVarSetOperationAppend, var_name, var_value));958if (error.Fail()) {959result.AppendError(error.AsCString());960}961}962};963964// CommandObjectSettingsClear965#define LLDB_OPTIONS_settings_clear966#include "CommandOptions.inc"967968class CommandObjectSettingsClear : public CommandObjectParsed {969public:970CommandObjectSettingsClear(CommandInterpreter &interpreter)971: CommandObjectParsed(972interpreter, "settings clear",973"Clear a debugger setting array, dictionary, or string. "974"If '-a' option is specified, it clears all settings.", nullptr) {975AddSimpleArgumentList(eArgTypeSettingVariableName);976}977978~CommandObjectSettingsClear() override = default;979980void981HandleArgumentCompletion(CompletionRequest &request,982OptionElementVector &opt_element_vector) override {983// Attempting to complete variable name984if (request.GetCursorIndex() < 2)985lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(986GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,987nullptr);988}989990Options *GetOptions() override { return &m_options; }991992class CommandOptions : public Options {993public:994CommandOptions() = default;995996~CommandOptions() override = default;997998Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,999ExecutionContext *execution_context) override {1000const int short_option = m_getopt_table[option_idx].val;1001switch (short_option) {1002case 'a':1003m_clear_all = true;1004break;1005default:1006llvm_unreachable("Unimplemented option");1007}1008return Status();1009}10101011void OptionParsingStarting(ExecutionContext *execution_context) override {1012m_clear_all = false;1013}10141015llvm::ArrayRef<OptionDefinition> GetDefinitions() override {1016return llvm::ArrayRef(g_settings_clear_options);1017}10181019bool m_clear_all = false;1020};10211022protected:1023void DoExecute(Args &command, CommandReturnObject &result) override {1024result.SetStatus(eReturnStatusSuccessFinishNoResult);1025const size_t argc = command.GetArgumentCount();10261027if (m_options.m_clear_all) {1028if (argc != 0) {1029result.AppendError("'settings clear --all' doesn't take any arguments");1030return;1031}1032GetDebugger().GetValueProperties()->Clear();1033return;1034}10351036if (argc != 1) {1037result.AppendError("'settings clear' takes exactly one argument");1038return;1039}10401041const char *var_name = command.GetArgumentAtIndex(0);1042if ((var_name == nullptr) || (var_name[0] == '\0')) {1043result.AppendError("'settings clear' command requires a valid variable "1044"name; No value supplied");1045return;1046}10471048Status error(GetDebugger().SetPropertyValue(1049&m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));1050if (error.Fail()) {1051result.AppendError(error.AsCString());1052}1053}10541055private:1056CommandOptions m_options;1057};10581059// CommandObjectMultiwordSettings10601061CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(1062CommandInterpreter &interpreter)1063: CommandObjectMultiword(interpreter, "settings",1064"Commands for managing LLDB settings.",1065"settings <subcommand> [<command-options>]") {1066LoadSubCommand("set",1067CommandObjectSP(new CommandObjectSettingsSet(interpreter)));1068LoadSubCommand("show",1069CommandObjectSP(new CommandObjectSettingsShow(interpreter)));1070LoadSubCommand("list",1071CommandObjectSP(new CommandObjectSettingsList(interpreter)));1072LoadSubCommand("remove",1073CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));1074LoadSubCommand("replace", CommandObjectSP(1075new CommandObjectSettingsReplace(interpreter)));1076LoadSubCommand(1077"insert-before",1078CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));1079LoadSubCommand(1080"insert-after",1081CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));1082LoadSubCommand("append",1083CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));1084LoadSubCommand("clear",1085CommandObjectSP(new CommandObjectSettingsClear(interpreter)));1086LoadSubCommand("write",1087CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));1088LoadSubCommand("read",1089CommandObjectSP(new CommandObjectSettingsRead(interpreter)));1090}10911092CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;109310941095