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