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