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