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