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