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   // clang-format off
289   {LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value."},
290   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
291   // clang-format on
292 };
293 
294 //-------------------------------------------------------------------------
295 // CommandObjectSettingsShow -- Show current values
296 //-------------------------------------------------------------------------
297 
298 class CommandObjectSettingsShow : public CommandObjectParsed
299 {
300 public:
301     CommandObjectSettingsShow(CommandInterpreter &interpreter)
302         : CommandObjectParsed(
303               interpreter, "settings show",
304               "Show matching debugger settings and their current values.  Defaults to showing all settings.", nullptr)
305     {
306         CommandArgumentEntry arg1;
307         CommandArgumentData var_name_arg;
308 
309         // Define the first (and only) variant of this arg.
310         var_name_arg.arg_type = eArgTypeSettingVariableName;
311         var_name_arg.arg_repetition = eArgRepeatOptional;
312 
313         // There is only one variant this argument could be; put it into the argument entry.
314         arg1.push_back (var_name_arg);
315 
316         // Push the data for the first argument into the m_arguments vector.
317         m_arguments.push_back (arg1);
318     }
319 
320     ~CommandObjectSettingsShow() override = default;
321 
322     int
323     HandleArgumentCompletion (Args &input,
324                               int &cursor_index,
325                               int &cursor_char_position,
326                               OptionElementVector &opt_element_vector,
327                               int match_start_point,
328                               int max_return_elements,
329                               bool &word_complete,
330                               StringList &matches) override
331     {
332         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
333 
334         CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
335                                                             CommandCompletions::eSettingsNameCompletion,
336                                                             completion_str.c_str(),
337                                                             match_start_point,
338                                                             max_return_elements,
339                                                             nullptr,
340                                                             word_complete,
341                                                             matches);
342         return matches.GetSize();
343     }
344 
345 protected:
346     bool
347     DoExecute (Args& args, CommandReturnObject &result) override
348     {
349         result.SetStatus (eReturnStatusSuccessFinishResult);
350 
351         const size_t argc = args.GetArgumentCount ();
352         if (argc > 0)
353         {
354             for (size_t i = 0; i < argc; ++i)
355             {
356                 const char *property_path = args.GetArgumentAtIndex (i);
357 
358                 Error error(m_interpreter.GetDebugger().DumpPropertyValue (&m_exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue));
359                 if (error.Success())
360                 {
361                     result.GetOutputStream().EOL();
362                 }
363                 else
364                 {
365                     result.AppendError (error.AsCString());
366                     result.SetStatus (eReturnStatusFailed);
367                 }
368             }
369         }
370         else
371         {
372             m_interpreter.GetDebugger().DumpAllPropertyValues (&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
373         }
374 
375         return result.Succeeded();
376     }
377 };
378 
379 //-------------------------------------------------------------------------
380 // CommandObjectSettingsList -- List settable variables
381 //-------------------------------------------------------------------------
382 
383 class CommandObjectSettingsList : public CommandObjectParsed
384 {
385 public:
386     CommandObjectSettingsList(CommandInterpreter &interpreter)
387         : CommandObjectParsed(interpreter, "settings list",
388                               "List and describe matching debugger settings.  Defaults to all listing all settings.",
389                               nullptr)
390     {
391         CommandArgumentEntry arg;
392         CommandArgumentData var_name_arg;
393         CommandArgumentData prefix_name_arg;
394 
395         // Define the first variant of this arg.
396         var_name_arg.arg_type = eArgTypeSettingVariableName;
397         var_name_arg.arg_repetition = eArgRepeatOptional;
398 
399         // Define the second variant of this arg.
400         prefix_name_arg.arg_type = eArgTypeSettingPrefix;
401         prefix_name_arg.arg_repetition = eArgRepeatOptional;
402 
403         arg.push_back (var_name_arg);
404         arg.push_back (prefix_name_arg);
405 
406         // Push the data for the first argument into the m_arguments vector.
407         m_arguments.push_back (arg);
408     }
409 
410     ~CommandObjectSettingsList() override = default;
411 
412     int
413     HandleArgumentCompletion (Args &input,
414                               int &cursor_index,
415                               int &cursor_char_position,
416                               OptionElementVector &opt_element_vector,
417                               int match_start_point,
418                               int max_return_elements,
419                               bool &word_complete,
420                               StringList &matches) override
421     {
422         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
423 
424         CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
425                                                             CommandCompletions::eSettingsNameCompletion,
426                                                             completion_str.c_str(),
427                                                             match_start_point,
428                                                             max_return_elements,
429                                                             nullptr,
430                                                             word_complete,
431                                                             matches);
432         return matches.GetSize();
433     }
434 
435 protected:
436     bool
437     DoExecute (Args& args, CommandReturnObject &result) override
438     {
439         result.SetStatus (eReturnStatusSuccessFinishResult);
440 
441         const bool will_modify = false;
442         const size_t argc = args.GetArgumentCount ();
443         if (argc > 0)
444         {
445             const bool dump_qualified_name = true;
446 
447             for (size_t i = 0; i < argc; ++i)
448             {
449                 const char *property_path = args.GetArgumentAtIndex (i);
450 
451                 const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&m_exe_ctx, will_modify, property_path);
452 
453                 if (property)
454                 {
455                     property->DumpDescription (m_interpreter, result.GetOutputStream(), 0, dump_qualified_name);
456                 }
457                 else
458                 {
459                     result.AppendErrorWithFormat ("invalid property path '%s'", property_path);
460                     result.SetStatus (eReturnStatusFailed);
461                 }
462             }
463         }
464         else
465         {
466             m_interpreter.GetDebugger().DumpAllDescriptions (m_interpreter, result.GetOutputStream());
467         }
468 
469         return result.Succeeded();
470     }
471 };
472 
473 //-------------------------------------------------------------------------
474 // CommandObjectSettingsRemove
475 //-------------------------------------------------------------------------
476 
477 class CommandObjectSettingsRemove : public CommandObjectRaw
478 {
479 public:
480     CommandObjectSettingsRemove(CommandInterpreter &interpreter)
481         : CommandObjectRaw(interpreter, "settings remove",
482                            "Remove a value from a setting, specified by array index or dictionary key.", nullptr)
483     {
484         CommandArgumentEntry arg1;
485         CommandArgumentEntry arg2;
486         CommandArgumentData var_name_arg;
487         CommandArgumentData index_arg;
488         CommandArgumentData key_arg;
489 
490         // Define the first (and only) variant of this arg.
491         var_name_arg.arg_type = eArgTypeSettingVariableName;
492         var_name_arg.arg_repetition = eArgRepeatPlain;
493 
494         // There is only one variant this argument could be; put it into the argument entry.
495         arg1.push_back (var_name_arg);
496 
497         // Define the first variant of this arg.
498         index_arg.arg_type = eArgTypeSettingIndex;
499         index_arg.arg_repetition = eArgRepeatPlain;
500 
501         // Define the second variant of this arg.
502         key_arg.arg_type = eArgTypeSettingKey;
503         key_arg.arg_repetition = eArgRepeatPlain;
504 
505         // Push both variants into this arg
506         arg2.push_back (index_arg);
507         arg2.push_back (key_arg);
508 
509         // Push the data for the first argument into the m_arguments vector.
510         m_arguments.push_back (arg1);
511         m_arguments.push_back (arg2);
512     }
513 
514     ~CommandObjectSettingsRemove() override = default;
515 
516     int
517     HandleArgumentCompletion (Args &input,
518                               int &cursor_index,
519                               int &cursor_char_position,
520                               OptionElementVector &opt_element_vector,
521                               int match_start_point,
522                               int max_return_elements,
523                               bool &word_complete,
524                               StringList &matches) override
525     {
526         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
527 
528         // Attempting to complete variable name
529         if (cursor_index < 2)
530             CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
531                                                                 CommandCompletions::eSettingsNameCompletion,
532                                                                 completion_str.c_str(),
533                                                                 match_start_point,
534                                                                 max_return_elements,
535                                                                 nullptr,
536                                                                 word_complete,
537                                                                 matches);
538         return matches.GetSize();
539     }
540 
541 protected:
542     bool
543     DoExecute (const char *command, CommandReturnObject &result) override
544     {
545         result.SetStatus (eReturnStatusSuccessFinishNoResult);
546 
547         Args cmd_args(command);
548 
549         // Process possible options.
550         if (!ParseOptions (cmd_args, result))
551             return false;
552 
553         const size_t argc = cmd_args.GetArgumentCount ();
554         if (argc == 0)
555         {
556             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");
557             result.SetStatus (eReturnStatusFailed);
558             return false;
559         }
560 
561         const char *var_name = cmd_args.GetArgumentAtIndex (0);
562         if ((var_name == nullptr) || (var_name[0] == '\0'))
563         {
564             result.AppendError ("'settings set' command requires a valid variable name");
565             result.SetStatus (eReturnStatusFailed);
566             return false;
567         }
568 
569         // Split the raw command into var_name and value pair.
570         llvm::StringRef raw_str(command);
571         std::string var_value_string = raw_str.split(var_name).second.str();
572         const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false);
573 
574         Error error (m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
575                                                                    eVarSetOperationRemove,
576                                                                    var_name,
577                                                                    var_value_cstr));
578         if (error.Fail())
579         {
580             result.AppendError (error.AsCString());
581             result.SetStatus (eReturnStatusFailed);
582             return false;
583         }
584 
585         return result.Succeeded();
586     }
587 };
588 
589 //-------------------------------------------------------------------------
590 // CommandObjectSettingsReplace
591 //-------------------------------------------------------------------------
592 
593 class CommandObjectSettingsReplace : public CommandObjectRaw
594 {
595 public:
596     CommandObjectSettingsReplace(CommandInterpreter &interpreter)
597         : CommandObjectRaw(interpreter, "settings replace",
598                            "Replace the debugger setting value specified by array index or dictionary key.", nullptr)
599     {
600         CommandArgumentEntry arg1;
601         CommandArgumentEntry arg2;
602         CommandArgumentEntry arg3;
603         CommandArgumentData var_name_arg;
604         CommandArgumentData index_arg;
605         CommandArgumentData key_arg;
606         CommandArgumentData value_arg;
607 
608         // Define the first (and only) variant of this arg.
609         var_name_arg.arg_type = eArgTypeSettingVariableName;
610         var_name_arg.arg_repetition = eArgRepeatPlain;
611 
612         // There is only one variant this argument could be; put it into the argument entry.
613         arg1.push_back (var_name_arg);
614 
615         // Define the first (variant of this arg.
616         index_arg.arg_type = eArgTypeSettingIndex;
617         index_arg.arg_repetition = eArgRepeatPlain;
618 
619         // Define the second (variant of this arg.
620         key_arg.arg_type = eArgTypeSettingKey;
621         key_arg.arg_repetition = eArgRepeatPlain;
622 
623         // Put both variants into this arg
624         arg2.push_back (index_arg);
625         arg2.push_back (key_arg);
626 
627         // Define the first (and only) variant of this arg.
628         value_arg.arg_type = eArgTypeValue;
629         value_arg.arg_repetition = eArgRepeatPlain;
630 
631         // There is only one variant this argument could be; put it into the argument entry.
632         arg3.push_back (value_arg);
633 
634         // Push the data for the first argument into the m_arguments vector.
635         m_arguments.push_back (arg1);
636         m_arguments.push_back (arg2);
637         m_arguments.push_back (arg3);
638     }
639 
640     ~CommandObjectSettingsReplace() override = default;
641 
642     // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
643     bool
644     WantsCompletion() override { return true; }
645 
646     int
647     HandleArgumentCompletion (Args &input,
648                               int &cursor_index,
649                               int &cursor_char_position,
650                               OptionElementVector &opt_element_vector,
651                               int match_start_point,
652                               int max_return_elements,
653                               bool &word_complete,
654                               StringList &matches) override
655     {
656         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
657 
658         // Attempting to complete variable name
659         if (cursor_index < 2)
660             CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
661                                                                 CommandCompletions::eSettingsNameCompletion,
662                                                                 completion_str.c_str(),
663                                                                 match_start_point,
664                                                                 max_return_elements,
665                                                                 nullptr,
666                                                                 word_complete,
667                                                                 matches);
668 
669         return matches.GetSize();
670     }
671 
672 protected:
673     bool
674     DoExecute (const char *command, CommandReturnObject &result) override
675     {
676         result.SetStatus (eReturnStatusSuccessFinishNoResult);
677 
678         Args cmd_args(command);
679         const char *var_name = cmd_args.GetArgumentAtIndex (0);
680         if ((var_name == nullptr) || (var_name[0] == '\0'))
681         {
682             result.AppendError ("'settings replace' command requires a valid variable name; No value supplied");
683             result.SetStatus (eReturnStatusFailed);
684             return false;
685         }
686 
687         // Split the raw command into var_name, index_value, and value triple.
688         llvm::StringRef raw_str(command);
689         std::string var_value_string = raw_str.split(var_name).second.str();
690         const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false);
691 
692         Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
693                                                                   eVarSetOperationReplace,
694                                                                   var_name,
695                                                                   var_value_cstr));
696         if (error.Fail())
697         {
698             result.AppendError (error.AsCString());
699             result.SetStatus (eReturnStatusFailed);
700             return false;
701         }
702         else
703         {
704             result.SetStatus (eReturnStatusSuccessFinishNoResult);
705 
706         }
707 
708         return result.Succeeded();
709     }
710 };
711 
712 //-------------------------------------------------------------------------
713 // CommandObjectSettingsInsertBefore
714 //-------------------------------------------------------------------------
715 
716 class CommandObjectSettingsInsertBefore : public CommandObjectRaw
717 {
718 public:
719     CommandObjectSettingsInsertBefore(CommandInterpreter &interpreter)
720         : CommandObjectRaw(interpreter, "settings insert-before", "Insert one or more values into an debugger array "
721                                                                   "setting immediately before the specified element "
722                                                                   "index.",
723                            nullptr)
724     {
725         CommandArgumentEntry arg1;
726         CommandArgumentEntry arg2;
727         CommandArgumentEntry arg3;
728         CommandArgumentData var_name_arg;
729         CommandArgumentData index_arg;
730         CommandArgumentData value_arg;
731 
732         // Define the first (and only) variant of this arg.
733         var_name_arg.arg_type = eArgTypeSettingVariableName;
734         var_name_arg.arg_repetition = eArgRepeatPlain;
735 
736         // There is only one variant this argument could be; put it into the argument entry.
737         arg1.push_back (var_name_arg);
738 
739         // Define the first (variant of this arg.
740         index_arg.arg_type = eArgTypeSettingIndex;
741         index_arg.arg_repetition = eArgRepeatPlain;
742 
743         // There is only one variant this argument could be; put it into the argument entry.
744         arg2.push_back (index_arg);
745 
746         // Define the first (and only) variant of this arg.
747         value_arg.arg_type = eArgTypeValue;
748         value_arg.arg_repetition = eArgRepeatPlain;
749 
750         // There is only one variant this argument could be; put it into the argument entry.
751         arg3.push_back (value_arg);
752 
753         // Push the data for the first argument into the m_arguments vector.
754         m_arguments.push_back (arg1);
755         m_arguments.push_back (arg2);
756         m_arguments.push_back (arg3);
757     }
758 
759     ~CommandObjectSettingsInsertBefore() override = default;
760 
761     // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
762     bool
763     WantsCompletion() override { return true; }
764 
765     int
766     HandleArgumentCompletion (Args &input,
767                               int &cursor_index,
768                               int &cursor_char_position,
769                               OptionElementVector &opt_element_vector,
770                               int match_start_point,
771                               int max_return_elements,
772                               bool &word_complete,
773                               StringList &matches) override
774     {
775         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
776 
777         // Attempting to complete variable name
778         if (cursor_index < 2)
779             CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
780                                                                 CommandCompletions::eSettingsNameCompletion,
781                                                                 completion_str.c_str(),
782                                                                 match_start_point,
783                                                                 max_return_elements,
784                                                                 nullptr,
785                                                                 word_complete,
786                                                                 matches);
787 
788         return matches.GetSize();
789     }
790 
791 protected:
792     bool
793     DoExecute (const char *command, CommandReturnObject &result) override
794     {
795         result.SetStatus (eReturnStatusSuccessFinishNoResult);
796 
797         Args cmd_args(command);
798         const size_t argc = cmd_args.GetArgumentCount ();
799 
800         if (argc < 3)
801         {
802             result.AppendError ("'settings insert-before' takes more arguments");
803             result.SetStatus (eReturnStatusFailed);
804             return false;
805         }
806 
807         const char *var_name = cmd_args.GetArgumentAtIndex (0);
808         if ((var_name == nullptr) || (var_name[0] == '\0'))
809         {
810             result.AppendError ("'settings insert-before' command requires a valid variable name; No value supplied");
811             result.SetStatus (eReturnStatusFailed);
812             return false;
813         }
814 
815         // Split the raw command into var_name, index_value, and value triple.
816         llvm::StringRef raw_str(command);
817         std::string var_value_string = raw_str.split(var_name).second.str();
818         const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false);
819 
820         Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
821                                                                   eVarSetOperationInsertBefore,
822                                                                   var_name,
823                                                                   var_value_cstr));
824         if (error.Fail())
825         {
826             result.AppendError (error.AsCString());
827             result.SetStatus (eReturnStatusFailed);
828             return false;
829         }
830 
831         return result.Succeeded();
832     }
833 };
834 
835 //-------------------------------------------------------------------------
836 // CommandObjectSettingInsertAfter
837 //-------------------------------------------------------------------------
838 
839 class CommandObjectSettingsInsertAfter : public CommandObjectRaw
840 {
841 public:
842     CommandObjectSettingsInsertAfter(CommandInterpreter &interpreter)
843         : CommandObjectRaw(
844               interpreter, "settings insert-after",
845               "Insert one or more values into a debugger array settings after the specified element index.", nullptr)
846     {
847         CommandArgumentEntry arg1;
848         CommandArgumentEntry arg2;
849         CommandArgumentEntry arg3;
850         CommandArgumentData var_name_arg;
851         CommandArgumentData index_arg;
852         CommandArgumentData value_arg;
853 
854         // Define the first (and only) variant of this arg.
855         var_name_arg.arg_type = eArgTypeSettingVariableName;
856         var_name_arg.arg_repetition = eArgRepeatPlain;
857 
858         // There is only one variant this argument could be; put it into the argument entry.
859         arg1.push_back (var_name_arg);
860 
861         // Define the first (variant of this arg.
862         index_arg.arg_type = eArgTypeSettingIndex;
863         index_arg.arg_repetition = eArgRepeatPlain;
864 
865         // There is only one variant this argument could be; put it into the argument entry.
866         arg2.push_back (index_arg);
867 
868         // Define the first (and only) variant of this arg.
869         value_arg.arg_type = eArgTypeValue;
870         value_arg.arg_repetition = eArgRepeatPlain;
871 
872         // There is only one variant this argument could be; put it into the argument entry.
873         arg3.push_back (value_arg);
874 
875         // Push the data for the first argument into the m_arguments vector.
876         m_arguments.push_back (arg1);
877         m_arguments.push_back (arg2);
878         m_arguments.push_back (arg3);
879     }
880 
881     ~CommandObjectSettingsInsertAfter() override = default;
882 
883     // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
884     bool
885     WantsCompletion() override { return true; }
886 
887     int
888     HandleArgumentCompletion (Args &input,
889                               int &cursor_index,
890                               int &cursor_char_position,
891                               OptionElementVector &opt_element_vector,
892                               int match_start_point,
893                               int max_return_elements,
894                               bool &word_complete,
895                               StringList &matches) override
896     {
897         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
898 
899         // Attempting to complete variable name
900         if (cursor_index < 2)
901             CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
902                                                                 CommandCompletions::eSettingsNameCompletion,
903                                                                 completion_str.c_str(),
904                                                                 match_start_point,
905                                                                 max_return_elements,
906                                                                 nullptr,
907                                                                 word_complete,
908                                                                 matches);
909 
910         return matches.GetSize();
911     }
912 
913 protected:
914     bool
915     DoExecute (const char *command, CommandReturnObject &result) override
916     {
917         result.SetStatus (eReturnStatusSuccessFinishNoResult);
918 
919         Args cmd_args(command);
920         const size_t argc = cmd_args.GetArgumentCount ();
921 
922         if (argc < 3)
923         {
924             result.AppendError ("'settings insert-after' takes more arguments");
925             result.SetStatus (eReturnStatusFailed);
926             return false;
927         }
928 
929         const char *var_name = cmd_args.GetArgumentAtIndex (0);
930         if ((var_name == nullptr) || (var_name[0] == '\0'))
931         {
932             result.AppendError ("'settings insert-after' command requires a valid variable name; No value supplied");
933             result.SetStatus (eReturnStatusFailed);
934             return false;
935         }
936 
937         // Split the raw command into var_name, index_value, and value triple.
938         llvm::StringRef raw_str(command);
939         std::string var_value_string = raw_str.split(var_name).second.str();
940         const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false);
941 
942         Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
943                                                                   eVarSetOperationInsertAfter,
944                                                                   var_name,
945                                                                   var_value_cstr));
946         if (error.Fail())
947         {
948             result.AppendError (error.AsCString());
949             result.SetStatus (eReturnStatusFailed);
950             return false;
951         }
952 
953         return result.Succeeded();
954     }
955 };
956 
957 //-------------------------------------------------------------------------
958 // CommandObjectSettingsAppend
959 //-------------------------------------------------------------------------
960 
961 class CommandObjectSettingsAppend : public CommandObjectRaw
962 {
963 public:
964     CommandObjectSettingsAppend(CommandInterpreter &interpreter)
965         : CommandObjectRaw(interpreter, "settings append",
966                            "Append one or more values to a debugger array, dictionary, or string setting.", nullptr)
967     {
968         CommandArgumentEntry arg1;
969         CommandArgumentEntry arg2;
970         CommandArgumentData var_name_arg;
971         CommandArgumentData value_arg;
972 
973         // Define the first (and only) variant of this arg.
974         var_name_arg.arg_type = eArgTypeSettingVariableName;
975         var_name_arg.arg_repetition = eArgRepeatPlain;
976 
977         // There is only one variant this argument could be; put it into the argument entry.
978         arg1.push_back (var_name_arg);
979 
980         // Define the first (and only) variant of this arg.
981         value_arg.arg_type = eArgTypeValue;
982         value_arg.arg_repetition = eArgRepeatPlain;
983 
984         // There is only one variant this argument could be; put it into the argument entry.
985         arg2.push_back (value_arg);
986 
987         // Push the data for the first argument into the m_arguments vector.
988         m_arguments.push_back (arg1);
989         m_arguments.push_back (arg2);
990     }
991 
992     ~CommandObjectSettingsAppend() override = default;
993 
994     // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
995     bool
996     WantsCompletion() override { return true; }
997 
998     int
999     HandleArgumentCompletion (Args &input,
1000                               int &cursor_index,
1001                               int &cursor_char_position,
1002                               OptionElementVector &opt_element_vector,
1003                               int match_start_point,
1004                               int max_return_elements,
1005                               bool &word_complete,
1006                               StringList &matches) override
1007     {
1008         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
1009 
1010         // Attempting to complete variable name
1011         if (cursor_index < 2)
1012             CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
1013                                                                 CommandCompletions::eSettingsNameCompletion,
1014                                                                 completion_str.c_str(),
1015                                                                 match_start_point,
1016                                                                 max_return_elements,
1017                                                                 nullptr,
1018                                                                 word_complete,
1019                                                                 matches);
1020 
1021         return matches.GetSize();
1022     }
1023 
1024 protected:
1025     bool
1026     DoExecute (const char *command, CommandReturnObject &result) override
1027     {
1028         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1029         Args cmd_args(command);
1030         const size_t argc = cmd_args.GetArgumentCount ();
1031 
1032         if (argc < 2)
1033         {
1034             result.AppendError ("'settings append' takes more arguments");
1035             result.SetStatus (eReturnStatusFailed);
1036             return false;
1037         }
1038 
1039         const char *var_name = cmd_args.GetArgumentAtIndex (0);
1040         if ((var_name == nullptr) || (var_name[0] == '\0'))
1041         {
1042             result.AppendError ("'settings append' command requires a valid variable name; No value supplied");
1043             result.SetStatus (eReturnStatusFailed);
1044             return false;
1045         }
1046 
1047         // Do not perform cmd_args.Shift() since StringRef is manipulating the
1048         // raw character string later on.
1049 
1050         // Split the raw command into var_name and value pair.
1051         llvm::StringRef raw_str(command);
1052         std::string var_value_string = raw_str.split(var_name).second.str();
1053         const char *var_value_cstr = Args::StripSpaces(var_value_string, true, true, false);
1054 
1055         Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
1056                                                                   eVarSetOperationAppend,
1057                                                                   var_name,
1058                                                                   var_value_cstr));
1059         if (error.Fail())
1060         {
1061             result.AppendError (error.AsCString());
1062             result.SetStatus (eReturnStatusFailed);
1063             return false;
1064         }
1065 
1066         return result.Succeeded();
1067     }
1068 };
1069 
1070 //-------------------------------------------------------------------------
1071 // CommandObjectSettingsClear
1072 //-------------------------------------------------------------------------
1073 
1074 class CommandObjectSettingsClear : public CommandObjectParsed
1075 {
1076 public:
1077     CommandObjectSettingsClear(CommandInterpreter &interpreter)
1078         : CommandObjectParsed(interpreter, "settings clear", "Clear a debugger setting array, dictionary, or string.",
1079                               nullptr)
1080     {
1081         CommandArgumentEntry arg;
1082         CommandArgumentData var_name_arg;
1083 
1084         // Define the first (and only) variant of this arg.
1085         var_name_arg.arg_type = eArgTypeSettingVariableName;
1086         var_name_arg.arg_repetition = eArgRepeatPlain;
1087 
1088         // There is only one variant this argument could be; put it into the argument entry.
1089         arg.push_back (var_name_arg);
1090 
1091         // Push the data for the first argument into the m_arguments vector.
1092         m_arguments.push_back (arg);
1093     }
1094 
1095     ~CommandObjectSettingsClear() override = default;
1096 
1097     int
1098     HandleArgumentCompletion (Args &input,
1099                               int &cursor_index,
1100                               int &cursor_char_position,
1101                               OptionElementVector &opt_element_vector,
1102                               int match_start_point,
1103                               int max_return_elements,
1104                               bool &word_complete,
1105                               StringList &matches) override
1106     {
1107         std::string completion_str (input.GetArgumentAtIndex (cursor_index), cursor_char_position);
1108 
1109         // Attempting to complete variable name
1110         if (cursor_index < 2)
1111             CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
1112                                                                 CommandCompletions::eSettingsNameCompletion,
1113                                                                 completion_str.c_str(),
1114                                                                 match_start_point,
1115                                                                 max_return_elements,
1116                                                                 nullptr,
1117                                                                 word_complete,
1118                                                                 matches);
1119 
1120         return matches.GetSize();
1121     }
1122 
1123 protected:
1124     bool
1125     DoExecute (Args& command, CommandReturnObject &result) override
1126     {
1127         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1128         const size_t argc = command.GetArgumentCount ();
1129 
1130         if (argc != 1)
1131         {
1132             result.AppendError ("'settings clear' takes exactly one argument");
1133             result.SetStatus (eReturnStatusFailed);
1134             return false;
1135         }
1136 
1137         const char *var_name = command.GetArgumentAtIndex (0);
1138         if ((var_name == nullptr) || (var_name[0] == '\0'))
1139         {
1140             result.AppendError ("'settings clear' command requires a valid variable name; No value supplied");
1141             result.SetStatus (eReturnStatusFailed);
1142             return false;
1143         }
1144 
1145         Error error(m_interpreter.GetDebugger().SetPropertyValue(&m_exe_ctx,
1146                                                                  eVarSetOperationClear,
1147                                                                  var_name,
1148                                                                  nullptr));
1149         if (error.Fail())
1150         {
1151             result.AppendError (error.AsCString());
1152             result.SetStatus (eReturnStatusFailed);
1153             return false;
1154         }
1155 
1156         return result.Succeeded();
1157     }
1158 };
1159 
1160 //-------------------------------------------------------------------------
1161 // CommandObjectMultiwordSettings
1162 //-------------------------------------------------------------------------
1163 
1164 CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(CommandInterpreter &interpreter)
1165     : CommandObjectMultiword(interpreter, "settings", "Commands for managing LLDB settings.",
1166                              "settings <subcommand> [<command-options>]")
1167 {
1168     LoadSubCommand ("set",           CommandObjectSP (new CommandObjectSettingsSet (interpreter)));
1169     LoadSubCommand ("show",          CommandObjectSP (new CommandObjectSettingsShow (interpreter)));
1170     LoadSubCommand ("list",          CommandObjectSP (new CommandObjectSettingsList (interpreter)));
1171     LoadSubCommand ("remove",        CommandObjectSP (new CommandObjectSettingsRemove (interpreter)));
1172     LoadSubCommand ("replace",       CommandObjectSP (new CommandObjectSettingsReplace (interpreter)));
1173     LoadSubCommand ("insert-before", CommandObjectSP (new CommandObjectSettingsInsertBefore (interpreter)));
1174     LoadSubCommand ("insert-after",  CommandObjectSP (new CommandObjectSettingsInsertAfter (interpreter)));
1175     LoadSubCommand ("append",        CommandObjectSP (new CommandObjectSettingsAppend (interpreter)));
1176     LoadSubCommand ("clear",         CommandObjectSP (new CommandObjectSettingsClear (interpreter)));
1177 }
1178 
1179 CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
1180