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