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