xref: /llvm-project/lldb/source/Commands/CommandObjectSettings.cpp (revision 36de94cf54efbad967a9a0fa41329a8b59bc35c4)
1 //===-- CommandObjectSettings.cpp -----------------------------------------===//
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(std::string(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(std::string(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     CommandInterpreterRunOptions options;
473     options.SetAddToHistory(false);
474     options.SetEchoCommands(false);
475     options.SetPrintResults(true);
476     options.SetPrintErrors(true);
477     options.SetStopOnError(false);
478     m_interpreter.HandleCommandsFromFile(file, options, result);
479     return result.Succeeded();
480   }
481 
482 private:
483   CommandOptions m_options;
484 };
485 
486 // CommandObjectSettingsList -- List settable variables
487 
488 class CommandObjectSettingsList : public CommandObjectParsed {
489 public:
490   CommandObjectSettingsList(CommandInterpreter &interpreter)
491       : CommandObjectParsed(interpreter, "settings list",
492                             "List and describe matching debugger settings.  "
493                             "Defaults to all listing all settings.",
494                             nullptr) {
495     CommandArgumentEntry arg;
496     CommandArgumentData var_name_arg;
497     CommandArgumentData prefix_name_arg;
498 
499     // Define the first variant of this arg.
500     var_name_arg.arg_type = eArgTypeSettingVariableName;
501     var_name_arg.arg_repetition = eArgRepeatOptional;
502 
503     // Define the second variant of this arg.
504     prefix_name_arg.arg_type = eArgTypeSettingPrefix;
505     prefix_name_arg.arg_repetition = eArgRepeatOptional;
506 
507     arg.push_back(var_name_arg);
508     arg.push_back(prefix_name_arg);
509 
510     // Push the data for the first argument into the m_arguments vector.
511     m_arguments.push_back(arg);
512   }
513 
514   ~CommandObjectSettingsList() override = default;
515 
516   void
517   HandleArgumentCompletion(CompletionRequest &request,
518                            OptionElementVector &opt_element_vector) override {
519     CommandCompletions::InvokeCommonCompletionCallbacks(
520         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
521         request, nullptr);
522   }
523 
524 protected:
525   bool DoExecute(Args &args, CommandReturnObject &result) override {
526     result.SetStatus(eReturnStatusSuccessFinishResult);
527 
528     const bool will_modify = false;
529     const size_t argc = args.GetArgumentCount();
530     if (argc > 0) {
531       const bool dump_qualified_name = true;
532 
533       for (const Args::ArgEntry &arg : args) {
534         const char *property_path = arg.c_str();
535 
536         const Property *property =
537             GetDebugger().GetValueProperties()->GetPropertyAtPath(
538                 &m_exe_ctx, will_modify, property_path);
539 
540         if (property) {
541           property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
542                                     dump_qualified_name);
543         } else {
544           result.AppendErrorWithFormat("invalid property path '%s'",
545                                        property_path);
546           result.SetStatus(eReturnStatusFailed);
547         }
548       }
549     } else {
550       GetDebugger().DumpAllDescriptions(m_interpreter,
551                                         result.GetOutputStream());
552     }
553 
554     return result.Succeeded();
555   }
556 };
557 
558 // CommandObjectSettingsRemove
559 
560 class CommandObjectSettingsRemove : public CommandObjectRaw {
561 public:
562   CommandObjectSettingsRemove(CommandInterpreter &interpreter)
563       : CommandObjectRaw(interpreter, "settings remove",
564                          "Remove a value from a setting, specified by array "
565                          "index or dictionary key.") {
566     CommandArgumentEntry arg1;
567     CommandArgumentEntry arg2;
568     CommandArgumentData var_name_arg;
569     CommandArgumentData index_arg;
570     CommandArgumentData key_arg;
571 
572     // Define the first (and only) variant of this arg.
573     var_name_arg.arg_type = eArgTypeSettingVariableName;
574     var_name_arg.arg_repetition = eArgRepeatPlain;
575 
576     // There is only one variant this argument could be; put it into the
577     // argument entry.
578     arg1.push_back(var_name_arg);
579 
580     // Define the first variant of this arg.
581     index_arg.arg_type = eArgTypeSettingIndex;
582     index_arg.arg_repetition = eArgRepeatPlain;
583 
584     // Define the second variant of this arg.
585     key_arg.arg_type = eArgTypeSettingKey;
586     key_arg.arg_repetition = eArgRepeatPlain;
587 
588     // Push both variants into this arg
589     arg2.push_back(index_arg);
590     arg2.push_back(key_arg);
591 
592     // Push the data for the first argument into the m_arguments vector.
593     m_arguments.push_back(arg1);
594     m_arguments.push_back(arg2);
595   }
596 
597   ~CommandObjectSettingsRemove() override = default;
598 
599   bool WantsCompletion() override { return true; }
600 
601   void
602   HandleArgumentCompletion(CompletionRequest &request,
603                            OptionElementVector &opt_element_vector) override {
604     if (request.GetCursorIndex() < 2)
605       CommandCompletions::InvokeCommonCompletionCallbacks(
606           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
607           request, nullptr);
608   }
609 
610 protected:
611   bool DoExecute(llvm::StringRef command,
612                  CommandReturnObject &result) override {
613     result.SetStatus(eReturnStatusSuccessFinishNoResult);
614 
615     Args cmd_args(command);
616 
617     // Process possible options.
618     if (!ParseOptions(cmd_args, result))
619       return false;
620 
621     const size_t argc = cmd_args.GetArgumentCount();
622     if (argc == 0) {
623       result.AppendError("'settings remove' takes an array or dictionary item, "
624                          "or an array followed by one or more indexes, or a "
625                          "dictionary followed by one or more key names to "
626                          "remove");
627       result.SetStatus(eReturnStatusFailed);
628       return false;
629     }
630 
631     const char *var_name = cmd_args.GetArgumentAtIndex(0);
632     if ((var_name == nullptr) || (var_name[0] == '\0')) {
633       result.AppendError(
634           "'settings remove' command requires a valid variable name");
635       result.SetStatus(eReturnStatusFailed);
636       return false;
637     }
638 
639     // Split the raw command into var_name and value pair.
640     llvm::StringRef var_value(command);
641     var_value = var_value.split(var_name).second.trim();
642 
643     Status error(GetDebugger().SetPropertyValue(
644         &m_exe_ctx, eVarSetOperationRemove, var_name, var_value));
645     if (error.Fail()) {
646       result.AppendError(error.AsCString());
647       result.SetStatus(eReturnStatusFailed);
648       return false;
649     }
650 
651     return result.Succeeded();
652   }
653 };
654 
655 // CommandObjectSettingsReplace
656 
657 class CommandObjectSettingsReplace : public CommandObjectRaw {
658 public:
659   CommandObjectSettingsReplace(CommandInterpreter &interpreter)
660       : CommandObjectRaw(interpreter, "settings replace",
661                          "Replace the debugger setting value specified by "
662                          "array index or dictionary key.") {
663     CommandArgumentEntry arg1;
664     CommandArgumentEntry arg2;
665     CommandArgumentEntry arg3;
666     CommandArgumentData var_name_arg;
667     CommandArgumentData index_arg;
668     CommandArgumentData key_arg;
669     CommandArgumentData value_arg;
670 
671     // Define the first (and only) variant of this arg.
672     var_name_arg.arg_type = eArgTypeSettingVariableName;
673     var_name_arg.arg_repetition = eArgRepeatPlain;
674 
675     // There is only one variant this argument could be; put it into the
676     // argument entry.
677     arg1.push_back(var_name_arg);
678 
679     // Define the first (variant of this arg.
680     index_arg.arg_type = eArgTypeSettingIndex;
681     index_arg.arg_repetition = eArgRepeatPlain;
682 
683     // Define the second (variant of this arg.
684     key_arg.arg_type = eArgTypeSettingKey;
685     key_arg.arg_repetition = eArgRepeatPlain;
686 
687     // Put both variants into this arg
688     arg2.push_back(index_arg);
689     arg2.push_back(key_arg);
690 
691     // Define the first (and only) variant of this arg.
692     value_arg.arg_type = eArgTypeValue;
693     value_arg.arg_repetition = eArgRepeatPlain;
694 
695     // There is only one variant this argument could be; put it into the
696     // argument entry.
697     arg3.push_back(value_arg);
698 
699     // Push the data for the first argument into the m_arguments vector.
700     m_arguments.push_back(arg1);
701     m_arguments.push_back(arg2);
702     m_arguments.push_back(arg3);
703   }
704 
705   ~CommandObjectSettingsReplace() override = default;
706 
707   // Overrides base class's behavior where WantsCompletion =
708   // !WantsRawCommandString.
709   bool WantsCompletion() override { return true; }
710 
711   void
712   HandleArgumentCompletion(CompletionRequest &request,
713                            OptionElementVector &opt_element_vector) override {
714     // Attempting to complete variable name
715     if (request.GetCursorIndex() < 2)
716       CommandCompletions::InvokeCommonCompletionCallbacks(
717           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
718           request, nullptr);
719   }
720 
721 protected:
722   bool DoExecute(llvm::StringRef command,
723                  CommandReturnObject &result) override {
724     result.SetStatus(eReturnStatusSuccessFinishNoResult);
725 
726     Args cmd_args(command);
727     const char *var_name = cmd_args.GetArgumentAtIndex(0);
728     if ((var_name == nullptr) || (var_name[0] == '\0')) {
729       result.AppendError("'settings replace' command requires a valid variable "
730                          "name; No value supplied");
731       result.SetStatus(eReturnStatusFailed);
732       return false;
733     }
734 
735     // Split the raw command into var_name, index_value, and value triple.
736     llvm::StringRef var_value(command);
737     var_value = var_value.split(var_name).second.trim();
738 
739     Status error(GetDebugger().SetPropertyValue(
740         &m_exe_ctx, eVarSetOperationReplace, var_name, var_value));
741     if (error.Fail()) {
742       result.AppendError(error.AsCString());
743       result.SetStatus(eReturnStatusFailed);
744       return false;
745     } else {
746       result.SetStatus(eReturnStatusSuccessFinishNoResult);
747     }
748 
749     return result.Succeeded();
750   }
751 };
752 
753 // CommandObjectSettingsInsertBefore
754 
755 class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
756 public:
757   CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
758       : CommandObjectRaw(interpreter, "settings insert-before",
759                          "Insert one or more values into an debugger array "
760                          "setting immediately before the specified element "
761                          "index.") {
762     CommandArgumentEntry arg1;
763     CommandArgumentEntry arg2;
764     CommandArgumentEntry arg3;
765     CommandArgumentData var_name_arg;
766     CommandArgumentData index_arg;
767     CommandArgumentData value_arg;
768 
769     // Define the first (and only) variant of this arg.
770     var_name_arg.arg_type = eArgTypeSettingVariableName;
771     var_name_arg.arg_repetition = eArgRepeatPlain;
772 
773     // There is only one variant this argument could be; put it into the
774     // argument entry.
775     arg1.push_back(var_name_arg);
776 
777     // Define the first (variant of this arg.
778     index_arg.arg_type = eArgTypeSettingIndex;
779     index_arg.arg_repetition = eArgRepeatPlain;
780 
781     // There is only one variant this argument could be; put it into the
782     // argument entry.
783     arg2.push_back(index_arg);
784 
785     // Define the first (and only) variant of this arg.
786     value_arg.arg_type = eArgTypeValue;
787     value_arg.arg_repetition = eArgRepeatPlain;
788 
789     // There is only one variant this argument could be; put it into the
790     // argument entry.
791     arg3.push_back(value_arg);
792 
793     // Push the data for the first argument into the m_arguments vector.
794     m_arguments.push_back(arg1);
795     m_arguments.push_back(arg2);
796     m_arguments.push_back(arg3);
797   }
798 
799   ~CommandObjectSettingsInsertBefore() override = default;
800 
801   // Overrides base class's behavior where WantsCompletion =
802   // !WantsRawCommandString.
803   bool WantsCompletion() override { return true; }
804 
805   void
806   HandleArgumentCompletion(CompletionRequest &request,
807                            OptionElementVector &opt_element_vector) override {
808     // Attempting to complete variable name
809     if (request.GetCursorIndex() < 2)
810       CommandCompletions::InvokeCommonCompletionCallbacks(
811           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
812           request, nullptr);
813   }
814 
815 protected:
816   bool DoExecute(llvm::StringRef command,
817                  CommandReturnObject &result) override {
818     result.SetStatus(eReturnStatusSuccessFinishNoResult);
819 
820     Args cmd_args(command);
821     const size_t argc = cmd_args.GetArgumentCount();
822 
823     if (argc < 3) {
824       result.AppendError("'settings insert-before' takes more arguments");
825       result.SetStatus(eReturnStatusFailed);
826       return false;
827     }
828 
829     const char *var_name = cmd_args.GetArgumentAtIndex(0);
830     if ((var_name == nullptr) || (var_name[0] == '\0')) {
831       result.AppendError("'settings insert-before' command requires a valid "
832                          "variable name; No value supplied");
833       result.SetStatus(eReturnStatusFailed);
834       return false;
835     }
836 
837     // Split the raw command into var_name, index_value, and value triple.
838     llvm::StringRef var_value(command);
839     var_value = var_value.split(var_name).second.trim();
840 
841     Status error(GetDebugger().SetPropertyValue(
842         &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value));
843     if (error.Fail()) {
844       result.AppendError(error.AsCString());
845       result.SetStatus(eReturnStatusFailed);
846       return false;
847     }
848 
849     return result.Succeeded();
850   }
851 };
852 
853 // CommandObjectSettingInsertAfter
854 
855 class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
856 public:
857   CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
858       : CommandObjectRaw(interpreter, "settings insert-after",
859                          "Insert one or more values into a debugger array "
860                          "settings after the specified element index.") {
861     CommandArgumentEntry arg1;
862     CommandArgumentEntry arg2;
863     CommandArgumentEntry arg3;
864     CommandArgumentData var_name_arg;
865     CommandArgumentData index_arg;
866     CommandArgumentData value_arg;
867 
868     // Define the first (and only) variant of this arg.
869     var_name_arg.arg_type = eArgTypeSettingVariableName;
870     var_name_arg.arg_repetition = eArgRepeatPlain;
871 
872     // There is only one variant this argument could be; put it into the
873     // argument entry.
874     arg1.push_back(var_name_arg);
875 
876     // Define the first (variant of this arg.
877     index_arg.arg_type = eArgTypeSettingIndex;
878     index_arg.arg_repetition = eArgRepeatPlain;
879 
880     // There is only one variant this argument could be; put it into the
881     // argument entry.
882     arg2.push_back(index_arg);
883 
884     // Define the first (and only) variant of this arg.
885     value_arg.arg_type = eArgTypeValue;
886     value_arg.arg_repetition = eArgRepeatPlain;
887 
888     // There is only one variant this argument could be; put it into the
889     // argument entry.
890     arg3.push_back(value_arg);
891 
892     // Push the data for the first argument into the m_arguments vector.
893     m_arguments.push_back(arg1);
894     m_arguments.push_back(arg2);
895     m_arguments.push_back(arg3);
896   }
897 
898   ~CommandObjectSettingsInsertAfter() override = default;
899 
900   // Overrides base class's behavior where WantsCompletion =
901   // !WantsRawCommandString.
902   bool WantsCompletion() override { return true; }
903 
904   void
905   HandleArgumentCompletion(CompletionRequest &request,
906                            OptionElementVector &opt_element_vector) override {
907     // Attempting to complete variable name
908     if (request.GetCursorIndex() < 2)
909       CommandCompletions::InvokeCommonCompletionCallbacks(
910           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
911           request, nullptr);
912   }
913 
914 protected:
915   bool DoExecute(llvm::StringRef command,
916                  CommandReturnObject &result) override {
917     result.SetStatus(eReturnStatusSuccessFinishNoResult);
918 
919     Args cmd_args(command);
920     const size_t argc = cmd_args.GetArgumentCount();
921 
922     if (argc < 3) {
923       result.AppendError("'settings insert-after' takes more arguments");
924       result.SetStatus(eReturnStatusFailed);
925       return false;
926     }
927 
928     const char *var_name = cmd_args.GetArgumentAtIndex(0);
929     if ((var_name == nullptr) || (var_name[0] == '\0')) {
930       result.AppendError("'settings insert-after' command requires a valid "
931                          "variable name; No value supplied");
932       result.SetStatus(eReturnStatusFailed);
933       return false;
934     }
935 
936     // Split the raw command into var_name, index_value, and value triple.
937     llvm::StringRef var_value(command);
938     var_value = var_value.split(var_name).second.trim();
939 
940     Status error(GetDebugger().SetPropertyValue(
941         &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value));
942     if (error.Fail()) {
943       result.AppendError(error.AsCString());
944       result.SetStatus(eReturnStatusFailed);
945       return false;
946     }
947 
948     return result.Succeeded();
949   }
950 };
951 
952 // CommandObjectSettingsAppend
953 
954 class CommandObjectSettingsAppend : public CommandObjectRaw {
955 public:
956   CommandObjectSettingsAppend(CommandInterpreter &interpreter)
957       : CommandObjectRaw(interpreter, "settings append",
958                          "Append one or more values to a debugger array, "
959                          "dictionary, or string setting.") {
960     CommandArgumentEntry arg1;
961     CommandArgumentEntry arg2;
962     CommandArgumentData var_name_arg;
963     CommandArgumentData value_arg;
964 
965     // Define the first (and only) variant of this arg.
966     var_name_arg.arg_type = eArgTypeSettingVariableName;
967     var_name_arg.arg_repetition = eArgRepeatPlain;
968 
969     // There is only one variant this argument could be; put it into the
970     // argument entry.
971     arg1.push_back(var_name_arg);
972 
973     // Define the first (and only) variant of this arg.
974     value_arg.arg_type = eArgTypeValue;
975     value_arg.arg_repetition = eArgRepeatPlain;
976 
977     // There is only one variant this argument could be; put it into the
978     // argument entry.
979     arg2.push_back(value_arg);
980 
981     // Push the data for the first argument into the m_arguments vector.
982     m_arguments.push_back(arg1);
983     m_arguments.push_back(arg2);
984   }
985 
986   ~CommandObjectSettingsAppend() override = default;
987 
988   // Overrides base class's behavior where WantsCompletion =
989   // !WantsRawCommandString.
990   bool WantsCompletion() override { return true; }
991 
992   void
993   HandleArgumentCompletion(CompletionRequest &request,
994                            OptionElementVector &opt_element_vector) override {
995     // Attempting to complete variable name
996     if (request.GetCursorIndex() < 2)
997       CommandCompletions::InvokeCommonCompletionCallbacks(
998           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
999           request, nullptr);
1000   }
1001 
1002 protected:
1003   bool DoExecute(llvm::StringRef command,
1004                  CommandReturnObject &result) override {
1005     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1006     Args cmd_args(command);
1007     const size_t argc = cmd_args.GetArgumentCount();
1008 
1009     if (argc < 2) {
1010       result.AppendError("'settings append' takes more arguments");
1011       result.SetStatus(eReturnStatusFailed);
1012       return false;
1013     }
1014 
1015     const char *var_name = cmd_args.GetArgumentAtIndex(0);
1016     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1017       result.AppendError("'settings append' command requires a valid variable "
1018                          "name; No value supplied");
1019       result.SetStatus(eReturnStatusFailed);
1020       return false;
1021     }
1022 
1023     // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
1024     // character string later on.
1025 
1026     // Split the raw command into var_name and value pair.
1027     llvm::StringRef var_value(command);
1028     var_value = var_value.split(var_name).second.trim();
1029 
1030     Status error(GetDebugger().SetPropertyValue(
1031         &m_exe_ctx, eVarSetOperationAppend, var_name, var_value));
1032     if (error.Fail()) {
1033       result.AppendError(error.AsCString());
1034       result.SetStatus(eReturnStatusFailed);
1035       return false;
1036     }
1037 
1038     return result.Succeeded();
1039   }
1040 };
1041 
1042 // CommandObjectSettingsClear
1043 #define LLDB_OPTIONS_settings_clear
1044 #include "CommandOptions.inc"
1045 
1046 class CommandObjectSettingsClear : public CommandObjectParsed {
1047 public:
1048   CommandObjectSettingsClear(CommandInterpreter &interpreter)
1049       : CommandObjectParsed(
1050             interpreter, "settings clear",
1051             "Clear a debugger setting array, dictionary, or string. "
1052             "If '-a' option is specified, it clears all settings.", 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    Options *GetOptions() override { return &m_options; }
1081 
1082   class CommandOptions : public Options {
1083   public:
1084     CommandOptions() = default;
1085 
1086     ~CommandOptions() override = default;
1087 
1088     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1089                           ExecutionContext *execution_context) override {
1090       const int short_option = m_getopt_table[option_idx].val;
1091       switch (short_option) {
1092       case 'a':
1093         m_clear_all = true;
1094         break;
1095       default:
1096         llvm_unreachable("Unimplemented option");
1097       }
1098       return Status();
1099     }
1100 
1101     void OptionParsingStarting(ExecutionContext *execution_context) override {
1102       m_clear_all = false;
1103     }
1104 
1105     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1106       return llvm::makeArrayRef(g_settings_clear_options);
1107     }
1108 
1109     bool m_clear_all = false;
1110   };
1111 
1112 protected:
1113   bool DoExecute(Args &command, CommandReturnObject &result) override {
1114     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1115     const size_t argc = command.GetArgumentCount();
1116 
1117     if (m_options.m_clear_all) {
1118       if (argc != 0) {
1119         result.AppendError("'settings clear --all' doesn't take any arguments");
1120         result.SetStatus(eReturnStatusFailed);
1121         return false;
1122       }
1123       GetDebugger().GetValueProperties()->Clear();
1124       return result.Succeeded();
1125     }
1126 
1127     if (argc != 1) {
1128       result.AppendError("'settings clear' takes exactly one argument");
1129       result.SetStatus(eReturnStatusFailed);
1130       return false;
1131     }
1132 
1133     const char *var_name = command.GetArgumentAtIndex(0);
1134     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1135       result.AppendError("'settings clear' command requires a valid variable "
1136                          "name; No value supplied");
1137       result.SetStatus(eReturnStatusFailed);
1138       return false;
1139     }
1140 
1141     Status error(GetDebugger().SetPropertyValue(
1142         &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
1143     if (error.Fail()) {
1144       result.AppendError(error.AsCString());
1145       result.SetStatus(eReturnStatusFailed);
1146       return false;
1147     }
1148 
1149     return result.Succeeded();
1150   }
1151 
1152   private:
1153     CommandOptions m_options;
1154 };
1155 
1156 // CommandObjectMultiwordSettings
1157 
1158 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
1159     CommandInterpreter &interpreter)
1160     : CommandObjectMultiword(interpreter, "settings",
1161                              "Commands for managing LLDB settings.",
1162                              "settings <subcommand> [<command-options>]") {
1163   LoadSubCommand("set",
1164                  CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
1165   LoadSubCommand("show",
1166                  CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
1167   LoadSubCommand("list",
1168                  CommandObjectSP(new CommandObjectSettingsList(interpreter)));
1169   LoadSubCommand("remove",
1170                  CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
1171   LoadSubCommand("replace", CommandObjectSP(
1172                                 new CommandObjectSettingsReplace(interpreter)));
1173   LoadSubCommand(
1174       "insert-before",
1175       CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
1176   LoadSubCommand(
1177       "insert-after",
1178       CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
1179   LoadSubCommand("append",
1180                  CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
1181   LoadSubCommand("clear",
1182                  CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
1183   LoadSubCommand("write",
1184                  CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
1185   LoadSubCommand("read",
1186                  CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
1187 }
1188 
1189 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1190