xref: /llvm-project/lldb/source/Commands/CommandObjectSettings.cpp (revision 8f3be7a32b631e9ba584872c1f0dde8fd8536c07)
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     FileSpec file_spec(m_options.m_filename);
407     FileSystem::Instance().Resolve(file_spec);
408     std::string path(file_spec.GetPath());
409     uint32_t options = File::OpenOptions::eOpenOptionWrite |
410                        File::OpenOptions::eOpenOptionCanCreate;
411     if (m_options.m_append)
412       options |= File::OpenOptions::eOpenOptionAppend;
413     else
414       options |= File::OpenOptions::eOpenOptionTruncate;
415 
416     StreamFile out_file(path.c_str(), options,
417                         lldb::eFilePermissionsFileDefault);
418 
419     if (!out_file.GetFile().IsValid()) {
420       result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
421       result.SetStatus(eReturnStatusFailed);
422       return false;
423     }
424 
425     // Exporting should not be context sensitive.
426     ExecutionContext clean_ctx;
427 
428     if (args.empty()) {
429       m_interpreter.GetDebugger().DumpAllPropertyValues(
430           &clean_ctx, out_file, OptionValue::eDumpGroupExport);
431       return result.Succeeded();
432     }
433 
434     for (const auto &arg : args) {
435       Status error(m_interpreter.GetDebugger().DumpPropertyValue(
436           &clean_ctx, out_file, arg.ref, OptionValue::eDumpGroupExport));
437       if (!error.Success()) {
438         result.AppendError(error.AsCString());
439         result.SetStatus(eReturnStatusFailed);
440       }
441     }
442 
443     return result.Succeeded();
444   }
445 
446 private:
447   CommandOptions m_options;
448 };
449 
450 //-------------------------------------------------------------------------
451 // CommandObjectSettingsRead -- Read settings from file
452 //-------------------------------------------------------------------------
453 
454 static constexpr OptionDefinition g_settings_read_options[] = {
455     // clang-format off
456   {LLDB_OPT_SET_ALL, true, "file",'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename,       "The file from which to read the breakpoints." },
457     // clang-format on
458 };
459 
460 class CommandObjectSettingsRead : public CommandObjectParsed {
461 public:
462   CommandObjectSettingsRead(CommandInterpreter &interpreter)
463       : CommandObjectParsed(
464             interpreter, "settings read",
465             "Read settings previously saved to a file with \"settings write\".",
466             nullptr),
467         m_options() {}
468 
469   ~CommandObjectSettingsRead() override = default;
470 
471   Options *GetOptions() override { return &m_options; }
472 
473   class CommandOptions : public Options {
474   public:
475     CommandOptions() : Options() {}
476 
477     ~CommandOptions() override = default;
478 
479     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
480                           ExecutionContext *execution_context) override {
481       Status error;
482       const int short_option = m_getopt_table[option_idx].val;
483 
484       switch (short_option) {
485       case 'f':
486         m_filename.assign(option_arg);
487         break;
488       default:
489         error.SetErrorStringWithFormat("unrecognized option '%c'",
490                                        short_option);
491         break;
492       }
493 
494       return error;
495     }
496 
497     void OptionParsingStarting(ExecutionContext *execution_context) override {
498       m_filename.clear();
499     }
500 
501     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
502       return llvm::makeArrayRef(g_settings_read_options);
503     }
504 
505     // Instance variables to hold the values for command options.
506     std::string m_filename;
507   };
508 
509 protected:
510   bool DoExecute(Args &command, CommandReturnObject &result) override {
511     FileSpec file(m_options.m_filename);
512     FileSystem::Instance().Resolve(file);
513     ExecutionContext clean_ctx;
514     CommandInterpreterRunOptions options;
515     options.SetAddToHistory(false);
516     options.SetEchoCommands(false);
517     options.SetPrintResults(true);
518     options.SetStopOnError(false);
519     m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result);
520     return result.Succeeded();
521   }
522 
523 private:
524   CommandOptions m_options;
525 };
526 
527 //-------------------------------------------------------------------------
528 // CommandObjectSettingsList -- List settable variables
529 //-------------------------------------------------------------------------
530 
531 class CommandObjectSettingsList : public CommandObjectParsed {
532 public:
533   CommandObjectSettingsList(CommandInterpreter &interpreter)
534       : CommandObjectParsed(interpreter, "settings list",
535                             "List and describe matching debugger settings.  "
536                             "Defaults to all listing all settings.",
537                             nullptr) {
538     CommandArgumentEntry arg;
539     CommandArgumentData var_name_arg;
540     CommandArgumentData prefix_name_arg;
541 
542     // Define the first variant of this arg.
543     var_name_arg.arg_type = eArgTypeSettingVariableName;
544     var_name_arg.arg_repetition = eArgRepeatOptional;
545 
546     // Define the second variant of this arg.
547     prefix_name_arg.arg_type = eArgTypeSettingPrefix;
548     prefix_name_arg.arg_repetition = eArgRepeatOptional;
549 
550     arg.push_back(var_name_arg);
551     arg.push_back(prefix_name_arg);
552 
553     // Push the data for the first argument into the m_arguments vector.
554     m_arguments.push_back(arg);
555   }
556 
557   ~CommandObjectSettingsList() override = default;
558 
559   int HandleArgumentCompletion(
560       CompletionRequest &request,
561       OptionElementVector &opt_element_vector) override {
562     CommandCompletions::InvokeCommonCompletionCallbacks(
563         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
564         request, nullptr);
565     return request.GetNumberOfMatches();
566   }
567 
568 protected:
569   bool DoExecute(Args &args, CommandReturnObject &result) override {
570     result.SetStatus(eReturnStatusSuccessFinishResult);
571 
572     const bool will_modify = false;
573     const size_t argc = args.GetArgumentCount();
574     if (argc > 0) {
575       const bool dump_qualified_name = true;
576 
577       // TODO: Convert to StringRef based enumeration.  Requires converting
578       // GetPropertyAtPath first.
579       for (size_t i = 0; i < argc; ++i) {
580         const char *property_path = args.GetArgumentAtIndex(i);
581 
582         const Property *property =
583             m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath(
584                 &m_exe_ctx, will_modify, property_path);
585 
586         if (property) {
587           property->DumpDescription(m_interpreter, result.GetOutputStream(), 0,
588                                     dump_qualified_name);
589         } else {
590           result.AppendErrorWithFormat("invalid property path '%s'",
591                                        property_path);
592           result.SetStatus(eReturnStatusFailed);
593         }
594       }
595     } else {
596       m_interpreter.GetDebugger().DumpAllDescriptions(m_interpreter,
597                                                       result.GetOutputStream());
598     }
599 
600     return result.Succeeded();
601   }
602 };
603 
604 //-------------------------------------------------------------------------
605 // CommandObjectSettingsRemove
606 //-------------------------------------------------------------------------
607 
608 class CommandObjectSettingsRemove : public CommandObjectRaw {
609 public:
610   CommandObjectSettingsRemove(CommandInterpreter &interpreter)
611       : CommandObjectRaw(interpreter, "settings remove",
612                          "Remove a value from a setting, specified by array "
613                          "index or dictionary key.") {
614     CommandArgumentEntry arg1;
615     CommandArgumentEntry arg2;
616     CommandArgumentData var_name_arg;
617     CommandArgumentData index_arg;
618     CommandArgumentData key_arg;
619 
620     // Define the first (and only) variant of this arg.
621     var_name_arg.arg_type = eArgTypeSettingVariableName;
622     var_name_arg.arg_repetition = eArgRepeatPlain;
623 
624     // There is only one variant this argument could be; put it into the
625     // argument entry.
626     arg1.push_back(var_name_arg);
627 
628     // Define the first variant of this arg.
629     index_arg.arg_type = eArgTypeSettingIndex;
630     index_arg.arg_repetition = eArgRepeatPlain;
631 
632     // Define the second variant of this arg.
633     key_arg.arg_type = eArgTypeSettingKey;
634     key_arg.arg_repetition = eArgRepeatPlain;
635 
636     // Push both variants into this arg
637     arg2.push_back(index_arg);
638     arg2.push_back(key_arg);
639 
640     // Push the data for the first argument into the m_arguments vector.
641     m_arguments.push_back(arg1);
642     m_arguments.push_back(arg2);
643   }
644 
645   ~CommandObjectSettingsRemove() override = default;
646 
647   int HandleArgumentCompletion(
648       CompletionRequest &request,
649       OptionElementVector &opt_element_vector) override {
650     if (request.GetCursorIndex() < 2)
651       CommandCompletions::InvokeCommonCompletionCallbacks(
652           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
653           request, nullptr);
654     return request.GetNumberOfMatches();
655   }
656 
657 protected:
658   bool DoExecute(llvm::StringRef command,
659                  CommandReturnObject &result) override {
660     result.SetStatus(eReturnStatusSuccessFinishNoResult);
661 
662     Args cmd_args(command);
663 
664     // Process possible options.
665     if (!ParseOptions(cmd_args, result))
666       return false;
667 
668     const size_t argc = cmd_args.GetArgumentCount();
669     if (argc == 0) {
670       result.AppendError("'settings set' takes an array or dictionary item, or "
671                          "an array followed by one or more indexes, or a "
672                          "dictionary followed by one or more key names to "
673                          "remove");
674       result.SetStatus(eReturnStatusFailed);
675       return false;
676     }
677 
678     const char *var_name = cmd_args.GetArgumentAtIndex(0);
679     if ((var_name == nullptr) || (var_name[0] == '\0')) {
680       result.AppendError(
681           "'settings set' command requires a valid variable name");
682       result.SetStatus(eReturnStatusFailed);
683       return false;
684     }
685 
686     // Split the raw command into var_name and value pair.
687     llvm::StringRef raw_str(command);
688     std::string var_value_string = raw_str.split(var_name).second.str();
689     const char *var_value_cstr =
690         Args::StripSpaces(var_value_string, true, true, false);
691 
692     Status error(m_interpreter.GetDebugger().SetPropertyValue(
693         &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr));
694     if (error.Fail()) {
695       result.AppendError(error.AsCString());
696       result.SetStatus(eReturnStatusFailed);
697       return false;
698     }
699 
700     return result.Succeeded();
701   }
702 };
703 
704 //-------------------------------------------------------------------------
705 // CommandObjectSettingsReplace
706 //-------------------------------------------------------------------------
707 
708 class CommandObjectSettingsReplace : public CommandObjectRaw {
709 public:
710   CommandObjectSettingsReplace(CommandInterpreter &interpreter)
711       : CommandObjectRaw(interpreter, "settings replace",
712                          "Replace the debugger setting value specified by "
713                          "array index or dictionary key.") {
714     CommandArgumentEntry arg1;
715     CommandArgumentEntry arg2;
716     CommandArgumentEntry arg3;
717     CommandArgumentData var_name_arg;
718     CommandArgumentData index_arg;
719     CommandArgumentData key_arg;
720     CommandArgumentData value_arg;
721 
722     // Define the first (and only) variant of this arg.
723     var_name_arg.arg_type = eArgTypeSettingVariableName;
724     var_name_arg.arg_repetition = eArgRepeatPlain;
725 
726     // There is only one variant this argument could be; put it into the
727     // argument entry.
728     arg1.push_back(var_name_arg);
729 
730     // Define the first (variant of this arg.
731     index_arg.arg_type = eArgTypeSettingIndex;
732     index_arg.arg_repetition = eArgRepeatPlain;
733 
734     // Define the second (variant of this arg.
735     key_arg.arg_type = eArgTypeSettingKey;
736     key_arg.arg_repetition = eArgRepeatPlain;
737 
738     // Put both variants into this arg
739     arg2.push_back(index_arg);
740     arg2.push_back(key_arg);
741 
742     // Define the first (and only) variant of this arg.
743     value_arg.arg_type = eArgTypeValue;
744     value_arg.arg_repetition = eArgRepeatPlain;
745 
746     // There is only one variant this argument could be; put it into the
747     // argument entry.
748     arg3.push_back(value_arg);
749 
750     // Push the data for the first argument into the m_arguments vector.
751     m_arguments.push_back(arg1);
752     m_arguments.push_back(arg2);
753     m_arguments.push_back(arg3);
754   }
755 
756   ~CommandObjectSettingsReplace() override = default;
757 
758   // Overrides base class's behavior where WantsCompletion =
759   // !WantsRawCommandString.
760   bool WantsCompletion() override { return true; }
761 
762   int HandleArgumentCompletion(
763       CompletionRequest &request,
764       OptionElementVector &opt_element_vector) override {
765     // Attempting to complete variable name
766     if (request.GetCursorIndex() < 2)
767       CommandCompletions::InvokeCommonCompletionCallbacks(
768           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
769           request, nullptr);
770 
771     return request.GetNumberOfMatches();
772   }
773 
774 protected:
775   bool DoExecute(llvm::StringRef command,
776                  CommandReturnObject &result) override {
777     result.SetStatus(eReturnStatusSuccessFinishNoResult);
778 
779     Args cmd_args(command);
780     const char *var_name = cmd_args.GetArgumentAtIndex(0);
781     if ((var_name == nullptr) || (var_name[0] == '\0')) {
782       result.AppendError("'settings replace' command requires a valid variable "
783                          "name; No value supplied");
784       result.SetStatus(eReturnStatusFailed);
785       return false;
786     }
787 
788     // Split the raw command into var_name, index_value, and value triple.
789     llvm::StringRef raw_str(command);
790     std::string var_value_string = raw_str.split(var_name).second.str();
791     const char *var_value_cstr =
792         Args::StripSpaces(var_value_string, true, true, false);
793 
794     Status error(m_interpreter.GetDebugger().SetPropertyValue(
795         &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr));
796     if (error.Fail()) {
797       result.AppendError(error.AsCString());
798       result.SetStatus(eReturnStatusFailed);
799       return false;
800     } else {
801       result.SetStatus(eReturnStatusSuccessFinishNoResult);
802     }
803 
804     return result.Succeeded();
805   }
806 };
807 
808 //-------------------------------------------------------------------------
809 // CommandObjectSettingsInsertBefore
810 //-------------------------------------------------------------------------
811 
812 class CommandObjectSettingsInsertBefore : public CommandObjectRaw {
813 public:
814   CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
815       : CommandObjectRaw(interpreter, "settings insert-before",
816                          "Insert one or more values into an debugger array "
817                          "setting immediately before the specified element "
818                          "index.") {
819     CommandArgumentEntry arg1;
820     CommandArgumentEntry arg2;
821     CommandArgumentEntry arg3;
822     CommandArgumentData var_name_arg;
823     CommandArgumentData index_arg;
824     CommandArgumentData value_arg;
825 
826     // Define the first (and only) variant of this arg.
827     var_name_arg.arg_type = eArgTypeSettingVariableName;
828     var_name_arg.arg_repetition = eArgRepeatPlain;
829 
830     // There is only one variant this argument could be; put it into the
831     // argument entry.
832     arg1.push_back(var_name_arg);
833 
834     // Define the first (variant of this arg.
835     index_arg.arg_type = eArgTypeSettingIndex;
836     index_arg.arg_repetition = eArgRepeatPlain;
837 
838     // There is only one variant this argument could be; put it into the
839     // argument entry.
840     arg2.push_back(index_arg);
841 
842     // Define the first (and only) variant of this arg.
843     value_arg.arg_type = eArgTypeValue;
844     value_arg.arg_repetition = eArgRepeatPlain;
845 
846     // There is only one variant this argument could be; put it into the
847     // argument entry.
848     arg3.push_back(value_arg);
849 
850     // Push the data for the first argument into the m_arguments vector.
851     m_arguments.push_back(arg1);
852     m_arguments.push_back(arg2);
853     m_arguments.push_back(arg3);
854   }
855 
856   ~CommandObjectSettingsInsertBefore() override = default;
857 
858   // Overrides base class's behavior where WantsCompletion =
859   // !WantsRawCommandString.
860   bool WantsCompletion() override { return true; }
861 
862   int HandleArgumentCompletion(
863       CompletionRequest &request,
864       OptionElementVector &opt_element_vector) override {
865     // Attempting to complete variable name
866     if (request.GetCursorIndex() < 2)
867       CommandCompletions::InvokeCommonCompletionCallbacks(
868           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
869           request, nullptr);
870 
871     return request.GetNumberOfMatches();
872   }
873 
874 protected:
875   bool DoExecute(llvm::StringRef command,
876                  CommandReturnObject &result) override {
877     result.SetStatus(eReturnStatusSuccessFinishNoResult);
878 
879     Args cmd_args(command);
880     const size_t argc = cmd_args.GetArgumentCount();
881 
882     if (argc < 3) {
883       result.AppendError("'settings insert-before' takes more arguments");
884       result.SetStatus(eReturnStatusFailed);
885       return false;
886     }
887 
888     const char *var_name = cmd_args.GetArgumentAtIndex(0);
889     if ((var_name == nullptr) || (var_name[0] == '\0')) {
890       result.AppendError("'settings insert-before' command requires a valid "
891                          "variable name; No value supplied");
892       result.SetStatus(eReturnStatusFailed);
893       return false;
894     }
895 
896     // Split the raw command into var_name, index_value, and value triple.
897     llvm::StringRef raw_str(command);
898     std::string var_value_string = raw_str.split(var_name).second.str();
899     const char *var_value_cstr =
900         Args::StripSpaces(var_value_string, true, true, false);
901 
902     Status error(m_interpreter.GetDebugger().SetPropertyValue(
903         &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr));
904     if (error.Fail()) {
905       result.AppendError(error.AsCString());
906       result.SetStatus(eReturnStatusFailed);
907       return false;
908     }
909 
910     return result.Succeeded();
911   }
912 };
913 
914 //-------------------------------------------------------------------------
915 // CommandObjectSettingInsertAfter
916 //-------------------------------------------------------------------------
917 
918 class CommandObjectSettingsInsertAfter : public CommandObjectRaw {
919 public:
920   CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
921       : CommandObjectRaw(interpreter, "settings insert-after",
922                          "Insert one or more values into a debugger array "
923                          "settings after the specified element index.") {
924     CommandArgumentEntry arg1;
925     CommandArgumentEntry arg2;
926     CommandArgumentEntry arg3;
927     CommandArgumentData var_name_arg;
928     CommandArgumentData index_arg;
929     CommandArgumentData value_arg;
930 
931     // Define the first (and only) variant of this arg.
932     var_name_arg.arg_type = eArgTypeSettingVariableName;
933     var_name_arg.arg_repetition = eArgRepeatPlain;
934 
935     // There is only one variant this argument could be; put it into the
936     // argument entry.
937     arg1.push_back(var_name_arg);
938 
939     // Define the first (variant of this arg.
940     index_arg.arg_type = eArgTypeSettingIndex;
941     index_arg.arg_repetition = eArgRepeatPlain;
942 
943     // There is only one variant this argument could be; put it into the
944     // argument entry.
945     arg2.push_back(index_arg);
946 
947     // Define the first (and only) variant of this arg.
948     value_arg.arg_type = eArgTypeValue;
949     value_arg.arg_repetition = eArgRepeatPlain;
950 
951     // There is only one variant this argument could be; put it into the
952     // argument entry.
953     arg3.push_back(value_arg);
954 
955     // Push the data for the first argument into the m_arguments vector.
956     m_arguments.push_back(arg1);
957     m_arguments.push_back(arg2);
958     m_arguments.push_back(arg3);
959   }
960 
961   ~CommandObjectSettingsInsertAfter() override = default;
962 
963   // Overrides base class's behavior where WantsCompletion =
964   // !WantsRawCommandString.
965   bool WantsCompletion() override { return true; }
966 
967   int HandleArgumentCompletion(
968       CompletionRequest &request,
969       OptionElementVector &opt_element_vector) override {
970     // Attempting to complete variable name
971     if (request.GetCursorIndex() < 2)
972       CommandCompletions::InvokeCommonCompletionCallbacks(
973           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
974           request, nullptr);
975 
976     return request.GetNumberOfMatches();
977   }
978 
979 protected:
980   bool DoExecute(llvm::StringRef command,
981                  CommandReturnObject &result) override {
982     result.SetStatus(eReturnStatusSuccessFinishNoResult);
983 
984     Args cmd_args(command);
985     const size_t argc = cmd_args.GetArgumentCount();
986 
987     if (argc < 3) {
988       result.AppendError("'settings insert-after' takes more arguments");
989       result.SetStatus(eReturnStatusFailed);
990       return false;
991     }
992 
993     const char *var_name = cmd_args.GetArgumentAtIndex(0);
994     if ((var_name == nullptr) || (var_name[0] == '\0')) {
995       result.AppendError("'settings insert-after' command requires a valid "
996                          "variable name; No value supplied");
997       result.SetStatus(eReturnStatusFailed);
998       return false;
999     }
1000 
1001     // Split the raw command into var_name, index_value, and value triple.
1002     llvm::StringRef raw_str(command);
1003     std::string var_value_string = raw_str.split(var_name).second.str();
1004     const char *var_value_cstr =
1005         Args::StripSpaces(var_value_string, true, true, false);
1006 
1007     Status error(m_interpreter.GetDebugger().SetPropertyValue(
1008         &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr));
1009     if (error.Fail()) {
1010       result.AppendError(error.AsCString());
1011       result.SetStatus(eReturnStatusFailed);
1012       return false;
1013     }
1014 
1015     return result.Succeeded();
1016   }
1017 };
1018 
1019 //-------------------------------------------------------------------------
1020 // CommandObjectSettingsAppend
1021 //-------------------------------------------------------------------------
1022 
1023 class CommandObjectSettingsAppend : public CommandObjectRaw {
1024 public:
1025   CommandObjectSettingsAppend(CommandInterpreter &interpreter)
1026       : CommandObjectRaw(interpreter, "settings append",
1027                          "Append one or more values to a debugger array, "
1028                          "dictionary, or string setting.") {
1029     CommandArgumentEntry arg1;
1030     CommandArgumentEntry arg2;
1031     CommandArgumentData var_name_arg;
1032     CommandArgumentData value_arg;
1033 
1034     // Define the first (and only) variant of this arg.
1035     var_name_arg.arg_type = eArgTypeSettingVariableName;
1036     var_name_arg.arg_repetition = eArgRepeatPlain;
1037 
1038     // There is only one variant this argument could be; put it into the
1039     // argument entry.
1040     arg1.push_back(var_name_arg);
1041 
1042     // Define the first (and only) variant of this arg.
1043     value_arg.arg_type = eArgTypeValue;
1044     value_arg.arg_repetition = eArgRepeatPlain;
1045 
1046     // There is only one variant this argument could be; put it into the
1047     // argument entry.
1048     arg2.push_back(value_arg);
1049 
1050     // Push the data for the first argument into the m_arguments vector.
1051     m_arguments.push_back(arg1);
1052     m_arguments.push_back(arg2);
1053   }
1054 
1055   ~CommandObjectSettingsAppend() override = default;
1056 
1057   // Overrides base class's behavior where WantsCompletion =
1058   // !WantsRawCommandString.
1059   bool WantsCompletion() override { return true; }
1060 
1061   int HandleArgumentCompletion(
1062       CompletionRequest &request,
1063       OptionElementVector &opt_element_vector) override {
1064     // Attempting to complete variable name
1065     if (request.GetCursorIndex() < 2)
1066       CommandCompletions::InvokeCommonCompletionCallbacks(
1067           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1068           request, nullptr);
1069 
1070     return request.GetNumberOfMatches();
1071   }
1072 
1073 protected:
1074   bool DoExecute(llvm::StringRef command,
1075                  CommandReturnObject &result) override {
1076     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1077     Args cmd_args(command);
1078     const size_t argc = cmd_args.GetArgumentCount();
1079 
1080     if (argc < 2) {
1081       result.AppendError("'settings append' takes more arguments");
1082       result.SetStatus(eReturnStatusFailed);
1083       return false;
1084     }
1085 
1086     const char *var_name = cmd_args.GetArgumentAtIndex(0);
1087     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1088       result.AppendError("'settings append' command requires a valid variable "
1089                          "name; No value supplied");
1090       result.SetStatus(eReturnStatusFailed);
1091       return false;
1092     }
1093 
1094     // Do not perform cmd_args.Shift() since StringRef is manipulating the raw
1095     // character string later on.
1096 
1097     // Split the raw command into var_name and value pair.
1098     llvm::StringRef raw_str(command);
1099     std::string var_value_string = raw_str.split(var_name).second.str();
1100     const char *var_value_cstr =
1101         Args::StripSpaces(var_value_string, true, true, false);
1102 
1103     Status error(m_interpreter.GetDebugger().SetPropertyValue(
1104         &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr));
1105     if (error.Fail()) {
1106       result.AppendError(error.AsCString());
1107       result.SetStatus(eReturnStatusFailed);
1108       return false;
1109     }
1110 
1111     return result.Succeeded();
1112   }
1113 };
1114 
1115 //-------------------------------------------------------------------------
1116 // CommandObjectSettingsClear
1117 //-------------------------------------------------------------------------
1118 
1119 class CommandObjectSettingsClear : public CommandObjectParsed {
1120 public:
1121   CommandObjectSettingsClear(CommandInterpreter &interpreter)
1122       : CommandObjectParsed(
1123             interpreter, "settings clear",
1124             "Clear a debugger setting array, dictionary, or string.", nullptr) {
1125     CommandArgumentEntry arg;
1126     CommandArgumentData var_name_arg;
1127 
1128     // Define the first (and only) variant of this arg.
1129     var_name_arg.arg_type = eArgTypeSettingVariableName;
1130     var_name_arg.arg_repetition = eArgRepeatPlain;
1131 
1132     // There is only one variant this argument could be; put it into the
1133     // argument entry.
1134     arg.push_back(var_name_arg);
1135 
1136     // Push the data for the first argument into the m_arguments vector.
1137     m_arguments.push_back(arg);
1138   }
1139 
1140   ~CommandObjectSettingsClear() override = default;
1141 
1142   int HandleArgumentCompletion(
1143       CompletionRequest &request,
1144       OptionElementVector &opt_element_vector) override {
1145     // Attempting to complete variable name
1146     if (request.GetCursorIndex() < 2)
1147       CommandCompletions::InvokeCommonCompletionCallbacks(
1148           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
1149           request, nullptr);
1150 
1151     return request.GetNumberOfMatches();
1152   }
1153 
1154 protected:
1155   bool DoExecute(Args &command, CommandReturnObject &result) override {
1156     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1157     const size_t argc = command.GetArgumentCount();
1158 
1159     if (argc != 1) {
1160       result.AppendError("'settings clear' takes exactly one argument");
1161       result.SetStatus(eReturnStatusFailed);
1162       return false;
1163     }
1164 
1165     const char *var_name = command.GetArgumentAtIndex(0);
1166     if ((var_name == nullptr) || (var_name[0] == '\0')) {
1167       result.AppendError("'settings clear' command requires a valid variable "
1168                          "name; No value supplied");
1169       result.SetStatus(eReturnStatusFailed);
1170       return false;
1171     }
1172 
1173     Status error(m_interpreter.GetDebugger().SetPropertyValue(
1174         &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
1175     if (error.Fail()) {
1176       result.AppendError(error.AsCString());
1177       result.SetStatus(eReturnStatusFailed);
1178       return false;
1179     }
1180 
1181     return result.Succeeded();
1182   }
1183 };
1184 
1185 //-------------------------------------------------------------------------
1186 // CommandObjectMultiwordSettings
1187 //-------------------------------------------------------------------------
1188 
1189 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
1190     CommandInterpreter &interpreter)
1191     : CommandObjectMultiword(interpreter, "settings",
1192                              "Commands for managing LLDB settings.",
1193                              "settings <subcommand> [<command-options>]") {
1194   LoadSubCommand("set",
1195                  CommandObjectSP(new CommandObjectSettingsSet(interpreter)));
1196   LoadSubCommand("show",
1197                  CommandObjectSP(new CommandObjectSettingsShow(interpreter)));
1198   LoadSubCommand("list",
1199                  CommandObjectSP(new CommandObjectSettingsList(interpreter)));
1200   LoadSubCommand("remove",
1201                  CommandObjectSP(new CommandObjectSettingsRemove(interpreter)));
1202   LoadSubCommand("replace", CommandObjectSP(
1203                                 new CommandObjectSettingsReplace(interpreter)));
1204   LoadSubCommand(
1205       "insert-before",
1206       CommandObjectSP(new CommandObjectSettingsInsertBefore(interpreter)));
1207   LoadSubCommand(
1208       "insert-after",
1209       CommandObjectSP(new CommandObjectSettingsInsertAfter(interpreter)));
1210   LoadSubCommand("append",
1211                  CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
1212   LoadSubCommand("clear",
1213                  CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
1214   LoadSubCommand("write",
1215                  CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
1216   LoadSubCommand("read",
1217                  CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
1218 }
1219 
1220 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1221