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