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