1131 lines · cpp
1//===-- CommandObjectSettings.cpp -----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "CommandObjectSettings.h"10 11#include "llvm/ADT/StringRef.h"12 13#include "lldb/Host/OptionParser.h"14#include "lldb/Interpreter/CommandCompletions.h"15#include "lldb/Interpreter/CommandInterpreter.h"16#include "lldb/Interpreter/CommandOptionArgumentTable.h"17#include "lldb/Interpreter/CommandReturnObject.h"18#include "lldb/Interpreter/OptionValueProperties.h"19 20using namespace lldb;21using namespace lldb_private;22 23// CommandObjectSettingsSet24#define LLDB_OPTIONS_settings_set25#include "CommandOptions.inc"26 27class CommandObjectSettingsSet : public CommandObjectRaw {28public:29 CommandObjectSettingsSet(CommandInterpreter &interpreter)30 : CommandObjectRaw(interpreter, "settings set",31 "Set the value of the specified debugger setting.") {32 CommandArgumentEntry arg1;33 CommandArgumentEntry arg2;34 CommandArgumentData var_name_arg;35 CommandArgumentData value_arg;36 37 // Define the first (and only) variant of this arg.38 var_name_arg.arg_type = eArgTypeSettingVariableName;39 var_name_arg.arg_repetition = eArgRepeatPlain;40 41 // There is only one variant this argument could be; put it into the42 // argument entry.43 arg1.push_back(var_name_arg);44 45 // Define the first (and only) variant of this arg.46 value_arg.arg_type = eArgTypeValue;47 value_arg.arg_repetition = eArgRepeatPlain;48 49 // There is only one variant this argument could be; put it into the50 // argument entry.51 arg2.push_back(value_arg);52 53 // Push the data for the first argument into the m_arguments vector.54 m_arguments.push_back(arg1);55 m_arguments.push_back(arg2);56 57 SetHelpLong(58 "\nWhen setting a dictionary or array variable, you can set multiple entries \59at once by giving the values to the set command. For example:"60 R"(61 62(lldb) settings set target.run-args value1 value2 value363(lldb) settings set target.env-vars MYPATH=~/.:/usr/bin SOME_ENV_VAR=1234564 65(lldb) settings show target.run-args66 [0]: 'value1'67 [1]: 'value2'68 [3]: 'value3'69(lldb) settings show target.env-vars70 'MYPATH=~/.:/usr/bin'71 'SOME_ENV_VAR=12345'72 73)"74 "Warning: The 'set' command re-sets the entire array or dictionary. If you \75just want to add, remove or update individual values (or add something to \76the end), use one of the other settings sub-commands: append, replace, \77insert-before or insert-after.");78 }79 80 ~CommandObjectSettingsSet() override = default;81 82 // Overrides base class's behavior where WantsCompletion =83 // !WantsRawCommandString.84 bool WantsCompletion() override { return true; }85 86 Options *GetOptions() override { return &m_options; }87 88 class CommandOptions : public Options {89 public:90 CommandOptions() = default;91 92 ~CommandOptions() override = default;93 94 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,95 ExecutionContext *execution_context) override {96 Status error;97 const int short_option = m_getopt_table[option_idx].val;98 99 switch (short_option) {100 case 'f':101 m_force = true;102 break;103 case 'g':104 m_global = true;105 break;106 case 'e':107 m_exists = true;108 break;109 default:110 llvm_unreachable("Unimplemented option");111 }112 113 return error;114 }115 116 void OptionParsingStarting(ExecutionContext *execution_context) override {117 m_global = false;118 m_force = false;119 m_exists = false;120 }121 122 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {123 return llvm::ArrayRef(g_settings_set_options);124 }125 126 // Instance variables to hold the values for command options.127 bool m_global = false;128 bool m_force = false;129 bool m_exists = false;130 };131 132 void133 HandleArgumentCompletion(CompletionRequest &request,134 OptionElementVector &opt_element_vector) override {135 136 const size_t argc = request.GetParsedLine().GetArgumentCount();137 const char *arg = nullptr;138 size_t setting_var_idx;139 for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) {140 arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);141 if (arg && arg[0] != '-')142 break; // We found our setting variable name index143 }144 if (request.GetCursorIndex() == setting_var_idx) {145 // Attempting to complete setting variable name146 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(147 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,148 nullptr);149 return;150 }151 arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());152 153 if (!arg)154 return;155 156 // Complete option name157 if (arg[0] == '-')158 return;159 160 // Complete setting value161 const char *setting_var_name =162 request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);163 Status error;164 lldb::OptionValueSP value_sp(165 GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, error));166 if (!value_sp)167 return;168 value_sp->AutoComplete(m_interpreter, request);169 }170 171protected:172 void DoExecute(llvm::StringRef command,173 CommandReturnObject &result) override {174 Args cmd_args(command);175 176 // Process possible options.177 if (!ParseOptions(cmd_args, result))178 return;179 180 const size_t min_argc = m_options.m_force ? 1 : 2;181 const size_t argc = cmd_args.GetArgumentCount();182 183 if ((argc < min_argc) && (!m_options.m_global)) {184 result.AppendError("'settings set' takes more arguments");185 return;186 }187 188 const char *var_name = cmd_args.GetArgumentAtIndex(0);189 if ((var_name == nullptr) || (var_name[0] == '\0')) {190 result.AppendError(191 "'settings set' command requires a valid variable name");192 return;193 }194 195 // A missing value corresponds to clearing the setting when "force" is196 // specified.197 if (argc == 1 && m_options.m_force) {198 Status error(GetDebugger().SetPropertyValue(199 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));200 if (error.Fail()) {201 result.AppendError(error.AsCString());202 }203 return;204 }205 206 // Split the raw command into var_name and value pair.207 llvm::StringRef var_value(command);208 var_value = var_value.split(var_name).second.ltrim();209 210 Status error;211 if (m_options.m_global)212 error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign,213 var_name, var_value);214 215 if (error.Success()) {216 // FIXME this is the same issue as the one in commands script import217 // we could be setting target.load-script-from-symbol-file which would218 // cause Python scripts to be loaded, which could run LLDB commands (e.g.219 // settings set target.process.python-os-plugin-path) and cause a crash220 // if we did not clear the command's exe_ctx first221 ExecutionContext exe_ctx(m_exe_ctx);222 m_exe_ctx.Clear();223 error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign,224 var_name, var_value);225 }226 227 if (error.Fail() && !m_options.m_exists) {228 result.AppendError(error.AsCString());229 return;230 }231 232 result.SetStatus(eReturnStatusSuccessFinishResult);233 }234 235private:236 CommandOptions m_options;237};238 239// CommandObjectSettingsShow -- Show current values240#define LLDB_OPTIONS_settings_show241#include "CommandOptions.inc"242 243class CommandObjectSettingsShow : public CommandObjectParsed {244public:245 CommandObjectSettingsShow(CommandInterpreter &interpreter)246 : CommandObjectParsed(interpreter, "settings show",247 "Show matching debugger settings and their current "248 "values. Defaults to showing all settings.") {249 AddSimpleArgumentList(eArgTypeSettingVariableName, eArgRepeatOptional);250 }251 252 ~CommandObjectSettingsShow() override = default;253 254 Options *GetOptions() override { return &m_options; }255 256 class CommandOptions : public Options {257 public:258 ~CommandOptions() override = default;259 260 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,261 ExecutionContext *execution_context) override {262 const int short_option = m_getopt_table[option_idx].val;263 switch (short_option) {264 case 'd':265 m_include_defaults = true;266 break;267 default:268 llvm_unreachable("Unimplemented option");269 }270 return {};271 }272 273 void OptionParsingStarting(ExecutionContext *execution_context) override {274 m_include_defaults = false;275 }276 277 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {278 return g_settings_show_options;279 }280 281 bool m_include_defaults = false;282 };283 284protected:285 void DoExecute(Args &args, CommandReturnObject &result) override {286 result.SetStatus(eReturnStatusSuccessFinishResult);287 288 uint32_t dump_mask = OptionValue::eDumpGroupValue;289 if (m_options.m_include_defaults)290 dump_mask |= OptionValue::eDumpOptionDefaultValue;291 292 if (!args.empty()) {293 for (const auto &arg : args) {294 Status error(GetDebugger().DumpPropertyValue(295 &m_exe_ctx, result.GetOutputStream(), arg.ref(), dump_mask));296 if (error.Success()) {297 result.GetOutputStream().EOL();298 } else {299 result.AppendError(error.AsCString());300 }301 }302 } else {303 GetDebugger().DumpAllPropertyValues(&m_exe_ctx, result.GetOutputStream(),304 dump_mask);305 }306 }307 308private:309 CommandOptions m_options;310};311 312// CommandObjectSettingsWrite -- Write settings to file313#define LLDB_OPTIONS_settings_write314#include "CommandOptions.inc"315 316class CommandObjectSettingsWrite : public CommandObjectParsed {317public:318 CommandObjectSettingsWrite(CommandInterpreter &interpreter)319 : CommandObjectParsed(320 interpreter, "settings export",321 "Write matching debugger settings and their "322 "current values to a file that can be read in with "323 "\"settings read\". Defaults to writing all settings.",324 nullptr) {325 AddSimpleArgumentList(eArgTypeSettingVariableName, eArgRepeatOptional);326 }327 328 ~CommandObjectSettingsWrite() override = default;329 330 Options *GetOptions() override { return &m_options; }331 332 class CommandOptions : public Options {333 public:334 CommandOptions() = default;335 336 ~CommandOptions() override = default;337 338 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,339 ExecutionContext *execution_context) override {340 Status error;341 const int short_option = m_getopt_table[option_idx].val;342 343 switch (short_option) {344 case 'f':345 m_filename.assign(std::string(option_arg));346 break;347 case 'a':348 m_append = true;349 break;350 default:351 llvm_unreachable("Unimplemented option");352 }353 354 return error;355 }356 357 void OptionParsingStarting(ExecutionContext *execution_context) override {358 m_filename.clear();359 m_append = false;360 }361 362 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {363 return llvm::ArrayRef(g_settings_write_options);364 }365 366 // Instance variables to hold the values for command options.367 std::string m_filename;368 bool m_append = false;369 };370 371protected:372 void DoExecute(Args &args, CommandReturnObject &result) override {373 FileSpec file_spec(m_options.m_filename);374 FileSystem::Instance().Resolve(file_spec);375 std::string path(file_spec.GetPath());376 auto options = File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate;377 if (m_options.m_append)378 options |= File::eOpenOptionAppend;379 else380 options |= File::eOpenOptionTruncate;381 382 StreamFile out_file(path.c_str(), options,383 lldb::eFilePermissionsFileDefault);384 385 if (!out_file.GetFile().IsValid()) {386 result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());387 return;388 }389 390 // Exporting should not be context sensitive.391 ExecutionContext clean_ctx;392 393 if (args.empty()) {394 GetDebugger().DumpAllPropertyValues(&clean_ctx, out_file,395 OptionValue::eDumpGroupExport);396 return;397 }398 399 for (const auto &arg : args) {400 Status error(GetDebugger().DumpPropertyValue(401 &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport));402 if (!error.Success()) {403 result.AppendError(error.AsCString());404 }405 }406 }407 408private:409 CommandOptions m_options;410};411 412// CommandObjectSettingsRead -- Read settings from file413#define LLDB_OPTIONS_settings_read414#include "CommandOptions.inc"415 416class CommandObjectSettingsRead : public CommandObjectParsed {417public:418 CommandObjectSettingsRead(CommandInterpreter &interpreter)419 : CommandObjectParsed(420 interpreter, "settings read",421 "Read settings previously saved to a file with \"settings write\".",422 nullptr) {}423 424 ~CommandObjectSettingsRead() override = default;425 426 Options *GetOptions() override { return &m_options; }427 428 class CommandOptions : public Options {429 public:430 CommandOptions() = default;431 432 ~CommandOptions() override = default;433 434 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,435 ExecutionContext *execution_context) override {436 Status error;437 const int short_option = m_getopt_table[option_idx].val;438 439 switch (short_option) {440 case 'f':441 m_filename.assign(std::string(option_arg));442 break;443 default:444 llvm_unreachable("Unimplemented option");445 }446 447 return error;448 }449 450 void OptionParsingStarting(ExecutionContext *execution_context) override {451 m_filename.clear();452 }453 454 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {455 return llvm::ArrayRef(g_settings_read_options);456 }457 458 // Instance variables to hold the values for command options.459 std::string m_filename;460 };461 462protected:463 void DoExecute(Args &command, CommandReturnObject &result) override {464 FileSpec file(m_options.m_filename);465 FileSystem::Instance().Resolve(file);466 CommandInterpreterRunOptions options;467 options.SetAddToHistory(false);468 options.SetEchoCommands(false);469 options.SetPrintResults(true);470 options.SetPrintErrors(true);471 options.SetStopOnError(false);472 m_interpreter.HandleCommandsFromFile(file, options, result);473 }474 475private:476 CommandOptions m_options;477};478 479// CommandObjectSettingsList -- List settable variables480 481class CommandObjectSettingsList : public CommandObjectParsed {482public:483 CommandObjectSettingsList(CommandInterpreter &interpreter)484 : CommandObjectParsed(interpreter, "settings list",485 "List and describe matching debugger settings. "486 "Defaults to all listing all settings.",487 nullptr) {488 CommandArgumentEntry arg;489 CommandArgumentData var_name_arg;490 CommandArgumentData prefix_name_arg;491 492 // Define the first variant of this arg.493 var_name_arg.arg_type = eArgTypeSettingVariableName;494 var_name_arg.arg_repetition = eArgRepeatOptional;495 496 // Define the second variant of this arg.497 prefix_name_arg.arg_type = eArgTypeSettingPrefix;498 prefix_name_arg.arg_repetition = eArgRepeatOptional;499 500 arg.push_back(var_name_arg);501 arg.push_back(prefix_name_arg);502 503 // Push the data for the first argument into the m_arguments vector.504 m_arguments.push_back(arg);505 }506 507 ~CommandObjectSettingsList() override = default;508 509 void510 HandleArgumentCompletion(CompletionRequest &request,511 OptionElementVector &opt_element_vector) override {512 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(513 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,514 nullptr);515 }516 517protected:518 void DoExecute(Args &args, CommandReturnObject &result) override {519 result.SetStatus(eReturnStatusSuccessFinishResult);520 521 const size_t argc = args.GetArgumentCount();522 if (argc > 0) {523 const bool dump_qualified_name = true;524 525 for (const Args::ArgEntry &arg : args) {526 const char *property_path = arg.c_str();527 528 const Property *property =529 GetDebugger().GetValueProperties()->GetPropertyAtPath(530 &m_exe_ctx, property_path);531 532 if (property) {533 property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,534 dump_qualified_name);535 } else {536 result.AppendErrorWithFormat("invalid property path '%s'",537 property_path);538 }539 }540 } else {541 GetDebugger().DumpAllDescriptions(m_interpreter,542 result.GetOutputStream());543 }544 }545};546 547// CommandObjectSettingsRemove548 549class CommandObjectSettingsRemove : public CommandObjectRaw {550public:551 CommandObjectSettingsRemove(CommandInterpreter &interpreter)552 : CommandObjectRaw(interpreter, "settings remove",553 "Remove a value from a setting, specified by array "554 "index or dictionary key.") {555 CommandArgumentEntry arg1;556 CommandArgumentEntry arg2;557 CommandArgumentData var_name_arg;558 CommandArgumentData index_arg;559 CommandArgumentData key_arg;560 561 // Define the first (and only) variant of this arg.562 var_name_arg.arg_type = eArgTypeSettingVariableName;563 var_name_arg.arg_repetition = eArgRepeatPlain;564 565 // There is only one variant this argument could be; put it into the566 // argument entry.567 arg1.push_back(var_name_arg);568 569 // Define the first variant of this arg.570 index_arg.arg_type = eArgTypeSettingIndex;571 index_arg.arg_repetition = eArgRepeatPlain;572 573 // Define the second variant of this arg.574 key_arg.arg_type = eArgTypeSettingKey;575 key_arg.arg_repetition = eArgRepeatPlain;576 577 // Push both variants into this arg578 arg2.push_back(index_arg);579 arg2.push_back(key_arg);580 581 // Push the data for the first argument into the m_arguments vector.582 m_arguments.push_back(arg1);583 m_arguments.push_back(arg2);584 }585 586 ~CommandObjectSettingsRemove() override = default;587 588 bool WantsCompletion() override { return true; }589 590 void591 HandleArgumentCompletion(CompletionRequest &request,592 OptionElementVector &opt_element_vector) override {593 if (request.GetCursorIndex() < 2)594 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(595 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,596 nullptr);597 }598 599protected:600 void DoExecute(llvm::StringRef command,601 CommandReturnObject &result) override {602 result.SetStatus(eReturnStatusSuccessFinishNoResult);603 604 Args cmd_args(command);605 606 // Process possible options.607 if (!ParseOptions(cmd_args, result))608 return;609 610 const size_t argc = cmd_args.GetArgumentCount();611 if (argc == 0) {612 result.AppendError("'settings remove' takes an array or dictionary item, "613 "or an array followed by one or more indexes, or a "614 "dictionary followed by one or more key names to "615 "remove");616 return;617 }618 619 const char *var_name = cmd_args.GetArgumentAtIndex(0);620 if ((var_name == nullptr) || (var_name[0] == '\0')) {621 result.AppendError(622 "'settings remove' command requires a valid variable name");623 return;624 }625 626 // Split the raw command into var_name and value pair.627 llvm::StringRef var_value(command);628 var_value = var_value.split(var_name).second.trim();629 630 Status error(GetDebugger().SetPropertyValue(631 &m_exe_ctx, eVarSetOperationRemove, var_name, var_value));632 if (error.Fail()) {633 result.AppendError(error.AsCString());634 }635 }636};637 638// CommandObjectSettingsReplace639 640class CommandObjectSettingsReplace : public CommandObjectRaw {641public:642 CommandObjectSettingsReplace(CommandInterpreter &interpreter)643 : CommandObjectRaw(interpreter, "settings replace",644 "Replace the debugger setting value specified by "645 "array index or dictionary key.") {646 CommandArgumentEntry arg1;647 CommandArgumentEntry arg2;648 CommandArgumentEntry arg3;649 CommandArgumentData var_name_arg;650 CommandArgumentData index_arg;651 CommandArgumentData key_arg;652 CommandArgumentData value_arg;653 654 // Define the first (and only) variant of this arg.655 var_name_arg.arg_type = eArgTypeSettingVariableName;656 var_name_arg.arg_repetition = eArgRepeatPlain;657 658 // There is only one variant this argument could be; put it into the659 // argument entry.660 arg1.push_back(var_name_arg);661 662 // Define the first (variant of this arg.663 index_arg.arg_type = eArgTypeSettingIndex;664 index_arg.arg_repetition = eArgRepeatPlain;665 666 // Define the second (variant of this arg.667 key_arg.arg_type = eArgTypeSettingKey;668 key_arg.arg_repetition = eArgRepeatPlain;669 670 // Put both variants into this arg671 arg2.push_back(index_arg);672 arg2.push_back(key_arg);673 674 // Define the first (and only) variant of this arg.675 value_arg.arg_type = eArgTypeValue;676 value_arg.arg_repetition = eArgRepeatPlain;677 678 // There is only one variant this argument could be; put it into the679 // argument entry.680 arg3.push_back(value_arg);681 682 // Push the data for the first argument into the m_arguments vector.683 m_arguments.push_back(arg1);684 m_arguments.push_back(arg2);685 m_arguments.push_back(arg3);686 }687 688 ~CommandObjectSettingsReplace() override = default;689 690 // Overrides base class's behavior where WantsCompletion =691 // !WantsRawCommandString.692 bool WantsCompletion() override { return true; }693 694 void695 HandleArgumentCompletion(CompletionRequest &request,696 OptionElementVector &opt_element_vector) override {697 // Attempting to complete variable name698 if (request.GetCursorIndex() < 2)699 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(700 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,701 nullptr);702 }703 704protected:705 void DoExecute(llvm::StringRef command,706 CommandReturnObject &result) override {707 result.SetStatus(eReturnStatusSuccessFinishNoResult);708 709 Args cmd_args(command);710 const char *var_name = cmd_args.GetArgumentAtIndex(0);711 if ((var_name == nullptr) || (var_name[0] == '\0')) {712 result.AppendError("'settings replace' command requires a valid variable "713 "name; No value supplied");714 return;715 }716 717 // Split the raw command into var_name, index_value, and value triple.718 llvm::StringRef var_value(command);719 var_value = var_value.split(var_name).second.trim();720 721 Status error(GetDebugger().SetPropertyValue(722 &m_exe_ctx, eVarSetOperationReplace, var_name, var_value));723 if (error.Fail()) {724 result.AppendError(error.AsCString());725 } else {726 result.SetStatus(eReturnStatusSuccessFinishNoResult);727 }728 }729};730 731// CommandObjectSettingsInsertBefore732 733class CommandObjectSettingsInsertBefore : public CommandObjectRaw {734public:735 CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)736 : CommandObjectRaw(interpreter, "settings insert-before",737 "Insert one or more values into an debugger array "738 "setting immediately before the specified element "739 "index.") {740 CommandArgumentEntry arg1;741 CommandArgumentEntry arg2;742 CommandArgumentEntry arg3;743 CommandArgumentData var_name_arg;744 CommandArgumentData index_arg;745 CommandArgumentData value_arg;746 747 // Define the first (and only) variant of this arg.748 var_name_arg.arg_type = eArgTypeSettingVariableName;749 var_name_arg.arg_repetition = eArgRepeatPlain;750 751 // There is only one variant this argument could be; put it into the752 // argument entry.753 arg1.push_back(var_name_arg);754 755 // Define the first (variant of this arg.756 index_arg.arg_type = eArgTypeSettingIndex;757 index_arg.arg_repetition = eArgRepeatPlain;758 759 // There is only one variant this argument could be; put it into the760 // argument entry.761 arg2.push_back(index_arg);762 763 // Define the first (and only) variant of this arg.764 value_arg.arg_type = eArgTypeValue;765 value_arg.arg_repetition = eArgRepeatPlain;766 767 // There is only one variant this argument could be; put it into the768 // argument entry.769 arg3.push_back(value_arg);770 771 // Push the data for the first argument into the m_arguments vector.772 m_arguments.push_back(arg1);773 m_arguments.push_back(arg2);774 m_arguments.push_back(arg3);775 }776 777 ~CommandObjectSettingsInsertBefore() override = default;778 779 // Overrides base class's behavior where WantsCompletion =780 // !WantsRawCommandString.781 bool WantsCompletion() override { return true; }782 783 void784 HandleArgumentCompletion(CompletionRequest &request,785 OptionElementVector &opt_element_vector) override {786 // Attempting to complete variable name787 if (request.GetCursorIndex() < 2)788 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(789 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,790 nullptr);791 }792 793protected:794 void DoExecute(llvm::StringRef command,795 CommandReturnObject &result) override {796 result.SetStatus(eReturnStatusSuccessFinishNoResult);797 798 Args cmd_args(command);799 const size_t argc = cmd_args.GetArgumentCount();800 801 if (argc < 3) {802 result.AppendError("'settings insert-before' takes more arguments");803 return;804 }805 806 const char *var_name = cmd_args.GetArgumentAtIndex(0);807 if ((var_name == nullptr) || (var_name[0] == '\0')) {808 result.AppendError("'settings insert-before' command requires a valid "809 "variable name; No value supplied");810 return;811 }812 813 // Split the raw command into var_name, index_value, and value triple.814 llvm::StringRef var_value(command);815 var_value = var_value.split(var_name).second.trim();816 817 Status error(GetDebugger().SetPropertyValue(818 &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));819 if (error.Fail()) {820 result.AppendError(error.AsCString());821 }822 }823};824 825// CommandObjectSettingInsertAfter826 827class CommandObjectSettingsInsertAfter : public CommandObjectRaw {828public:829 CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)830 : CommandObjectRaw(interpreter, "settings insert-after",831 "Insert one or more values into a debugger array "832 "settings after the specified element index.") {833 CommandArgumentEntry arg1;834 CommandArgumentEntry arg2;835 CommandArgumentEntry arg3;836 CommandArgumentData var_name_arg;837 CommandArgumentData index_arg;838 CommandArgumentData value_arg;839 840 // Define the first (and only) variant of this arg.841 var_name_arg.arg_type = eArgTypeSettingVariableName;842 var_name_arg.arg_repetition = eArgRepeatPlain;843 844 // There is only one variant this argument could be; put it into the845 // argument entry.846 arg1.push_back(var_name_arg);847 848 // Define the first (variant of this arg.849 index_arg.arg_type = eArgTypeSettingIndex;850 index_arg.arg_repetition = eArgRepeatPlain;851 852 // There is only one variant this argument could be; put it into the853 // argument entry.854 arg2.push_back(index_arg);855 856 // Define the first (and only) variant of this arg.857 value_arg.arg_type = eArgTypeValue;858 value_arg.arg_repetition = eArgRepeatPlain;859 860 // There is only one variant this argument could be; put it into the861 // argument entry.862 arg3.push_back(value_arg);863 864 // Push the data for the first argument into the m_arguments vector.865 m_arguments.push_back(arg1);866 m_arguments.push_back(arg2);867 m_arguments.push_back(arg3);868 }869 870 ~CommandObjectSettingsInsertAfter() override = default;871 872 // Overrides base class's behavior where WantsCompletion =873 // !WantsRawCommandString.874 bool WantsCompletion() override { return true; }875 876 void877 HandleArgumentCompletion(CompletionRequest &request,878 OptionElementVector &opt_element_vector) override {879 // Attempting to complete variable name880 if (request.GetCursorIndex() < 2)881 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(882 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,883 nullptr);884 }885 886protected:887 void DoExecute(llvm::StringRef command,888 CommandReturnObject &result) override {889 result.SetStatus(eReturnStatusSuccessFinishNoResult);890 891 Args cmd_args(command);892 const size_t argc = cmd_args.GetArgumentCount();893 894 if (argc < 3) {895 result.AppendError("'settings insert-after' takes more arguments");896 return;897 }898 899 const char *var_name = cmd_args.GetArgumentAtIndex(0);900 if ((var_name == nullptr) || (var_name[0] == '\0')) {901 result.AppendError("'settings insert-after' command requires a valid "902 "variable name; No value supplied");903 return;904 }905 906 // Split the raw command into var_name, index_value, and value triple.907 llvm::StringRef var_value(command);908 var_value = var_value.split(var_name).second.trim();909 910 Status error(GetDebugger().SetPropertyValue(911 &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));912 if (error.Fail()) {913 result.AppendError(error.AsCString());914 }915 }916};917 918// CommandObjectSettingsAppend919 920class CommandObjectSettingsAppend : public CommandObjectRaw {921public:922 CommandObjectSettingsAppend(CommandInterpreter &interpreter)923 : CommandObjectRaw(interpreter, "settings append",924 "Append one or more values to a debugger array, "925 "dictionary, or string setting.") {926 CommandArgumentEntry arg1;927 CommandArgumentEntry arg2;928 CommandArgumentData var_name_arg;929 CommandArgumentData value_arg;930 931 // Define the first (and only) variant of this arg.932 var_name_arg.arg_type = eArgTypeSettingVariableName;933 var_name_arg.arg_repetition = eArgRepeatPlain;934 935 // There is only one variant this argument could be; put it into the936 // argument entry.937 arg1.push_back(var_name_arg);938 939 // Define the first (and only) variant of this arg.940 value_arg.arg_type = eArgTypeValue;941 value_arg.arg_repetition = eArgRepeatPlain;942 943 // There is only one variant this argument could be; put it into the944 // argument entry.945 arg2.push_back(value_arg);946 947 // Push the data for the first argument into the m_arguments vector.948 m_arguments.push_back(arg1);949 m_arguments.push_back(arg2);950 }951 952 ~CommandObjectSettingsAppend() override = default;953 954 // Overrides base class's behavior where WantsCompletion =955 // !WantsRawCommandString.956 bool WantsCompletion() override { return true; }957 958 void959 HandleArgumentCompletion(CompletionRequest &request,960 OptionElementVector &opt_element_vector) override {961 // Attempting to complete variable name962 if (request.GetCursorIndex() < 2)963 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(964 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,965 nullptr);966 }967 968protected:969 void DoExecute(llvm::StringRef command,970 CommandReturnObject &result) override {971 result.SetStatus(eReturnStatusSuccessFinishNoResult);972 Args cmd_args(command);973 const size_t argc = cmd_args.GetArgumentCount();974 975 if (argc < 2) {976 result.AppendError("'settings append' takes more arguments");977 return;978 }979 980 const char *var_name = cmd_args.GetArgumentAtIndex(0);981 if ((var_name == nullptr) || (var_name[0] == '\0')) {982 result.AppendError("'settings append' command requires a valid variable "983 "name; No value supplied");984 return;985 }986 987 // Do not perform cmd_args.Shift() since StringRef is manipulating the raw988 // character string later on.989 990 // Split the raw command into var_name and value pair.991 llvm::StringRef var_value(command);992 var_value = var_value.split(var_name).second.trim();993 994 Status error(GetDebugger().SetPropertyValue(995 &m_exe_ctx, eVarSetOperationAppend, var_name, var_value));996 if (error.Fail()) {997 result.AppendError(error.AsCString());998 }999 }1000};1001 1002// CommandObjectSettingsClear1003#define LLDB_OPTIONS_settings_clear1004#include "CommandOptions.inc"1005 1006class CommandObjectSettingsClear : public CommandObjectParsed {1007public:1008 CommandObjectSettingsClear(CommandInterpreter &interpreter)1009 : CommandObjectParsed(1010 interpreter, "settings clear",1011 "Clear a debugger setting array, dictionary, or string. "1012 "If '-a' option is specified, it clears all settings.", nullptr) {1013 AddSimpleArgumentList(eArgTypeSettingVariableName);1014 }1015 1016 ~CommandObjectSettingsClear() override = default;1017 1018 void1019 HandleArgumentCompletion(CompletionRequest &request,1020 OptionElementVector &opt_element_vector) override {1021 // Attempting to complete variable name1022 if (request.GetCursorIndex() < 2)1023 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(1024 GetCommandInterpreter(), lldb::eSettingsNameCompletion, request,1025 nullptr);1026 }1027 1028 Options *GetOptions() override { return &m_options; }1029 1030 class CommandOptions : public Options {1031 public:1032 CommandOptions() = default;1033 1034 ~CommandOptions() override = default;1035 1036 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,1037 ExecutionContext *execution_context) override {1038 const int short_option = m_getopt_table[option_idx].val;1039 switch (short_option) {1040 case 'a':1041 m_clear_all = true;1042 break;1043 default:1044 llvm_unreachable("Unimplemented option");1045 }1046 return Status();1047 }1048 1049 void OptionParsingStarting(ExecutionContext *execution_context) override {1050 m_clear_all = false;1051 }1052 1053 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {1054 return llvm::ArrayRef(g_settings_clear_options);1055 }1056 1057 bool m_clear_all = false;1058 };1059 1060protected:1061 void DoExecute(Args &command, CommandReturnObject &result) override {1062 result.SetStatus(eReturnStatusSuccessFinishNoResult);1063 const size_t argc = command.GetArgumentCount();1064 1065 if (m_options.m_clear_all) {1066 if (argc != 0) {1067 result.AppendError("'settings clear --all' doesn't take any arguments");1068 return;1069 }1070 GetDebugger().GetValueProperties()->Clear();1071 return;1072 }1073 1074 if (argc != 1) {1075 result.AppendError("'settings clear' takes exactly one argument");1076 return;1077 }1078 1079 const char *var_name = command.GetArgumentAtIndex(0);1080 if ((var_name == nullptr) || (var_name[0] == '\0')) {1081 result.AppendError("'settings clear' command requires a valid variable "1082 "name; No value supplied");1083 return;1084 }1085 1086 Status error(GetDebugger().SetPropertyValue(1087 &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));1088 if (error.Fail()) {1089 result.AppendError(error.AsCString());1090 }1091 }1092 1093 private:1094 CommandOptions m_options;1095};1096 1097// CommandObjectMultiwordSettings1098 1099CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(1100 CommandInterpreter &interpreter)1101 : CommandObjectMultiword(interpreter, "settings",1102 "Commands for managing LLDB settings.",1103 "settings <subcommand> [<command-options>]") {1104 LoadSubCommand("set",1105 CommandObjectSP(new CommandObjectSettingsSet(interpreter)));1106 LoadSubCommand("show",1107 CommandObjectSP(new CommandObjectSettingsShow(interpreter)));1108 LoadSubCommand("list",1109 CommandObjectSP(new CommandObjectSettingsList(interpreter)));1110 LoadSubCommand("remove",1111 CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));1112 LoadSubCommand("replace", CommandObjectSP(1113 new CommandObjectSettingsReplace(interpreter)));1114 LoadSubCommand(1115 "insert-before",1116 CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));1117 LoadSubCommand(1118 "insert-after",1119 CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));1120 LoadSubCommand("append",1121 CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));1122 LoadSubCommand("clear",1123 CommandObjectSP(new CommandObjectSettingsClear(interpreter)));1124 LoadSubCommand("write",1125 CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));1126 LoadSubCommand("read",1127 CommandObjectSP(new CommandObjectSettingsRead(interpreter)));1128}1129 1130CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;1131