brintos

brintos / llvm-project-archived public Read only

0
0
Text · 36.5 KiB · 126f57c Raw
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