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