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