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