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