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