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