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