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