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(interpreter)
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 (CommandInterpreter &interpreter) :
99             Options (interpreter),
100             m_global (false)
101         {
102         }
103 
104         ~CommandOptions() override = default;
105 
106         Error
107         SetOptionValue (uint32_t option_idx, const char *option_arg) override
108         {
109             Error error;
110             const int short_option = m_getopt_table[option_idx].val;
111 
112             switch (short_option)
113             {
114                 case 'g':
115                     m_global = true;
116                     break;
117                 default:
118                     error.SetErrorStringWithFormat ("unrecognized options '%c'", short_option);
119                     break;
120             }
121 
122             return error;
123         }
124 
125         void
126         OptionParsingStarting () override
127         {
128             m_global = false;
129         }
130 
131         const OptionDefinition*
132         GetDefinitions () override
133         {
134             return g_option_table;
135         }
136 
137         // Options table: Required for subclasses of Options.
138 
139         static OptionDefinition g_option_table[];
140 
141         // Instance variables to hold the values for command options.
142 
143         bool m_global;
144     };
145 
146     int
147     HandleArgumentCompletion (Args &input,
148                               int &cursor_index,
149                               int &cursor_char_position,
150                               OptionElementVector &opt_element_vector,
151                               int match_start_point,
152                               int max_return_elements,
153                               bool &word_complete,
154                               StringList &matches) override
155     {
156         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
157 
158         const size_t argc = input.GetArgumentCount();
159         const char *arg = nullptr;
160         int setting_var_idx;
161         for (setting_var_idx = 1; setting_var_idx < static_cast<int>(argc);
162              ++setting_var_idx)
163         {
164             arg = input.GetArgumentAtIndex(setting_var_idx);
165             if (arg && arg[0] != '-')
166                 break; // We found our setting variable name index
167         }
168         if (cursor_index == setting_var_idx)
169         {
170             // Attempting to complete setting variable name
171             CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
172                                                                 CommandCompletions::eSettingsNameCompletion,
173                                                                 completion_str.c_str(),
174                                                                 match_start_point,
175                                                                 max_return_elements,
176                                                                 nullptr,
177                                                                 word_complete,
178                                                                 matches);
179         }
180         else
181         {
182             arg = input.GetArgumentAtIndex(cursor_index);
183 
184             if (arg)
185             {
186                 if (arg[0] == '-')
187                 {
188                     // Complete option name
189                 }
190                 else
191                 {
192                     // Complete setting value
193                     const char *setting_var_name = input.GetArgumentAtIndex(setting_var_idx);
194                     Error error;
195                     lldb::OptionValueSP value_sp (m_interpreter.GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, false, error));
196                     if (value_sp)
197                     {
198                         value_sp->AutoComplete (m_interpreter,
199                                                 completion_str.c_str(),
200                                                 match_start_point,
201                                                 max_return_elements,
202                                                 word_complete,
203                                                 matches);
204                     }
205                 }
206             }
207         }
208         return matches.GetSize();
209     }
210 
211 protected:
212     bool
213     DoExecute (const char *command, CommandReturnObject &result) override
214     {
215         Args cmd_args(command);
216 
217         // Process possible options.
218         if (!ParseOptions (cmd_args, result))
219             return false;
220 
221         const size_t argc = cmd_args.GetArgumentCount ();
222         if ((argc < 2) && (!m_options.m_global))
223         {
224             result.AppendError ("'settings set' takes more arguments");
225             result.SetStatus (eReturnStatusFailed);
226             return false;
227         }
228 
229         const char *var_name = cmd_args.GetArgumentAtIndex (0);
230         if ((var_name == nullptr) || (var_name[0] == '\0'))
231         {
232             result.AppendError ("'settings set' command requires a valid variable name");
233             result.SetStatus (eReturnStatusFailed);
234             return false;
235         }
236 
237         // Split the raw command into var_name and value pair.
238         llvm::StringRef raw_str(command);
239         std::string var_value_string = raw_str.split(var_name).second.str();
240         const char *var_value_cstr = Args::StripSpaces(var_value_string, true, false, false);
241 
242         Error error;
243         if (m_options.m_global)
244         {
245             error = m_interpreter.GetDebugger().SetPropertyValue(nullptr,
246                                                                  eVarSetOperationAssign,
247                                                                  var_name,
248                                                                  var_value_cstr);
249         }
250 
251         if (error.Success())
252         {
253             // FIXME this is the same issue as the one in commands script import
254             // we could be setting target.load-script-from-symbol-file which would cause
255             // Python scripts to be loaded, which could run LLDB commands
256             // (e.g. settings set target.process.python-os-plugin-path) and cause a crash
257             // if we did not clear the command's exe_ctx first
258             ExecutionContext exe_ctx(m_exe_ctx);
259             m_exe_ctx.Clear();
260             error = m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
261                                                                   eVarSetOperationAssign,
262                                                                   var_name,
263                                                                   var_value_cstr);
264         }
265 
266         if (error.Fail())
267         {
268             result.AppendError (error.AsCString());
269             result.SetStatus (eReturnStatusFailed);
270             return false;
271         }
272         else
273         {
274             result.SetStatus (eReturnStatusSuccessFinishResult);
275         }
276 
277         return result.Succeeded();
278     }
279 
280 private:
281     CommandOptions m_options;
282 };
283 
284 OptionDefinition
285 CommandObjectSettingsSet::CommandOptions::g_option_table[] =
286 {
287     { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument,   nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value." },
288     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
289 };
290 
291 //-------------------------------------------------------------------------
292 // CommandObjectSettingsShow -- Show current values
293 //-------------------------------------------------------------------------
294 
295 class CommandObjectSettingsShow : public CommandObjectParsed
296 {
297 public:
298     CommandObjectSettingsShow(CommandInterpreter &interpreter)
299         : CommandObjectParsed(
300               interpreter, "settings show",
301               "Show matching debugger settings and their current values.  Defaults to showing all settings.", nullptr)
302     {
303         CommandArgumentEntry arg1;
304         CommandArgumentData var_name_arg;
305 
306         // Define the first (and only) variant of this arg.
307         var_name_arg.arg_type = eArgTypeSettingVariableName;
308         var_name_arg.arg_repetition = eArgRepeatOptional;
309 
310         // There is only one variant this argument could be; put it into the argument entry.
311         arg1.push_back (var_name_arg);
312 
313         // Push the data for the first argument into the m_arguments vector.
314         m_arguments.push_back (arg1);
315     }
316 
317     ~CommandObjectSettingsShow() override = default;
318 
319     int
320     HandleArgumentCompletion (Args &input,
321                               int &cursor_index,
322                               int &cursor_char_position,
323                               OptionElementVector &opt_element_vector,
324                               int match_start_point,
325                               int max_return_elements,
326                               bool &word_complete,
327                               StringList &matches) override
328     {
329         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
330 
331         CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
332                                                             CommandCompletions::eSettingsNameCompletion,
333                                                             completion_str.c_str(),
334                                                             match_start_point,
335                                                             max_return_elements,
336                                                             nullptr,
337                                                             word_complete,
338                                                             matches);
339         return matches.GetSize();
340     }
341 
342 protected:
343     bool
344     DoExecute (Args& args, CommandReturnObject &result) override
345     {
346         result.SetStatus (eReturnStatusSuccessFinishResult);
347 
348         const size_t argc = args.GetArgumentCount ();
349         if (argc > 0)
350         {
351             for (size_t i = 0; i < argc; ++i)
352             {
353                 const char *property_path = args.GetArgumentAtIndex (i);
354 
355                 Error error(m_interpreter.GetDebugger().DumpPropertyValue (&m_exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue));
356                 if (error.Success())
357                 {
358                     result.GetOutputStream().EOL();
359                 }
360                 else
361                 {
362                     result.AppendError (error.AsCString());
363                     result.SetStatus (eReturnStatusFailed);
364                 }
365             }
366         }
367         else
368         {
369             m_interpreter.GetDebugger().DumpAllPropertyValues (&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
370         }
371 
372         return result.Succeeded();
373     }
374 };
375 
376 //-------------------------------------------------------------------------
377 // CommandObjectSettingsList -- List settable variables
378 //-------------------------------------------------------------------------
379 
380 class CommandObjectSettingsList : public CommandObjectParsed
381 {
382 public:
383     CommandObjectSettingsList(CommandInterpreter &interpreter)
384         : CommandObjectParsed(interpreter, "settings list",
385                               "List and describe matching debugger settings.  Defaults to all listing all settings.",
386                               nullptr)
387     {
388         CommandArgumentEntry arg;
389         CommandArgumentData var_name_arg;
390         CommandArgumentData prefix_name_arg;
391 
392         // Define the first variant of this arg.
393         var_name_arg.arg_type = eArgTypeSettingVariableName;
394         var_name_arg.arg_repetition = eArgRepeatOptional;
395 
396         // Define the second variant of this arg.
397         prefix_name_arg.arg_type = eArgTypeSettingPrefix;
398         prefix_name_arg.arg_repetition = eArgRepeatOptional;
399 
400         arg.push_back (var_name_arg);
401         arg.push_back (prefix_name_arg);
402 
403         // Push the data for the first argument into the m_arguments vector.
404         m_arguments.push_back (arg);
405     }
406 
407     ~CommandObjectSettingsList() override = default;
408 
409     int
410     HandleArgumentCompletion (Args &input,
411                               int &cursor_index,
412                               int &cursor_char_position,
413                               OptionElementVector &opt_element_vector,
414                               int match_start_point,
415                               int max_return_elements,
416                               bool &word_complete,
417                               StringList &matches) override
418     {
419         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
420 
421         CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
422                                                             CommandCompletions::eSettingsNameCompletion,
423                                                             completion_str.c_str(),
424                                                             match_start_point,
425                                                             max_return_elements,
426                                                             nullptr,
427                                                             word_complete,
428                                                             matches);
429         return matches.GetSize();
430     }
431 
432 protected:
433     bool
434     DoExecute (Args& args, CommandReturnObject &result) override
435     {
436         result.SetStatus (eReturnStatusSuccessFinishResult);
437 
438         const bool will_modify = false;
439         const size_t argc = args.GetArgumentCount ();
440         if (argc > 0)
441         {
442             const bool dump_qualified_name = true;
443 
444             for (size_t i = 0; i < argc; ++i)
445             {
446                 const char *property_path = args.GetArgumentAtIndex (i);
447 
448                 const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&m_exe_ctx, will_modify, property_path);
449 
450                 if (property)
451                 {
452                     property->DumpDescription (m_interpreter, result.GetOutputStream(), 0, dump_qualified_name);
453                 }
454                 else
455                 {
456                     result.AppendErrorWithFormat ("invalid property path '%s'", property_path);
457                     result.SetStatus (eReturnStatusFailed);
458                 }
459             }
460         }
461         else
462         {
463             m_interpreter.GetDebugger().DumpAllDescriptions (m_interpreter, result.GetOutputStream());
464         }
465 
466         return result.Succeeded();
467     }
468 };
469 
470 //-------------------------------------------------------------------------
471 // CommandObjectSettingsRemove
472 //-------------------------------------------------------------------------
473 
474 class CommandObjectSettingsRemove : public CommandObjectRaw
475 {
476 public:
477     CommandObjectSettingsRemove(CommandInterpreter &interpreter)
478         : CommandObjectRaw(interpreter, "settings remove",
479                            "Remove a value from a setting, specified by array index or dictionary key.", nullptr)
480     {
481         CommandArgumentEntry arg1;
482         CommandArgumentEntry arg2;
483         CommandArgumentData var_name_arg;
484         CommandArgumentData index_arg;
485         CommandArgumentData key_arg;
486 
487         // Define the first (and only) variant of this arg.
488         var_name_arg.arg_type = eArgTypeSettingVariableName;
489         var_name_arg.arg_repetition = eArgRepeatPlain;
490 
491         // There is only one variant this argument could be; put it into the argument entry.
492         arg1.push_back (var_name_arg);
493 
494         // Define the first variant of this arg.
495         index_arg.arg_type = eArgTypeSettingIndex;
496         index_arg.arg_repetition = eArgRepeatPlain;
497 
498         // Define the second variant of this arg.
499         key_arg.arg_type = eArgTypeSettingKey;
500         key_arg.arg_repetition = eArgRepeatPlain;
501 
502         // Push both variants into this arg
503         arg2.push_back (index_arg);
504         arg2.push_back (key_arg);
505 
506         // Push the data for the first argument into the m_arguments vector.
507         m_arguments.push_back (arg1);
508         m_arguments.push_back (arg2);
509     }
510 
511     ~CommandObjectSettingsRemove() override = default;
512 
513     int
514     HandleArgumentCompletion (Args &input,
515                               int &cursor_index,
516                               int &cursor_char_position,
517                               OptionElementVector &opt_element_vector,
518                               int match_start_point,
519                               int max_return_elements,
520                               bool &word_complete,
521                               StringList &matches) override
522     {
523         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
524 
525         // Attempting to complete variable name
526         if (cursor_index < 2)
527             CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
528                                                                 CommandCompletions::eSettingsNameCompletion,
529                                                                 completion_str.c_str(),
530                                                                 match_start_point,
531                                                                 max_return_elements,
532                                                                 nullptr,
533                                                                 word_complete,
534                                                                 matches);
535 
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(m_interpreter,
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(m_interpreter,
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(m_interpreter,
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(m_interpreter,
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(m_interpreter,
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