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