1 //===-- CommandObject.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/Interpreter/CommandObject.h"
11 
12 #include <string>
13 #include <map>
14 
15 #include <getopt.h>
16 #include <stdlib.h>
17 #include <ctype.h>
18 
19 #include "lldb/Core/Address.h"
20 #include "lldb/Interpreter/Options.h"
21 
22 // These are for the Sourcename completers.
23 // FIXME: Make a separate file for the completers.
24 #include "lldb/Host/FileSpec.h"
25 #include "lldb/Core/FileSpecList.h"
26 #include "lldb/Target/Process.h"
27 #include "lldb/Target/Target.h"
28 
29 #include "lldb/Interpreter/CommandInterpreter.h"
30 #include "lldb/Interpreter/CommandReturnObject.h"
31 #include "lldb/Interpreter/ScriptInterpreter.h"
32 #include "lldb/Interpreter/ScriptInterpreterPython.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 //-------------------------------------------------------------------------
38 // CommandObject
39 //-------------------------------------------------------------------------
40 
41 CommandObject::CommandObject
42 (
43     CommandInterpreter &interpreter,
44     const char *name,
45     const char *help,
46     const char *syntax,
47     uint32_t flags
48 ) :
49     m_interpreter (interpreter),
50     m_cmd_name (name),
51     m_cmd_help_short (),
52     m_cmd_help_long (),
53     m_cmd_syntax (),
54     m_is_alias (false),
55     m_flags (flags),
56     m_arguments()
57 {
58     if (help && help[0])
59         m_cmd_help_short = help;
60     if (syntax && syntax[0])
61         m_cmd_syntax = syntax;
62 }
63 
64 CommandObject::~CommandObject ()
65 {
66 }
67 
68 const char *
69 CommandObject::GetHelp ()
70 {
71     return m_cmd_help_short.c_str();
72 }
73 
74 const char *
75 CommandObject::GetHelpLong ()
76 {
77     return m_cmd_help_long.c_str();
78 }
79 
80 const char *
81 CommandObject::GetSyntax ()
82 {
83     if (m_cmd_syntax.length() == 0)
84     {
85         StreamString syntax_str;
86         syntax_str.Printf ("%s", GetCommandName());
87         if (GetOptions() != NULL)
88             syntax_str.Printf (" <cmd-options>");
89         if (m_arguments.size() > 0)
90         {
91             syntax_str.Printf (" ");
92             GetFormattedCommandArguments (syntax_str);
93         }
94         m_cmd_syntax = syntax_str.GetData ();
95     }
96 
97     return m_cmd_syntax.c_str();
98 }
99 
100 const char *
101 CommandObject::Translate ()
102 {
103     //return m_cmd_func_name.c_str();
104     return "This function is currently not implemented.";
105 }
106 
107 const char *
108 CommandObject::GetCommandName ()
109 {
110     return m_cmd_name.c_str();
111 }
112 
113 void
114 CommandObject::SetCommandName (const char *name)
115 {
116     m_cmd_name = name;
117 }
118 
119 void
120 CommandObject::SetHelp (const char *cstr)
121 {
122     m_cmd_help_short = cstr;
123 }
124 
125 void
126 CommandObject::SetHelpLong (const char *cstr)
127 {
128     m_cmd_help_long = cstr;
129 }
130 
131 void
132 CommandObject::SetHelpLong (std::string str)
133 {
134     m_cmd_help_long = str;
135 }
136 
137 void
138 CommandObject::SetSyntax (const char *cstr)
139 {
140     m_cmd_syntax = cstr;
141 }
142 
143 Options *
144 CommandObject::GetOptions ()
145 {
146     // By default commands don't have options unless this virtual function
147     // is overridden by base classes.
148     return NULL;
149 }
150 
151 Flags&
152 CommandObject::GetFlags()
153 {
154     return m_flags;
155 }
156 
157 const Flags&
158 CommandObject::GetFlags() const
159 {
160     return m_flags;
161 }
162 
163 bool
164 CommandObject::ExecuteCommandString
165 (
166     const char *command_line,
167     CommandReturnObject &result
168 )
169 {
170     Args command_args(command_line);
171     return ExecuteWithOptions (command_args, result);
172 }
173 
174 bool
175 CommandObject::ParseOptions
176 (
177     Args& args,
178     CommandReturnObject &result
179 )
180 {
181     // See if the subclass has options?
182     Options *options = GetOptions();
183     if (options != NULL)
184     {
185         Error error;
186         options->NotifyOptionParsingStarting();
187 
188         // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
189         // so we need to push a dummy value into position zero.
190         args.Unshift("dummy_string");
191         error = args.ParseOptions (*options);
192 
193         // The "dummy_string" will have already been removed by ParseOptions,
194         // so no need to remove it.
195 
196         if (error.Success())
197             error = options->NotifyOptionParsingFinished();
198 
199         if (error.Success())
200         {
201             if (options->VerifyOptions (result))
202                 return true;
203         }
204         else
205         {
206             const char *error_cstr = error.AsCString();
207             if (error_cstr)
208             {
209                 // We got an error string, lets use that
210                 result.GetErrorStream().PutCString(error_cstr);
211             }
212             else
213             {
214                 // No error string, output the usage information into result
215                 options->GenerateOptionUsage (result.GetErrorStream(), this);
216             }
217         }
218         result.SetStatus (eReturnStatusFailed);
219         return false;
220     }
221     return true;
222 }
223 bool
224 CommandObject::ExecuteWithOptions (Args& args, CommandReturnObject &result)
225 {
226     for (size_t i = 0; i < args.GetArgumentCount();  ++i)
227     {
228         const char *tmp_str = args.GetArgumentAtIndex (i);
229         if (tmp_str[0] == '`')  // back-quote
230             args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
231     }
232 
233     if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
234     {
235         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
236         if (process == NULL)
237         {
238             // A process that is not running is considered paused.
239             if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
240             {
241                 result.AppendError ("Process must exist.");
242                 result.SetStatus (eReturnStatusFailed);
243                 return false;
244             }
245         }
246         else
247         {
248             StateType state = process->GetState();
249 
250             switch (state)
251             {
252             case eStateInvalid:
253             case eStateSuspended:
254             case eStateCrashed:
255             case eStateStopped:
256                 break;
257 
258             case eStateConnected:
259             case eStateAttaching:
260             case eStateLaunching:
261             case eStateDetached:
262             case eStateExited:
263             case eStateUnloaded:
264                 if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
265                 {
266                     result.AppendError ("Process must be launched.");
267                     result.SetStatus (eReturnStatusFailed);
268                     return false;
269                 }
270                 break;
271 
272             case eStateRunning:
273             case eStateStepping:
274                 if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused))
275                 {
276                     result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
277                     result.SetStatus (eReturnStatusFailed);
278                     return false;
279                 }
280             }
281         }
282     }
283 
284     if (!ParseOptions (args, result))
285         return false;
286 
287     // Call the command-specific version of 'Execute', passing it the already processed arguments.
288     return Execute (args, result);
289 }
290 
291 class CommandDictCommandPartialMatch
292 {
293     public:
294         CommandDictCommandPartialMatch (const char *match_str)
295         {
296             m_match_str = match_str;
297         }
298         bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
299         {
300             // A NULL or empty string matches everything.
301             if (m_match_str == NULL || *m_match_str == '\0')
302                 return 1;
303 
304             size_t found = map_element.first.find (m_match_str, 0);
305             if (found == std::string::npos)
306                 return 0;
307             else
308                 return found == 0;
309         }
310 
311     private:
312         const char *m_match_str;
313 };
314 
315 int
316 CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
317                                               StringList &matches)
318 {
319     int number_added = 0;
320     CommandDictCommandPartialMatch matcher(cmd_str);
321 
322     CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
323 
324     while (matching_cmds != in_map.end())
325     {
326         ++number_added;
327         matches.AppendString((*matching_cmds).first.c_str());
328         matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
329     }
330     return number_added;
331 }
332 
333 int
334 CommandObject::HandleCompletion
335 (
336     Args &input,
337     int &cursor_index,
338     int &cursor_char_position,
339     int match_start_point,
340     int max_return_elements,
341     bool &word_complete,
342     StringList &matches
343 )
344 {
345     if (WantsRawCommandString())
346     {
347         // FIXME: Abstract telling the completion to insert the completion character.
348         matches.Clear();
349         return -1;
350     }
351     else
352     {
353         // Can we do anything generic with the options?
354         Options *cur_options = GetOptions();
355         CommandReturnObject result;
356         OptionElementVector opt_element_vector;
357 
358         if (cur_options != NULL)
359         {
360             // Re-insert the dummy command name string which will have been
361             // stripped off:
362             input.Unshift ("dummy-string");
363             cursor_index++;
364 
365 
366             // I stick an element on the end of the input, because if the last element is
367             // option that requires an argument, getopt_long will freak out.
368 
369             input.AppendArgument ("<FAKE-VALUE>");
370 
371             input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index);
372 
373             input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
374 
375             bool handled_by_options;
376             handled_by_options = cur_options->HandleOptionCompletion (input,
377                                                                       opt_element_vector,
378                                                                       cursor_index,
379                                                                       cursor_char_position,
380                                                                       match_start_point,
381                                                                       max_return_elements,
382                                                                       word_complete,
383                                                                       matches);
384             if (handled_by_options)
385                 return matches.GetSize();
386         }
387 
388         // If we got here, the last word is not an option or an option argument.
389         return HandleArgumentCompletion (input,
390                                          cursor_index,
391                                          cursor_char_position,
392                                          opt_element_vector,
393                                          match_start_point,
394                                          max_return_elements,
395                                          word_complete,
396                                          matches);
397     }
398 }
399 
400 bool
401 CommandObject::HelpTextContainsWord (const char *search_word)
402 {
403     const char *short_help;
404     const char *long_help;
405     const char *syntax_help;
406     std::string options_usage_help;
407 
408 
409     bool found_word = false;
410 
411     short_help = GetHelp();
412     long_help = GetHelpLong();
413     syntax_help = GetSyntax();
414 
415     if (strcasestr (short_help, search_word))
416         found_word = true;
417     else if (strcasestr (long_help, search_word))
418         found_word = true;
419     else if (strcasestr (syntax_help, search_word))
420         found_word = true;
421 
422     if (!found_word
423         && GetOptions() != NULL)
424     {
425         StreamString usage_help;
426         GetOptions()->GenerateOptionUsage (usage_help, this);
427         if (usage_help.GetSize() > 0)
428         {
429             const char *usage_text = usage_help.GetData();
430             if (strcasestr (usage_text, search_word))
431               found_word = true;
432         }
433     }
434 
435     return found_word;
436 }
437 
438 int
439 CommandObject::GetNumArgumentEntries  ()
440 {
441     return m_arguments.size();
442 }
443 
444 CommandObject::CommandArgumentEntry *
445 CommandObject::GetArgumentEntryAtIndex (int idx)
446 {
447     if (idx < m_arguments.size())
448         return &(m_arguments[idx]);
449 
450     return NULL;
451 }
452 
453 CommandObject::ArgumentTableEntry *
454 CommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
455 {
456     const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
457 
458     for (int i = 0; i < eArgTypeLastArg; ++i)
459         if (table[i].arg_type == arg_type)
460             return (ArgumentTableEntry *) &(table[i]);
461 
462     return NULL;
463 }
464 
465 void
466 CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter)
467 {
468     const ArgumentTableEntry* table = CommandObject::GetArgumentTable();
469     ArgumentTableEntry *entry = (ArgumentTableEntry *) &(table[arg_type]);
470 
471     // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
472 
473     if (entry->arg_type != arg_type)
474         entry = CommandObject::FindArgumentDataByType (arg_type);
475 
476     if (!entry)
477         return;
478 
479     StreamString name_str;
480     name_str.Printf ("<%s>", entry->arg_name);
481 
482     if (entry->help_function)
483     {
484         const char* help_text = entry->help_function();
485         if (!entry->help_function.self_formatting)
486         {
487             interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,
488                                                  name_str.GetSize());
489         }
490         else
491         {
492             interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text,
493                                        name_str.GetSize());
494         }
495     }
496     else
497         interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize());
498 }
499 
500 const char *
501 CommandObject::GetArgumentName (CommandArgumentType arg_type)
502 {
503     ArgumentTableEntry *entry = (ArgumentTableEntry *) &(CommandObject::GetArgumentTable()[arg_type]);
504 
505     // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
506 
507     if (entry->arg_type != arg_type)
508         entry = CommandObject::FindArgumentDataByType (arg_type);
509 
510     if (entry)
511         return entry->arg_name;
512 
513     StreamString str;
514     str << "Arg name for type (" << arg_type << ") not in arg table!";
515     return str.GetData();
516 }
517 
518 bool
519 CommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type)
520 {
521     if ((arg_repeat_type == eArgRepeatPairPlain)
522         ||  (arg_repeat_type == eArgRepeatPairOptional)
523         ||  (arg_repeat_type == eArgRepeatPairPlus)
524         ||  (arg_repeat_type == eArgRepeatPairStar)
525         ||  (arg_repeat_type == eArgRepeatPairRange)
526         ||  (arg_repeat_type == eArgRepeatPairRangeOptional))
527         return true;
528 
529     return false;
530 }
531 
532 void
533 CommandObject::GetFormattedCommandArguments (Stream &str)
534 {
535     int num_args = m_arguments.size();
536     for (int i = 0; i < num_args; ++i)
537     {
538         if (i > 0)
539             str.Printf (" ");
540         CommandArgumentEntry arg_entry = m_arguments[i];
541         int num_alternatives = arg_entry.size();
542 
543         if ((num_alternatives == 2)
544             && IsPairType (arg_entry[0].arg_repetition))
545         {
546             const char *first_name = GetArgumentName (arg_entry[0].arg_type);
547             const char *second_name = GetArgumentName (arg_entry[1].arg_type);
548             switch (arg_entry[0].arg_repetition)
549             {
550                 case eArgRepeatPairPlain:
551                     str.Printf ("<%s> <%s>", first_name, second_name);
552                     break;
553                 case eArgRepeatPairOptional:
554                     str.Printf ("[<%s> <%s>]", first_name, second_name);
555                     break;
556                 case eArgRepeatPairPlus:
557                     str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name);
558                     break;
559                 case eArgRepeatPairStar:
560                     str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name);
561                     break;
562                 case eArgRepeatPairRange:
563                     str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name);
564                     break;
565                 case eArgRepeatPairRangeOptional:
566                     str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name);
567                     break;
568                 // Explicitly test for all the rest of the cases, so if new types get added we will notice the
569                 // missing case statement(s).
570                 case eArgRepeatPlain:
571                 case eArgRepeatOptional:
572                 case eArgRepeatPlus:
573                 case eArgRepeatStar:
574                 case eArgRepeatRange:
575                     // These should not be reached, as they should fail the IsPairType test above.
576                     break;
577             }
578         }
579         else
580         {
581             StreamString names;
582             for (int j = 0; j < num_alternatives; ++j)
583             {
584                 if (j > 0)
585                     names.Printf (" | ");
586                 names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type));
587             }
588             switch (arg_entry[0].arg_repetition)
589             {
590                 case eArgRepeatPlain:
591                     str.Printf ("<%s>", names.GetData());
592                     break;
593                 case eArgRepeatPlus:
594                     str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData());
595                     break;
596                 case eArgRepeatStar:
597                     str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
598                     break;
599                 case eArgRepeatOptional:
600                     str.Printf ("[<%s>]", names.GetData());
601                     break;
602                 case eArgRepeatRange:
603                     str.Printf ("<%s_1> .. <%s_n>", names.GetData(), names.GetData());
604                     break;
605                 // Explicitly test for all the rest of the cases, so if new types get added we will notice the
606                 // missing case statement(s).
607                 case eArgRepeatPairPlain:
608                 case eArgRepeatPairOptional:
609                 case eArgRepeatPairPlus:
610                 case eArgRepeatPairStar:
611                 case eArgRepeatPairRange:
612                 case eArgRepeatPairRangeOptional:
613                     // These should not be hit, as they should pass the IsPairType test above, and control should
614                     // have gone into the other branch of the if statement.
615                     break;
616             }
617         }
618     }
619 }
620 
621 CommandArgumentType
622 CommandObject::LookupArgumentName (const char *arg_name)
623 {
624     CommandArgumentType return_type = eArgTypeLastArg;
625 
626     std::string arg_name_str (arg_name);
627     size_t len = arg_name_str.length();
628     if (arg_name[0] == '<'
629         && arg_name[len-1] == '>')
630         arg_name_str = arg_name_str.substr (1, len-2);
631 
632     const ArgumentTableEntry *table = GetArgumentTable();
633     for (int i = 0; i < eArgTypeLastArg; ++i)
634         if (arg_name_str.compare (table[i].arg_name) == 0)
635             return_type = g_arguments_data[i].arg_type;
636 
637     return return_type;
638 }
639 
640 static const char *
641 BreakpointIDHelpTextCallback ()
642 {
643     return "Breakpoint ID's consist major and minor numbers;  the major number corresponds to the single entity that was created with a 'breakpoint set' command; the minor numbers correspond to all the locations that were actually found/set based on the major breakpoint.  A full breakpoint ID might look like 3.14, meaning the 14th location set for the 3rd breakpoint.  You can specify all the locations of a breakpoint by just indicating the major breakpoint number. A valid breakpoint id consists either of just the major id number, or the major number, a dot, and the location number (e.g. 3 or 3.2 could both be valid breakpoint ids).";
644 }
645 
646 static const char *
647 BreakpointIDRangeHelpTextCallback ()
648 {
649     return "A 'breakpoint id list' is a manner of specifying multiple breakpoints. This can be done  through several mechanisms.  The easiest way is to just enter a space-separated list of breakpoint ids.  To specify all the breakpoint locations under a major breakpoint, you can use the major breakpoint number followed by '.*', eg. '5.*' means all the locations under breakpoint 5.  You can also indicate a range of breakpoints by using <start-bp-id> - <end-bp-id>.  The start-bp-id and end-bp-id for a range can be any valid breakpoint ids.  It is not legal, however, to specify a range using specific locations that cross major breakpoint numbers.  I.e. 3.2 - 3.7 is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
650 }
651 
652 static const char *
653 FormatHelpTextCallback ()
654 {
655 
656     static char* help_text_ptr = NULL;
657 
658     if (help_text_ptr)
659         return help_text_ptr;
660 
661     StreamString sstr;
662     sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n";
663     for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
664     {
665         if (f != eFormatDefault)
666             sstr.PutChar('\n');
667 
668         char format_char = FormatManager::GetFormatAsFormatChar(f);
669         if (format_char)
670             sstr.Printf("'%c' or ", format_char);
671 
672         sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
673     }
674 
675     sstr.Flush();
676 
677     std::string data = sstr.GetString();
678 
679     help_text_ptr = new char[data.length()+1];
680 
681     data.copy(help_text_ptr, data.length());
682 
683     return help_text_ptr;
684 }
685 
686 static const char *
687 SummaryStringHelpTextCallback()
688 {
689     return
690         "A summary string is a way to extract information from variables in order to present them using a summary.\n"
691         "Summary strings contain static text, variables, scopes and control sequences:\n"
692         "  - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n"
693         "  - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n"
694         "  - Scopes are any sequence of text between { and }. Anything included in a scope will only appear in the output summary if there were no errors.\n"
695         "  - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n"
696         "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n"
697         "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n"
698         "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type"
699         " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be"
700         " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed."
701         " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n"
702         "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed."
703         "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression"
704         " path refers to:\n"
705         "  - if it is a scalar type (any basic type like int, float, ...) the expression is a bitfield, i.e. the bits indicated by the indexing operator are extracted out of the number"
706         " and displayed as an individual variable\n"
707         "  - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are"
708         " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n"
709         "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n"
710         "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the"
711         " special symbols only allowed as part of a variable:\n"
712         "    %V: show the value of the object by default\n"
713         "    %S: show the summary of the object by default\n"
714         "    %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n"
715         "    %L: show the location of the object (memory address or a register name)\n"
716         "    %#: show the number of children of the object\n"
717         "    %T: show the type of the object\n"
718         "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses"
719         " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would"
720         " count the number of actual elements stored in an std::list:\n"
721         "type summary add -s \"${svar%#}\" -x \"std::list<\"";
722 }
723 
724 static const char *
725 ExprPathHelpTextCallback()
726 {
727     return
728     "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n"
729     "For instance, given a class:\n"
730     "  class foo {\n"
731     "      int a;\n"
732     "      int b; .\n"
733     "      foo* next;\n"
734     "  };\n"
735     "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n"
736     "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n"
737     "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n"
738     "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n"
739     "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n"
740     "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract"
741     " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index"
742     " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the"
743     " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
744 }
745 
746 void
747 CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange)
748 {
749     CommandArgumentData id_arg;
750     CommandArgumentData id_range_arg;
751 
752     // Create the first variant for the first (and only) argument for this command.
753     id_arg.arg_type = ID;
754     id_arg.arg_repetition = eArgRepeatOptional;
755 
756     // Create the second variant for the first (and only) argument for this command.
757     id_range_arg.arg_type = IDRange;
758     id_range_arg.arg_repetition = eArgRepeatOptional;
759 
760     // The first (and only) argument for this command could be either an id or an id_range.
761     // Push both variants into the entry for the first argument for this command.
762     arg.push_back(id_arg);
763     arg.push_back(id_range_arg);
764 }
765 
766 const char *
767 CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
768 {
769     if (arg_type >=0 && arg_type < eArgTypeLastArg)
770         return g_arguments_data[arg_type].arg_name;
771     return NULL;
772 
773 }
774 
775 const char *
776 CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type)
777 {
778     if (arg_type >=0 && arg_type < eArgTypeLastArg)
779         return g_arguments_data[arg_type].help_text;
780     return NULL;
781 }
782 
783 CommandObject::ArgumentTableEntry
784 CommandObject::g_arguments_data[] =
785 {
786     { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." },
787     { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." },
788     { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { NULL, false }, "Command options to be used as part of an alias (abbreviation) definition.  (See 'help commands alias' for more information.)" },
789     { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { NULL, false }, "The architecture name, e.g. i386 or x86_64." },
790     { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { NULL, false }, "A Boolean value: 'true' or 'false'" },
791     { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, NULL },
792     { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, NULL },
793     { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { NULL, false }, "Number of bytes to use." },
794     { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." },
795     { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." },
796     { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
797     { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
798     { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
799     { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL },
800     { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
801     { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." },
802     { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL },
803     { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." },
804     { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
805     { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." },
806     { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." },
807     { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." },
808     { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." },
809     { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
810     { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { NULL, false }, "A C++ method name." },
811     { eArgTypeName, "name", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
812     { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
813     { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { NULL, false }, "The number of lines to use." },
814     { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { NULL, false }, "The number of items per line to display." },
815     { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
816     { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
817     { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." },
818     { eArgTypePath, "path", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
819     { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." },
820     { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
821     { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." },
822     { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." },
823     { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." },
824     { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." },
825     { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." },
826     { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." },
827     { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." },
828     { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." },
829     { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
830     { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { NULL, false }, "The scripting language to be used for script-based commands.  Currently only Python is valid." },
831     { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { NULL, false }, "The word for which you wish to search for information about." },
832     { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { NULL, false }, "An Objective-C selector name." },
833     { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
834     { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { NULL, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
835     { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
836     { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable.  Type 'settings list' to see a complete list of such variables." },
837     { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a shared library." },
838     { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { NULL, false }, "The name of a source file.." },
839     { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { NULL, false }, "Specify a sort order when dumping lists." },
840     { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
841     { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, NULL },
842     { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { NULL, false }, "Any symbol name (function name, variable, argument, etc.)" },
843     { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." },
844     { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." },
845     { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." },
846     { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
847     { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
848     { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." },
849     { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." },
850     { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
851     { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { NULL, false }, "No help available for this." },
852     { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { NULL, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
853     { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { NULL, false }, "Watchpoint IDs are positive integers." },
854     { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { NULL, false }, "For example, '1-3' or '1 to 3'." },
855     { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { NULL, false }, "Specify the type for a watchpoint." }
856 };
857 
858 const CommandObject::ArgumentTableEntry*
859 CommandObject::GetArgumentTable ()
860 {
861     // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration
862     assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
863     return CommandObject::g_arguments_data;
864 }
865 
866 
867