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::SetSyntax (const char *cstr)
133 {
134     m_cmd_syntax = cstr;
135 }
136 
137 Options *
138 CommandObject::GetOptions ()
139 {
140     // By default commands don't have options unless this virtual function
141     // is overridden by base classes.
142     return NULL;
143 }
144 
145 Flags&
146 CommandObject::GetFlags()
147 {
148     return m_flags;
149 }
150 
151 const Flags&
152 CommandObject::GetFlags() const
153 {
154     return m_flags;
155 }
156 
157 bool
158 CommandObject::ExecuteCommandString
159 (
160     const char *command_line,
161     CommandReturnObject &result
162 )
163 {
164     Args command_args(command_line);
165     return ExecuteWithOptions (command_args, result);
166 }
167 
168 bool
169 CommandObject::ParseOptions
170 (
171     Args& args,
172     CommandReturnObject &result
173 )
174 {
175     // See if the subclass has options?
176     Options *options = GetOptions();
177     if (options != NULL)
178     {
179         Error error;
180         options->NotifyOptionParsingStarting();
181 
182         // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1,
183         // so we need to push a dummy value into position zero.
184         args.Unshift("dummy_string");
185         error = args.ParseOptions (*options);
186 
187         // The "dummy_string" will have already been removed by ParseOptions,
188         // so no need to remove it.
189 
190         if (error.Success())
191             error = options->NotifyOptionParsingFinished();
192 
193         if (error.Success())
194         {
195             if (options->VerifyOptions (result))
196                 return true;
197         }
198         else
199         {
200             const char *error_cstr = error.AsCString();
201             if (error_cstr)
202             {
203                 // We got an error string, lets use that
204                 result.GetErrorStream().PutCString(error_cstr);
205             }
206             else
207             {
208                 // No error string, output the usage information into result
209                 options->GenerateOptionUsage (result.GetErrorStream(), this);
210             }
211         }
212         result.SetStatus (eReturnStatusFailed);
213         return false;
214     }
215     return true;
216 }
217 bool
218 CommandObject::ExecuteWithOptions (Args& args, CommandReturnObject &result)
219 {
220     for (size_t i = 0; i < args.GetArgumentCount();  ++i)
221     {
222         const char *tmp_str = args.GetArgumentAtIndex (i);
223         if (tmp_str[0] == '`')  // back-quote
224             args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
225     }
226 
227     if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
228     {
229         Process *process = m_interpreter.GetExecutionContext().process;
230         if (process == NULL)
231         {
232             // A process that is not running is considered paused.
233             if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
234             {
235                 result.AppendError ("Process must exist.");
236                 result.SetStatus (eReturnStatusFailed);
237                 return false;
238             }
239         }
240         else
241         {
242             StateType state = process->GetState();
243 
244             switch (state)
245             {
246             case eStateInvalid:
247             case eStateSuspended:
248             case eStateCrashed:
249             case eStateStopped:
250                 break;
251 
252             case eStateConnected:
253             case eStateAttaching:
254             case eStateLaunching:
255             case eStateDetached:
256             case eStateExited:
257             case eStateUnloaded:
258                 if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
259                 {
260                     result.AppendError ("Process must be launched.");
261                     result.SetStatus (eReturnStatusFailed);
262                     return false;
263                 }
264                 break;
265 
266             case eStateRunning:
267             case eStateStepping:
268                 if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused))
269                 {
270                     result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
271                     result.SetStatus (eReturnStatusFailed);
272                     return false;
273                 }
274             }
275         }
276     }
277 
278     if (!ParseOptions (args, result))
279         return false;
280 
281     // Call the command-specific version of 'Execute', passing it the already processed arguments.
282     return Execute (args, result);
283 }
284 
285 class CommandDictCommandPartialMatch
286 {
287     public:
288         CommandDictCommandPartialMatch (const char *match_str)
289         {
290             m_match_str = match_str;
291         }
292         bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
293         {
294             // A NULL or empty string matches everything.
295             if (m_match_str == NULL || *m_match_str == '\0')
296                 return 1;
297 
298             size_t found = map_element.first.find (m_match_str, 0);
299             if (found == std::string::npos)
300                 return 0;
301             else
302                 return found == 0;
303         }
304 
305     private:
306         const char *m_match_str;
307 };
308 
309 int
310 CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
311                                               StringList &matches)
312 {
313     int number_added = 0;
314     CommandDictCommandPartialMatch matcher(cmd_str);
315 
316     CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
317 
318     while (matching_cmds != in_map.end())
319     {
320         ++number_added;
321         matches.AppendString((*matching_cmds).first.c_str());
322         matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
323     }
324     return number_added;
325 }
326 
327 int
328 CommandObject::HandleCompletion
329 (
330     Args &input,
331     int &cursor_index,
332     int &cursor_char_position,
333     int match_start_point,
334     int max_return_elements,
335     bool &word_complete,
336     StringList &matches
337 )
338 {
339     if (WantsRawCommandString())
340     {
341         // FIXME: Abstract telling the completion to insert the completion character.
342         matches.Clear();
343         return -1;
344     }
345     else
346     {
347         // Can we do anything generic with the options?
348         Options *cur_options = GetOptions();
349         CommandReturnObject result;
350         OptionElementVector opt_element_vector;
351 
352         if (cur_options != NULL)
353         {
354             // Re-insert the dummy command name string which will have been
355             // stripped off:
356             input.Unshift ("dummy-string");
357             cursor_index++;
358 
359 
360             // I stick an element on the end of the input, because if the last element is
361             // option that requires an argument, getopt_long will freak out.
362 
363             input.AppendArgument ("<FAKE-VALUE>");
364 
365             input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index);
366 
367             input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
368 
369             bool handled_by_options;
370             handled_by_options = cur_options->HandleOptionCompletion (input,
371                                                                       opt_element_vector,
372                                                                       cursor_index,
373                                                                       cursor_char_position,
374                                                                       match_start_point,
375                                                                       max_return_elements,
376                                                                       word_complete,
377                                                                       matches);
378             if (handled_by_options)
379                 return matches.GetSize();
380         }
381 
382         // If we got here, the last word is not an option or an option argument.
383         return HandleArgumentCompletion (input,
384                                          cursor_index,
385                                          cursor_char_position,
386                                          opt_element_vector,
387                                          match_start_point,
388                                          max_return_elements,
389                                          word_complete,
390                                          matches);
391     }
392 }
393 
394 bool
395 CommandObject::HelpTextContainsWord (const char *search_word)
396 {
397     const char *short_help;
398     const char *long_help;
399     const char *syntax_help;
400     std::string options_usage_help;
401 
402 
403     bool found_word = false;
404 
405     short_help = GetHelp();
406     long_help = GetHelpLong();
407     syntax_help = GetSyntax();
408 
409     if (strcasestr (short_help, search_word))
410         found_word = true;
411     else if (strcasestr (long_help, search_word))
412         found_word = true;
413     else if (strcasestr (syntax_help, search_word))
414         found_word = true;
415 
416     if (!found_word
417         && GetOptions() != NULL)
418     {
419         StreamString usage_help;
420         GetOptions()->GenerateOptionUsage (usage_help, this);
421         if (usage_help.GetSize() > 0)
422         {
423             const char *usage_text = usage_help.GetData();
424             if (strcasestr (usage_text, search_word))
425               found_word = true;
426         }
427     }
428 
429     return found_word;
430 }
431 
432 int
433 CommandObject::GetNumArgumentEntries  ()
434 {
435     return m_arguments.size();
436 }
437 
438 CommandObject::CommandArgumentEntry *
439 CommandObject::GetArgumentEntryAtIndex (int idx)
440 {
441     if (idx < m_arguments.size())
442         return &(m_arguments[idx]);
443 
444     return NULL;
445 }
446 
447 CommandObject::ArgumentTableEntry *
448 CommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
449 {
450     const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
451 
452     for (int i = 0; i < eArgTypeLastArg; ++i)
453         if (table[i].arg_type == arg_type)
454             return (ArgumentTableEntry *) &(table[i]);
455 
456     return NULL;
457 }
458 
459 void
460 CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter)
461 {
462     const ArgumentTableEntry* table = CommandObject::GetArgumentTable();
463     ArgumentTableEntry *entry = (ArgumentTableEntry *) &(table[arg_type]);
464 
465     // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
466 
467     if (entry->arg_type != arg_type)
468         entry = CommandObject::FindArgumentDataByType (arg_type);
469 
470     if (!entry)
471         return;
472 
473     StreamString name_str;
474     name_str.Printf ("<%s>", entry->arg_name);
475 
476     if (entry->help_function)
477     {
478         const char* help_text = entry->help_function();
479         if (!entry->help_function.self_formatting)
480         {
481             interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,
482                                                  name_str.GetSize());
483         }
484         else
485         {
486             interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text,
487                                        name_str.GetSize());
488         }
489     }
490     else
491         interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize());
492 }
493 
494 const char *
495 CommandObject::GetArgumentName (CommandArgumentType arg_type)
496 {
497     ArgumentTableEntry *entry = (ArgumentTableEntry *) &(CommandObject::GetArgumentTable()[arg_type]);
498 
499     // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
500 
501     if (entry->arg_type != arg_type)
502         entry = CommandObject::FindArgumentDataByType (arg_type);
503 
504     if (entry)
505         return entry->arg_name;
506 
507     StreamString str;
508     str << "Arg name for type (" << arg_type << ") not in arg table!";
509     return str.GetData();
510 }
511 
512 bool
513 CommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type)
514 {
515     if ((arg_repeat_type == eArgRepeatPairPlain)
516         ||  (arg_repeat_type == eArgRepeatPairOptional)
517         ||  (arg_repeat_type == eArgRepeatPairPlus)
518         ||  (arg_repeat_type == eArgRepeatPairStar)
519         ||  (arg_repeat_type == eArgRepeatPairRange)
520         ||  (arg_repeat_type == eArgRepeatPairRangeOptional))
521         return true;
522 
523     return false;
524 }
525 
526 void
527 CommandObject::GetFormattedCommandArguments (Stream &str)
528 {
529     int num_args = m_arguments.size();
530     for (int i = 0; i < num_args; ++i)
531     {
532         if (i > 0)
533             str.Printf (" ");
534         CommandArgumentEntry arg_entry = m_arguments[i];
535         int num_alternatives = arg_entry.size();
536 
537         if ((num_alternatives == 2)
538             && IsPairType (arg_entry[0].arg_repetition))
539         {
540             const char *first_name = GetArgumentName (arg_entry[0].arg_type);
541             const char *second_name = GetArgumentName (arg_entry[1].arg_type);
542             switch (arg_entry[0].arg_repetition)
543             {
544                 case eArgRepeatPairPlain:
545                     str.Printf ("<%s> <%s>", first_name, second_name);
546                     break;
547                 case eArgRepeatPairOptional:
548                     str.Printf ("[<%s> <%s>]", first_name, second_name);
549                     break;
550                 case eArgRepeatPairPlus:
551                     str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name);
552                     break;
553                 case eArgRepeatPairStar:
554                     str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name);
555                     break;
556                 case eArgRepeatPairRange:
557                     str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name);
558                     break;
559                 case eArgRepeatPairRangeOptional:
560                     str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name);
561                     break;
562                 // Explicitly test for all the rest of the cases, so if new types get added we will notice the
563                 // missing case statement(s).
564                 case eArgRepeatPlain:
565                 case eArgRepeatOptional:
566                 case eArgRepeatPlus:
567                 case eArgRepeatStar:
568                 case eArgRepeatRange:
569                     // These should not be reached, as they should fail the IsPairType test above.
570                     break;
571             }
572         }
573         else
574         {
575             StreamString names;
576             for (int j = 0; j < num_alternatives; ++j)
577             {
578                 if (j > 0)
579                     names.Printf (" | ");
580                 names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type));
581             }
582             switch (arg_entry[0].arg_repetition)
583             {
584                 case eArgRepeatPlain:
585                     str.Printf ("<%s>", names.GetData());
586                     break;
587                 case eArgRepeatPlus:
588                     str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData());
589                     break;
590                 case eArgRepeatStar:
591                     str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
592                     break;
593                 case eArgRepeatOptional:
594                     str.Printf ("[<%s>]", names.GetData());
595                     break;
596                 case eArgRepeatRange:
597                     str.Printf ("<%s_1> .. <%s_n>", names.GetData());
598                     break;
599                 // Explicitly test for all the rest of the cases, so if new types get added we will notice the
600                 // missing case statement(s).
601                 case eArgRepeatPairPlain:
602                 case eArgRepeatPairOptional:
603                 case eArgRepeatPairPlus:
604                 case eArgRepeatPairStar:
605                 case eArgRepeatPairRange:
606                 case eArgRepeatPairRangeOptional:
607                     // These should not be hit, as they should pass the IsPairType test above, and control should
608                     // have gone into the other branch of the if statement.
609                     break;
610             }
611         }
612     }
613 }
614 
615 CommandArgumentType
616 CommandObject::LookupArgumentName (const char *arg_name)
617 {
618     CommandArgumentType return_type = eArgTypeLastArg;
619 
620     std::string arg_name_str (arg_name);
621     size_t len = arg_name_str.length();
622     if (arg_name[0] == '<'
623         && arg_name[len-1] == '>')
624         arg_name_str = arg_name_str.substr (1, len-2);
625 
626     for (int i = 0; i < eArgTypeLastArg; ++i)
627         if (arg_name_str.compare (g_arguments_data[i].arg_name) == 0)
628             return_type = g_arguments_data[i].arg_type;
629 
630     return return_type;
631 }
632 
633 static const char *
634 BreakpointIDHelpTextCallback ()
635 {
636     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).";
637 }
638 
639 static const char *
640 BreakpointIDRangeHelpTextCallback ()
641 {
642     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.";
643 }
644 
645 static const char *
646 FormatHelpTextCallback ()
647 {
648 
649     static char* help_text_ptr = NULL;
650 
651     if (help_text_ptr)
652         return help_text_ptr;
653 
654     StreamString sstr;
655     sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n";
656     for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
657     {
658         if (f != eFormatDefault)
659             sstr.PutChar('\n');
660 
661         char format_char = FormatManager::GetFormatAsFormatChar(f);
662         if (format_char)
663             sstr.Printf("'%c' or ", format_char);
664 
665         sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
666     }
667 
668     sstr.Flush();
669 
670     std::string data = sstr.GetString();
671 
672     help_text_ptr = new char[data.length()+1];
673 
674     data.copy(help_text_ptr, data.length());
675 
676     return help_text_ptr;
677 }
678 
679 static const char *
680 SummaryStringHelpTextCallback()
681 {
682     return
683         "A summary string is a way to extract information from variables in order to present them using a summary.\n"
684         "Summary strings contain static text, variables, scopes and control sequences:\n"
685         "  - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n"
686         "  - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n"
687         "  - 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"
688         "  - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n"
689         "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n"
690         "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"
691         "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"
692         " (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"
693         " ${var.x.y}). In expression paths you can use either . or -> without any difference in meaning. You can also use ${*var followed by an expression path and in that case"
694         " the object referred by the path will be dereferenced before being displayed. If the object is not a pointer, doing so will cause an error.\n"
695         "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."
696         "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"
697         " path refers to:\n"
698         "  - 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"
699         " and displayed as an individual variable\n"
700         "  - 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"
701         " 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"
702         "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.";
703 }
704 
705 const char *
706 CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
707 {
708     if (arg_type >=0 && arg_type < eArgTypeLastArg)
709         return g_arguments_data[arg_type].arg_name;
710     return NULL;
711 
712 }
713 
714 const char *
715 CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type)
716 {
717     if (arg_type >=0 && arg_type < eArgTypeLastArg)
718         return g_arguments_data[arg_type].help_text;
719     return NULL;
720 }
721 
722 CommandObject::ArgumentTableEntry
723 CommandObject::g_arguments_data[] =
724 {
725     { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." },
726     { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." },
727     { 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.)" },
728     { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { NULL, false }, "The architecture name, e.g. i386 or x86_64." },
729     { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { NULL, false }, "A Boolean value: 'true' or 'false'" },
730     { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, NULL },
731     { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, NULL },
732     { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { NULL, false }, "Number of bytes to use." },
733     { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." },
734     { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." },
735     { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." },
736     { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
737     { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
738     { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
739     { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." },
740     { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL },
741     { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." },
742     { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
743     { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." },
744     { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." },
745     { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." },
746     { 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." },
747     { 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)." },
748     { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { NULL, false }, "A C++ method name." },
749     { eArgTypeName, "name", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
750     { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
751     { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { NULL, false }, "The number of lines to use." },
752     { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { NULL, false }, "The number of items per line to display." },
753     { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
754     { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
755     { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." },
756     { eArgTypePath, "path", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
757     { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." },
758     { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
759     { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." },
760     { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." },
761     { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { NULL, false }, "A register name." },
762     { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." },
763     { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." },
764     { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
765     { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { NULL, false }, "The scripting language to be used for script-based commands.  Currently only Python is valid." },
766     { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { NULL, false }, "The word for which you wish to search for information about." },
767     { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { NULL, false }, "An Objective-C selector name." },
768     { 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)." },
769     { 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)." },
770     { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
771     { 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." },
772     { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a shared library." },
773     { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { NULL, false }, "The name of a source file.." },
774     { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { NULL, false }, "Specify a sort order when dumping lists." },
775     { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
776     { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, NULL },
777     { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { NULL, false }, "Any symbol name (function name, variable, argument, etc.)" },
778     { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." },
779     { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." },
780     { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." },
781     { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
782     { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." },
783     { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." },
784     { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." },
785     { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { NULL, false }, "No help available for this." },
786     { 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." }
787 };
788 
789 const CommandObject::ArgumentTableEntry*
790 CommandObject::GetArgumentTable ()
791 {
792     // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration
793     assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
794     return CommandObject::g_arguments_data;
795 }
796 
797 
798