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