xref: /llvm-project/lldb/source/Commands/CommandObjectSettings.cpp (revision 05097246f352eca76207c9ebb08656c88bdf751a)
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/Host/OptionParser.h"
19 #include "lldb/Interpreter/CommandCompletions.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Interpreter/OptionValueProperties.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 //-------------------------------------------------------------------------
28 // CommandObjectSettingsSet
29 //-------------------------------------------------------------------------
30 
31 static OptionDefinition g_settings_set_options[] = {
32     // clang-format off
33   { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value." }
34     // clang-format on
35 };
36 
37 class CommandObjectSettingsSet : public CommandObjectRaw {
38 public:
39   CommandObjectSettingsSet(CommandInterpreter &interpreter)
40       : CommandObjectRaw(interpreter, "settings set",
41                          "Set the value of the specified debugger setting."),
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     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
106                           ExecutionContext *execution_context) override {
107       Status 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 = 0; 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           Status 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     Status 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 Python scripts to be loaded, which could run LLDB commands (e.g.
224       // settings set target.process.python-os-plugin-path) and cause a crash
225       // if we did not clear the command's exe_ctx first
226       ExecutionContext exe_ctx(m_exe_ctx);
227       m_exe_ctx.Clear();
228       error = m_interpreter.GetDebugger().SetPropertyValue(
229           &exe_ctx, eVarSetOperationAssign, var_name, var_value_cstr);
230     }
231 
232     if (error.Fail()) {
233       result.AppendError(error.AsCString());
234       result.SetStatus(eReturnStatusFailed);
235       return false;
236     } else {
237       result.SetStatus(eReturnStatusSuccessFinishResult);
238     }
239 
240     return result.Succeeded();
241   }
242 
243 private:
244   CommandOptions m_options;
245 };
246 
247 //-------------------------------------------------------------------------
248 // CommandObjectSettingsShow -- Show current values
249 //-------------------------------------------------------------------------
250 
251 class CommandObjectSettingsShow : public CommandObjectParsed {
252 public:
253   CommandObjectSettingsShow(CommandInterpreter &interpreter)
254       : CommandObjectParsed(interpreter, "settings show",
255                             "Show matching debugger settings and their current "
256                             "values.  Defaults to showing all settings.",
257                             nullptr) {
258     CommandArgumentEntry arg1;
259     CommandArgumentData var_name_arg;
260 
261     // Define the first (and only) variant of this arg.
262     var_name_arg.arg_type = eArgTypeSettingVariableName;
263     var_name_arg.arg_repetition = eArgRepeatOptional;
264 
265     // There is only one variant this argument could be; put it into the
266     // argument entry.
267     arg1.push_back(var_name_arg);
268 
269     // Push the data for the first argument into the m_arguments vector.
270     m_arguments.push_back(arg1);
271   }
272 
273   ~CommandObjectSettingsShow() override = default;
274 
275   int HandleArgumentCompletion(Args &input, int &cursor_index,
276                                int &cursor_char_position,
277                                OptionElementVector &opt_element_vector,
278                                int match_start_point, int max_return_elements,
279                                bool &word_complete,
280                                StringList &matches) override {
281     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
282                                cursor_char_position);
283 
284     CommandCompletions::InvokeCommonCompletionCallbacks(
285         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
286         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
287         word_complete, matches);
288     return matches.GetSize();
289   }
290 
291 protected:
292   bool DoExecute(Args &args, CommandReturnObject &result) override {
293     result.SetStatus(eReturnStatusSuccessFinishResult);
294 
295     if (!args.empty()) {
296       for (const auto &arg : args) {
297         Status error(m_interpreter.GetDebugger().DumpPropertyValue(
298             &m_exe_ctx, result.GetOutputStream(), arg.ref,
299             OptionValue::eDumpGroupValue));
300         if (error.Success()) {
301           result.GetOutputStream().EOL();
302         } else {
303           result.AppendError(error.AsCString());
304           result.SetStatus(eReturnStatusFailed);
305         }
306       }
307     } else {
308       m_interpreter.GetDebugger().DumpAllPropertyValues(
309           &m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
310     }
311 
312     return result.Succeeded();
313   }
314 };
315 
316 //-------------------------------------------------------------------------
317 // CommandObjectSettingsList -- List settable variables
318 //-------------------------------------------------------------------------
319 
320 class CommandObjectSettingsList : public CommandObjectParsed {
321 public:
322   CommandObjectSettingsList(CommandInterpreter &interpreter)
323       : CommandObjectParsed(interpreter, "settings list",
324                             "List and describe matching debugger settings.  "
325                             "Defaults to all listing all settings.",
326                             nullptr) {
327     CommandArgumentEntry arg;
328     CommandArgumentData var_name_arg;
329     CommandArgumentData prefix_name_arg;
330 
331     // Define the first variant of this arg.
332     var_name_arg.arg_type = eArgTypeSettingVariableName;
333     var_name_arg.arg_repetition = eArgRepeatOptional;
334 
335     // Define the second variant of this arg.
336     prefix_name_arg.arg_type = eArgTypeSettingPrefix;
337     prefix_name_arg.arg_repetition = eArgRepeatOptional;
338 
339     arg.push_back(var_name_arg);
340     arg.push_back(prefix_name_arg);
341 
342     // Push the data for the first argument into the m_arguments vector.
343     m_arguments.push_back(arg);
344   }
345 
346   ~CommandObjectSettingsList() override = default;
347 
348   int HandleArgumentCompletion(Args &input, int &cursor_index,
349                                int &cursor_char_position,
350                                OptionElementVector &opt_element_vector,
351                                int match_start_point, int max_return_elements,
352                                bool &word_complete,
353                                StringList &matches) override {
354     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
355                                cursor_char_position);
356 
357     CommandCompletions::InvokeCommonCompletionCallbacks(
358         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
359         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
360         word_complete, matches);
361     return matches.GetSize();
362   }
363 
364 protected:
365   bool DoExecute(Args &args, CommandReturnObject &result) override {
366     result.SetStatus(eReturnStatusSuccessFinishResult);
367 
368     const bool will_modify = false;
369     const size_t argc = args.GetArgumentCount();
370     if (argc > 0) {
371       const bool dump_qualified_name = true;
372 
373       // TODO: Convert to StringRef based enumeration.  Requires converting
374       // GetPropertyAtPath first.
375       for (size_t i = 0; i < argc; ++i) {
376         const char *property_path = args.GetArgumentAtIndex(i);
377 
378         const Property *property =
379             m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath(
380                 &m_exe_ctx, will_modify, property_path);
381 
382         if (property) {
383           property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
384                                     dump_qualified_name);
385         } else {
386           result.AppendErrorWithFormat("invalid property path '%s'",
387                                        property_path);
388           result.SetStatus(eReturnStatusFailed);
389         }
390       }
391     } else {
392       m_interpreter.GetDebugger().DumpAllDescriptions(m_interpreter,
393                                                       result.GetOutputStream());
394     }
395 
396     return result.Succeeded();
397   }
398 };
399 
400 //-------------------------------------------------------------------------
401 // CommandObjectSettingsRemove
402 //-------------------------------------------------------------------------
403 
404 class CommandObjectSettingsRemove : public CommandObjectRaw {
405 public:
406   CommandObjectSettingsRemove(CommandInterpreter &interpreter)
407       : CommandObjectRaw(interpreter, "settings remove",
408                          "Remove a value from a setting, specified by array "
409                          "index or dictionary key.") {
410     CommandArgumentEntry arg1;
411     CommandArgumentEntry arg2;
412     CommandArgumentData var_name_arg;
413     CommandArgumentData index_arg;
414     CommandArgumentData key_arg;
415 
416     // Define the first (and only) variant of this arg.
417     var_name_arg.arg_type = eArgTypeSettingVariableName;
418     var_name_arg.arg_repetition = eArgRepeatPlain;
419 
420     // There is only one variant this argument could be; put it into the
421     // argument entry.
422     arg1.push_back(var_name_arg);
423 
424     // Define the first variant of this arg.
425     index_arg.arg_type = eArgTypeSettingIndex;
426     index_arg.arg_repetition = eArgRepeatPlain;
427 
428     // Define the second variant of this arg.
429     key_arg.arg_type = eArgTypeSettingKey;
430     key_arg.arg_repetition = eArgRepeatPlain;
431 
432     // Push both variants into this arg
433     arg2.push_back(index_arg);
434     arg2.push_back(key_arg);
435 
436     // Push the data for the first argument into the m_arguments vector.
437     m_arguments.push_back(arg1);
438     m_arguments.push_back(arg2);
439   }
440 
441   ~CommandObjectSettingsRemove() override = default;
442 
443   int HandleArgumentCompletion(Args &input, int &cursor_index,
444                                int &cursor_char_position,
445                                OptionElementVector &opt_element_vector,
446                                int match_start_point, int max_return_elements,
447                                bool &word_complete,
448                                StringList &matches) override {
449     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
450                                cursor_char_position);
451 
452     // Attempting to complete variable name
453     if (cursor_index < 2)
454       CommandCompletions::InvokeCommonCompletionCallbacks(
455           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
456           completion_str.c_str(), match_start_point, max_return_elements,
457           nullptr, word_complete, matches);
458     return matches.GetSize();
459   }
460 
461 protected:
462   bool DoExecute(const char *command, CommandReturnObject &result) override {
463     result.SetStatus(eReturnStatusSuccessFinishNoResult);
464 
465     Args cmd_args(command);
466 
467     // Process possible options.
468     if (!ParseOptions(cmd_args, result))
469       return false;
470 
471     const size_t argc = cmd_args.GetArgumentCount();
472     if (argc == 0) {
473       result.AppendError("'settings set' takes an array or dictionary item, or "
474                          "an array followed by one or more indexes, or a "
475                          "dictionary followed by one or more key names to "
476                          "remove");
477       result.SetStatus(eReturnStatusFailed);
478       return false;
479     }
480 
481     const char *var_name = cmd_args.GetArgumentAtIndex(0);
482     if ((var_name == nullptr) || (var_name[0] == '\0')) {
483       result.AppendError(
484           "'settings set' command requires a valid variable name");
485       result.SetStatus(eReturnStatusFailed);
486       return false;
487     }
488 
489     // Split the raw command into var_name and value pair.
490     llvm::StringRef raw_str(command);
491     std::string var_value_string = raw_str.split(var_name).second.str();
492     const char *var_value_cstr =
493         Args::StripSpaces(var_value_string, true, true, false);
494 
495     Status error(m_interpreter.GetDebugger().SetPropertyValue(
496         &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr));
497     if (error.Fail()) {
498       result.AppendError(error.AsCString());
499       result.SetStatus(eReturnStatusFailed);
500       return false;
501     }
502 
503     return result.Succeeded();
504   }
505 };
506 
507 //-------------------------------------------------------------------------
508 // CommandObjectSettingsReplace
509 //-------------------------------------------------------------------------
510 
511 class CommandObjectSettingsReplace : public CommandObjectRaw {
512 public:
513   CommandObjectSettingsReplace(CommandInterpreter &interpreter)
514       : CommandObjectRaw(interpreter, "settings replace",
515                          "Replace the debugger setting value specified by "
516                          "array index or dictionary key.") {
517     CommandArgumentEntry arg1;
518     CommandArgumentEntry arg2;
519     CommandArgumentEntry arg3;
520     CommandArgumentData var_name_arg;
521     CommandArgumentData index_arg;
522     CommandArgumentData key_arg;
523     CommandArgumentData value_arg;
524 
525     // Define the first (and only) variant of this arg.
526     var_name_arg.arg_type = eArgTypeSettingVariableName;
527     var_name_arg.arg_repetition = eArgRepeatPlain;
528 
529     // There is only one variant this argument could be; put it into the
530     // argument entry.
531     arg1.push_back(var_name_arg);
532 
533     // Define the first (variant of this arg.
534     index_arg.arg_type = eArgTypeSettingIndex;
535     index_arg.arg_repetition = eArgRepeatPlain;
536 
537     // Define the second (variant of this arg.
538     key_arg.arg_type = eArgTypeSettingKey;
539     key_arg.arg_repetition = eArgRepeatPlain;
540 
541     // Put both variants into this arg
542     arg2.push_back(index_arg);
543     arg2.push_back(key_arg);
544 
545     // Define the first (and only) variant of this arg.
546     value_arg.arg_type = eArgTypeValue;
547     value_arg.arg_repetition = eArgRepeatPlain;
548 
549     // There is only one variant this argument could be; put it into the
550     // argument entry.
551     arg3.push_back(value_arg);
552 
553     // Push the data for the first argument into the m_arguments vector.
554     m_arguments.push_back(arg1);
555     m_arguments.push_back(arg2);
556     m_arguments.push_back(arg3);
557   }
558 
559   ~CommandObjectSettingsReplace() override = default;
560 
561   // Overrides base class's behavior where WantsCompletion =
562   // !WantsRawCommandString.
563   bool WantsCompletion() override { return true; }
564 
565   int HandleArgumentCompletion(Args &input, int &cursor_index,
566                                int &cursor_char_position,
567                                OptionElementVector &opt_element_vector,
568                                int match_start_point, int max_return_elements,
569                                bool &word_complete,
570                                StringList &matches) override {
571     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
572                                cursor_char_position);
573 
574     // Attempting to complete variable name
575     if (cursor_index < 2)
576       CommandCompletions::InvokeCommonCompletionCallbacks(
577           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
578           completion_str.c_str(), match_start_point, max_return_elements,
579           nullptr, word_complete, matches);
580 
581     return matches.GetSize();
582   }
583 
584 protected:
585   bool DoExecute(const char *command, CommandReturnObject &result) override {
586     result.SetStatus(eReturnStatusSuccessFinishNoResult);
587 
588     Args cmd_args(command);
589     const char *var_name = cmd_args.GetArgumentAtIndex(0);
590     if ((var_name == nullptr) || (var_name[0] == '\0')) {
591       result.AppendError("'settings replace' command requires a valid variable "
592                          "name; No value supplied");
593       result.SetStatus(eReturnStatusFailed);
594       return false;
595     }
596 
597     // Split the raw command into var_name, index_value, and value triple.
598     llvm::StringRef raw_str(command);
599     std::string var_value_string = raw_str.split(var_name).second.str();
600     const char *var_value_cstr =
601         Args::StripSpaces(var_value_string, true, true, false);
602 
603     Status error(m_interpreter.GetDebugger().SetPropertyValue(
604         &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr));
605     if (error.Fail()) {
606       result.AppendError(error.AsCString());
607       result.SetStatus(eReturnStatusFailed);
608       return false;
609     } else {
610       result.SetStatus(eReturnStatusSuccessFinishNoResult);
611     }
612 
613     return result.Succeeded();
614   }
615 };
616 
617 //-------------------------------------------------------------------------
618 // CommandObjectSettingsInsertBefore
619 //-------------------------------------------------------------------------
620 
621 class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
622 public:
623   CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
624       : CommandObjectRaw(interpreter, "settings insert-before",
625                          "Insert one or more values into an debugger array "
626                          "setting immediately before the specified element "
627                          "index.") {
628     CommandArgumentEntry arg1;
629     CommandArgumentEntry arg2;
630     CommandArgumentEntry arg3;
631     CommandArgumentData var_name_arg;
632     CommandArgumentData index_arg;
633     CommandArgumentData value_arg;
634 
635     // Define the first (and only) variant of this arg.
636     var_name_arg.arg_type = eArgTypeSettingVariableName;
637     var_name_arg.arg_repetition = eArgRepeatPlain;
638 
639     // There is only one variant this argument could be; put it into the
640     // argument entry.
641     arg1.push_back(var_name_arg);
642 
643     // Define the first (variant of this arg.
644     index_arg.arg_type = eArgTypeSettingIndex;
645     index_arg.arg_repetition = eArgRepeatPlain;
646 
647     // There is only one variant this argument could be; put it into the
648     // argument entry.
649     arg2.push_back(index_arg);
650 
651     // Define the first (and only) variant of this arg.
652     value_arg.arg_type = eArgTypeValue;
653     value_arg.arg_repetition = eArgRepeatPlain;
654 
655     // There is only one variant this argument could be; put it into the
656     // argument entry.
657     arg3.push_back(value_arg);
658 
659     // Push the data for the first argument into the m_arguments vector.
660     m_arguments.push_back(arg1);
661     m_arguments.push_back(arg2);
662     m_arguments.push_back(arg3);
663   }
664 
665   ~CommandObjectSettingsInsertBefore() override = default;
666 
667   // Overrides base class's behavior where WantsCompletion =
668   // !WantsRawCommandString.
669   bool WantsCompletion() override { return true; }
670 
671   int HandleArgumentCompletion(Args &input, int &cursor_index,
672                                int &cursor_char_position,
673                                OptionElementVector &opt_element_vector,
674                                int match_start_point, int max_return_elements,
675                                bool &word_complete,
676                                StringList &matches) override {
677     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
678                                cursor_char_position);
679 
680     // Attempting to complete variable name
681     if (cursor_index < 2)
682       CommandCompletions::InvokeCommonCompletionCallbacks(
683           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
684           completion_str.c_str(), match_start_point, max_return_elements,
685           nullptr, word_complete, matches);
686 
687     return matches.GetSize();
688   }
689 
690 protected:
691   bool DoExecute(const char *command, CommandReturnObject &result) override {
692     result.SetStatus(eReturnStatusSuccessFinishNoResult);
693 
694     Args cmd_args(command);
695     const size_t argc = cmd_args.GetArgumentCount();
696 
697     if (argc < 3) {
698       result.AppendError("'settings insert-before' takes more arguments");
699       result.SetStatus(eReturnStatusFailed);
700       return false;
701     }
702 
703     const char *var_name = cmd_args.GetArgumentAtIndex(0);
704     if ((var_name == nullptr) || (var_name[0] == '\0')) {
705       result.AppendError("'settings insert-before' command requires a valid "
706                          "variable name; No value supplied");
707       result.SetStatus(eReturnStatusFailed);
708       return false;
709     }
710 
711     // Split the raw command into var_name, index_value, and value triple.
712     llvm::StringRef raw_str(command);
713     std::string var_value_string = raw_str.split(var_name).second.str();
714     const char *var_value_cstr =
715         Args::StripSpaces(var_value_string, true, true, false);
716 
717     Status error(m_interpreter.GetDebugger().SetPropertyValue(
718         &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr));
719     if (error.Fail()) {
720       result.AppendError(error.AsCString());
721       result.SetStatus(eReturnStatusFailed);
722       return false;
723     }
724 
725     return result.Succeeded();
726   }
727 };
728 
729 //-------------------------------------------------------------------------
730 // CommandObjectSettingInsertAfter
731 //-------------------------------------------------------------------------
732 
733 class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
734 public:
735   CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
736       : CommandObjectRaw(interpreter, "settings insert-after",
737                          "Insert one or more values into a debugger array "
738                          "settings after the specified element index.") {
739     CommandArgumentEntry arg1;
740     CommandArgumentEntry arg2;
741     CommandArgumentEntry arg3;
742     CommandArgumentData var_name_arg;
743     CommandArgumentData index_arg;
744     CommandArgumentData value_arg;
745 
746     // Define the first (and only) variant of this arg.
747     var_name_arg.arg_type = eArgTypeSettingVariableName;
748     var_name_arg.arg_repetition = eArgRepeatPlain;
749 
750     // There is only one variant this argument could be; put it into the
751     // argument entry.
752     arg1.push_back(var_name_arg);
753 
754     // Define the first (variant of this arg.
755     index_arg.arg_type = eArgTypeSettingIndex;
756     index_arg.arg_repetition = eArgRepeatPlain;
757 
758     // There is only one variant this argument could be; put it into the
759     // argument entry.
760     arg2.push_back(index_arg);
761 
762     // Define the first (and only) variant of this arg.
763     value_arg.arg_type = eArgTypeValue;
764     value_arg.arg_repetition = eArgRepeatPlain;
765 
766     // There is only one variant this argument could be; put it into the
767     // argument entry.
768     arg3.push_back(value_arg);
769 
770     // Push the data for the first argument into the m_arguments vector.
771     m_arguments.push_back(arg1);
772     m_arguments.push_back(arg2);
773     m_arguments.push_back(arg3);
774   }
775 
776   ~CommandObjectSettingsInsertAfter() override = default;
777 
778   // Overrides base class's behavior where WantsCompletion =
779   // !WantsRawCommandString.
780   bool WantsCompletion() override { return true; }
781 
782   int HandleArgumentCompletion(Args &input, int &cursor_index,
783                                int &cursor_char_position,
784                                OptionElementVector &opt_element_vector,
785                                int match_start_point, int max_return_elements,
786                                bool &word_complete,
787                                StringList &matches) override {
788     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
789                                cursor_char_position);
790 
791     // Attempting to complete variable name
792     if (cursor_index < 2)
793       CommandCompletions::InvokeCommonCompletionCallbacks(
794           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
795           completion_str.c_str(), match_start_point, max_return_elements,
796           nullptr, word_complete, matches);
797 
798     return matches.GetSize();
799   }
800 
801 protected:
802   bool DoExecute(const char *command, CommandReturnObject &result) override {
803     result.SetStatus(eReturnStatusSuccessFinishNoResult);
804 
805     Args cmd_args(command);
806     const size_t argc = cmd_args.GetArgumentCount();
807 
808     if (argc < 3) {
809       result.AppendError("'settings insert-after' takes more arguments");
810       result.SetStatus(eReturnStatusFailed);
811       return false;
812     }
813 
814     const char *var_name = cmd_args.GetArgumentAtIndex(0);
815     if ((var_name == nullptr) || (var_name[0] == '\0')) {
816       result.AppendError("'settings insert-after' command requires a valid "
817                          "variable name; No value supplied");
818       result.SetStatus(eReturnStatusFailed);
819       return false;
820     }
821 
822     // Split the raw command into var_name, index_value, and value triple.
823     llvm::StringRef raw_str(command);
824     std::string var_value_string = raw_str.split(var_name).second.str();
825     const char *var_value_cstr =
826         Args::StripSpaces(var_value_string, true, true, false);
827 
828     Status error(m_interpreter.GetDebugger().SetPropertyValue(
829         &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr));
830     if (error.Fail()) {
831       result.AppendError(error.AsCString());
832       result.SetStatus(eReturnStatusFailed);
833       return false;
834     }
835 
836     return result.Succeeded();
837   }
838 };
839 
840 //-------------------------------------------------------------------------
841 // CommandObjectSettingsAppend
842 //-------------------------------------------------------------------------
843 
844 class CommandObjectSettingsAppend : public CommandObjectRaw {
845 public:
846   CommandObjectSettingsAppend(CommandInterpreter &interpreter)
847       : CommandObjectRaw(interpreter, "settings append",
848                          "Append one or more values to a debugger array, "
849                          "dictionary, or string setting.") {
850     CommandArgumentEntry arg1;
851     CommandArgumentEntry arg2;
852     CommandArgumentData var_name_arg;
853     CommandArgumentData value_arg;
854 
855     // Define the first (and only) variant of this arg.
856     var_name_arg.arg_type = eArgTypeSettingVariableName;
857     var_name_arg.arg_repetition = eArgRepeatPlain;
858 
859     // There is only one variant this argument could be; put it into the
860     // argument entry.
861     arg1.push_back(var_name_arg);
862 
863     // Define the first (and only) variant of this arg.
864     value_arg.arg_type = eArgTypeValue;
865     value_arg.arg_repetition = eArgRepeatPlain;
866 
867     // There is only one variant this argument could be; put it into the
868     // argument entry.
869     arg2.push_back(value_arg);
870 
871     // Push the data for the first argument into the m_arguments vector.
872     m_arguments.push_back(arg1);
873     m_arguments.push_back(arg2);
874   }
875 
876   ~CommandObjectSettingsAppend() override = default;
877 
878   // Overrides base class's behavior where WantsCompletion =
879   // !WantsRawCommandString.
880   bool WantsCompletion() override { return true; }
881 
882   int HandleArgumentCompletion(Args &input, int &cursor_index,
883                                int &cursor_char_position,
884                                OptionElementVector &opt_element_vector,
885                                int match_start_point, int max_return_elements,
886                                bool &word_complete,
887                                StringList &matches) override {
888     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
889                                cursor_char_position);
890 
891     // Attempting to complete variable name
892     if (cursor_index < 2)
893       CommandCompletions::InvokeCommonCompletionCallbacks(
894           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
895           completion_str.c_str(), match_start_point, max_return_elements,
896           nullptr, word_complete, matches);
897 
898     return matches.GetSize();
899   }
900 
901 protected:
902   bool DoExecute(const char *command, CommandReturnObject &result) override {
903     result.SetStatus(eReturnStatusSuccessFinishNoResult);
904     Args cmd_args(command);
905     const size_t argc = cmd_args.GetArgumentCount();
906 
907     if (argc < 2) {
908       result.AppendError("'settings append' takes more arguments");
909       result.SetStatus(eReturnStatusFailed);
910       return false;
911     }
912 
913     const char *var_name = cmd_args.GetArgumentAtIndex(0);
914     if ((var_name == nullptr) || (var_name[0] == '\0')) {
915       result.AppendError("'settings append' command requires a valid variable "
916                          "name; No value supplied");
917       result.SetStatus(eReturnStatusFailed);
918       return false;
919     }
920 
921     // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
922     // character string later on.
923 
924     // Split the raw command into var_name and value pair.
925     llvm::StringRef raw_str(command);
926     std::string var_value_string = raw_str.split(var_name).second.str();
927     const char *var_value_cstr =
928         Args::StripSpaces(var_value_string, true, true, false);
929 
930     Status error(m_interpreter.GetDebugger().SetPropertyValue(
931         &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr));
932     if (error.Fail()) {
933       result.AppendError(error.AsCString());
934       result.SetStatus(eReturnStatusFailed);
935       return false;
936     }
937 
938     return result.Succeeded();
939   }
940 };
941 
942 //-------------------------------------------------------------------------
943 // CommandObjectSettingsClear
944 //-------------------------------------------------------------------------
945 
946 class CommandObjectSettingsClear : public CommandObjectParsed {
947 public:
948   CommandObjectSettingsClear(CommandInterpreter &interpreter)
949       : CommandObjectParsed(
950             interpreter, "settings clear",
951             "Clear a debugger setting array, dictionary, or string.", nullptr) {
952     CommandArgumentEntry arg;
953     CommandArgumentData var_name_arg;
954 
955     // Define the first (and only) variant of this arg.
956     var_name_arg.arg_type = eArgTypeSettingVariableName;
957     var_name_arg.arg_repetition = eArgRepeatPlain;
958 
959     // There is only one variant this argument could be; put it into the
960     // argument entry.
961     arg.push_back(var_name_arg);
962 
963     // Push the data for the first argument into the m_arguments vector.
964     m_arguments.push_back(arg);
965   }
966 
967   ~CommandObjectSettingsClear() override = default;
968 
969   int HandleArgumentCompletion(Args &input, int &cursor_index,
970                                int &cursor_char_position,
971                                OptionElementVector &opt_element_vector,
972                                int match_start_point, int max_return_elements,
973                                bool &word_complete,
974                                StringList &matches) override {
975     std::string completion_str(input.GetArgumentAtIndex(cursor_index),
976                                cursor_char_position);
977 
978     // Attempting to complete variable name
979     if (cursor_index < 2)
980       CommandCompletions::InvokeCommonCompletionCallbacks(
981           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
982           completion_str.c_str(), match_start_point, max_return_elements,
983           nullptr, word_complete, matches);
984 
985     return matches.GetSize();
986   }
987 
988 protected:
989   bool DoExecute(Args &command, CommandReturnObject &result) override {
990     result.SetStatus(eReturnStatusSuccessFinishNoResult);
991     const size_t argc = command.GetArgumentCount();
992 
993     if (argc != 1) {
994       result.AppendError("'settings clear' takes exactly one argument");
995       result.SetStatus(eReturnStatusFailed);
996       return false;
997     }
998 
999     const char *var_name = command.GetArgumentAtIndex(0);
1000     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1001       result.AppendError("'settings clear' command requires a valid variable "
1002                          "name; No value supplied");
1003       result.SetStatus(eReturnStatusFailed);
1004       return false;
1005     }
1006 
1007     Status error(m_interpreter.GetDebugger().SetPropertyValue(
1008         &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
1009     if (error.Fail()) {
1010       result.AppendError(error.AsCString());
1011       result.SetStatus(eReturnStatusFailed);
1012       return false;
1013     }
1014 
1015     return result.Succeeded();
1016   }
1017 };
1018 
1019 //-------------------------------------------------------------------------
1020 // CommandObjectMultiwordSettings
1021 //-------------------------------------------------------------------------
1022 
1023 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
1024     CommandInterpreter &interpreter)
1025     : CommandObjectMultiword(interpreter, "settings",
1026                              "Commands for managing LLDB settings.",
1027                              "settings <subcommand> [<command-options>]") {
1028   LoadSubCommand("set",
1029                  CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
1030   LoadSubCommand("show",
1031                  CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
1032   LoadSubCommand("list",
1033                  CommandObjectSP(new CommandObjectSettingsList(interpreter)));
1034   LoadSubCommand("remove",
1035                  CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
1036   LoadSubCommand("replace", CommandObjectSP(
1037                                 new CommandObjectSettingsReplace(interpreter)));
1038   LoadSubCommand(
1039       "insert-before",
1040       CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
1041   LoadSubCommand(
1042       "insert-after",
1043       CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
1044   LoadSubCommand("append",
1045                  CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
1046   LoadSubCommand("clear",
1047                  CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
1048 }
1049 
1050 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1051