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