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