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