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