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