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