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/Core/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->ResetOptionValues();
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.Fail() || !options->VerifyOptions (result))
191         {
192             const char *error_cstr = error.AsCString();
193             if (error_cstr)
194             {
195                 // We got an error string, lets use that
196                 result.GetErrorStream().PutCString(error_cstr);
197             }
198             else
199             {
200                 // No error string, output the usage information into result
201                 options->GenerateOptionUsage (m_interpreter, result.GetErrorStream(), this);
202             }
203             // Set the return status to failed (this was an error).
204             result.SetStatus (eReturnStatusFailed);
205             return false;
206         }
207     }
208     return true;
209 }
210 bool
211 CommandObject::ExecuteWithOptions (Args& args, CommandReturnObject &result)
212 {
213     for (size_t i = 0; i < args.GetArgumentCount();  ++i)
214     {
215         const char *tmp_str = args.GetArgumentAtIndex (i);
216         if (tmp_str[0] == '`')  // back-quote
217             args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
218     }
219 
220     Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
221     if (process == NULL)
222     {
223         if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
224         {
225             result.AppendError ("Process must exist.");
226             result.SetStatus (eReturnStatusFailed);
227             return false;
228         }
229     }
230     else
231     {
232         StateType state = process->GetState();
233 
234         switch (state)
235         {
236 
237         case eStateAttaching:
238         case eStateLaunching:
239         case eStateSuspended:
240         case eStateCrashed:
241         case eStateStopped:
242             break;
243 
244         case eStateDetached:
245         case eStateExited:
246         case eStateUnloaded:
247             if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched))
248             {
249                 result.AppendError ("Process must be launched.");
250                 result.SetStatus (eReturnStatusFailed);
251                 return false;
252             }
253             break;
254 
255         case eStateRunning:
256         case eStateStepping:
257             if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused))
258             {
259                 result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
260                 result.SetStatus (eReturnStatusFailed);
261                 return false;
262             }
263         }
264     }
265 
266     if (!ParseOptions (args, result))
267         return false;
268 
269     // Call the command-specific version of 'Execute', passing it the already processed arguments.
270     return Execute (args, result);
271 }
272 
273 class CommandDictCommandPartialMatch
274 {
275     public:
276         CommandDictCommandPartialMatch (const char *match_str)
277         {
278             m_match_str = match_str;
279         }
280         bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
281         {
282             // A NULL or empty string matches everything.
283             if (m_match_str == NULL || *m_match_str == '\0')
284                 return 1;
285 
286             size_t found = map_element.first.find (m_match_str, 0);
287             if (found == std::string::npos)
288                 return 0;
289             else
290                 return found == 0;
291         }
292 
293     private:
294         const char *m_match_str;
295 };
296 
297 int
298 CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
299                                               StringList &matches)
300 {
301     int number_added = 0;
302     CommandDictCommandPartialMatch matcher(cmd_str);
303 
304     CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
305 
306     while (matching_cmds != in_map.end())
307     {
308         ++number_added;
309         matches.AppendString((*matching_cmds).first.c_str());
310         matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
311     }
312     return number_added;
313 }
314 
315 int
316 CommandObject::HandleCompletion
317 (
318     Args &input,
319     int &cursor_index,
320     int &cursor_char_position,
321     int match_start_point,
322     int max_return_elements,
323     bool &word_complete,
324     StringList &matches
325 )
326 {
327     if (WantsRawCommandString())
328     {
329         // FIXME: Abstract telling the completion to insert the completion character.
330         matches.Clear();
331         return -1;
332     }
333     else
334     {
335         // Can we do anything generic with the options?
336         Options *cur_options = GetOptions();
337         CommandReturnObject result;
338         OptionElementVector opt_element_vector;
339 
340         if (cur_options != NULL)
341         {
342             // Re-insert the dummy command name string which will have been
343             // stripped off:
344             input.Unshift ("dummy-string");
345             cursor_index++;
346 
347 
348             // I stick an element on the end of the input, because if the last element is
349             // option that requires an argument, getopt_long will freak out.
350 
351             input.AppendArgument ("<FAKE-VALUE>");
352 
353             input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index);
354 
355             input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
356 
357             bool handled_by_options;
358             handled_by_options = cur_options->HandleOptionCompletion (m_interpreter,
359                                                                       input,
360                                                                       opt_element_vector,
361                                                                       cursor_index,
362                                                                       cursor_char_position,
363                                                                       match_start_point,
364                                                                       max_return_elements,
365                                                                       word_complete,
366                                                                       matches);
367             if (handled_by_options)
368                 return matches.GetSize();
369         }
370 
371         // If we got here, the last word is not an option or an option argument.
372         return HandleArgumentCompletion (input,
373                                          cursor_index,
374                                          cursor_char_position,
375                                          opt_element_vector,
376                                          match_start_point,
377                                          max_return_elements,
378                                          word_complete,
379                                          matches);
380     }
381 }
382 
383 bool
384 CommandObject::HelpTextContainsWord (const char *search_word)
385 {
386     const char *short_help;
387     const char *long_help;
388     const char *syntax_help;
389     std::string options_usage_help;
390 
391 
392     bool found_word = false;
393 
394     short_help = GetHelp();
395     long_help = GetHelpLong();
396     syntax_help = GetSyntax();
397 
398     if (strcasestr (short_help, search_word))
399         found_word = true;
400     else if (strcasestr (long_help, search_word))
401         found_word = true;
402     else if (strcasestr (syntax_help, search_word))
403         found_word = true;
404 
405     if (!found_word
406         && GetOptions() != NULL)
407     {
408         StreamString usage_help;
409         GetOptions()->GenerateOptionUsage (m_interpreter, usage_help, this);
410         if (usage_help.GetSize() > 0)
411         {
412             const char *usage_text = usage_help.GetData();
413             if (strcasestr (usage_text, search_word))
414               found_word = true;
415         }
416     }
417 
418     return found_word;
419 }
420 
421 int
422 CommandObject::GetNumArgumentEntries  ()
423 {
424     return m_arguments.size();
425 }
426 
427 CommandObject::CommandArgumentEntry *
428 CommandObject::GetArgumentEntryAtIndex (int idx)
429 {
430     if (idx < m_arguments.size())
431         return &(m_arguments[idx]);
432 
433     return NULL;
434 }
435 
436 CommandObject::ArgumentTableEntry *
437 CommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
438 {
439     const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
440 
441     for (int i = 0; i < eArgTypeLastArg; ++i)
442         if (table[i].arg_type == arg_type)
443             return (ArgumentTableEntry *) &(table[i]);
444 
445     return NULL;
446 }
447 
448 void
449 CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter)
450 {
451     const ArgumentTableEntry* table = CommandObject::GetArgumentTable();
452     ArgumentTableEntry *entry = (ArgumentTableEntry *) &(table[arg_type]);
453 
454     // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
455 
456     if (entry->arg_type != arg_type)
457         entry = CommandObject::FindArgumentDataByType (arg_type);
458 
459     if (!entry)
460         return;
461 
462     StreamString name_str;
463     name_str.Printf ("<%s>", entry->arg_name);
464 
465     if (entry->help_function != NULL)
466         interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", (*(entry->help_function)) (),
467                                              name_str.GetSize());
468     else
469         interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize());
470 }
471 
472 const char *
473 CommandObject::GetArgumentName (CommandArgumentType arg_type)
474 {
475     ArgumentTableEntry *entry = (ArgumentTableEntry *) &(CommandObject::GetArgumentTable()[arg_type]);
476 
477     // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
478 
479     if (entry->arg_type != arg_type)
480         entry = CommandObject::FindArgumentDataByType (arg_type);
481 
482     if (entry)
483         return entry->arg_name;
484 
485     StreamString str;
486     str << "Arg name for type (" << arg_type << ") not in arg table!";
487     return str.GetData();
488 }
489 
490 bool
491 CommandObject::IsPairType (lldb::ArgumentRepetitionType arg_repeat_type)
492 {
493     if ((arg_repeat_type == eArgRepeatPairPlain)
494         ||  (arg_repeat_type == eArgRepeatPairOptional)
495         ||  (arg_repeat_type == eArgRepeatPairPlus)
496         ||  (arg_repeat_type == eArgRepeatPairStar)
497         ||  (arg_repeat_type == eArgRepeatPairRange)
498         ||  (arg_repeat_type == eArgRepeatPairRangeOptional))
499         return true;
500 
501     return false;
502 }
503 
504 void
505 CommandObject::GetFormattedCommandArguments (Stream &str)
506 {
507     int num_args = m_arguments.size();
508     for (int i = 0; i < num_args; ++i)
509     {
510         if (i > 0)
511             str.Printf (" ");
512         CommandArgumentEntry arg_entry = m_arguments[i];
513         int num_alternatives = arg_entry.size();
514 
515         if ((num_alternatives == 2)
516             && IsPairType (arg_entry[0].arg_repetition))
517         {
518             const char *first_name = GetArgumentName (arg_entry[0].arg_type);
519             const char *second_name = GetArgumentName (arg_entry[1].arg_type);
520             switch (arg_entry[0].arg_repetition)
521             {
522                 case eArgRepeatPairPlain:
523                     str.Printf ("<%s> <%s>", first_name, second_name);
524                     break;
525                 case eArgRepeatPairOptional:
526                     str.Printf ("[<%s> <%s>]", first_name, second_name);
527                     break;
528                 case eArgRepeatPairPlus:
529                     str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name);
530                     break;
531                 case eArgRepeatPairStar:
532                     str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name);
533                     break;
534                 case eArgRepeatPairRange:
535                     str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name);
536                     break;
537                 case eArgRepeatPairRangeOptional:
538                     str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name);
539                     break;
540             }
541         }
542         else
543         {
544             StreamString names;
545             for (int j = 0; j < num_alternatives; ++j)
546             {
547                 if (j > 0)
548                     names.Printf (" | ");
549                 names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type));
550             }
551             switch (arg_entry[0].arg_repetition)
552             {
553                 case eArgRepeatPlain:
554                     str.Printf ("<%s>", names.GetData());
555                     break;
556                 case eArgRepeatPlus:
557                     str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData());
558                     break;
559                 case eArgRepeatStar:
560                     str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
561                     break;
562                 case eArgRepeatOptional:
563                     str.Printf ("[<%s>]", names.GetData());
564                     break;
565                 case eArgRepeatRange:
566                     str.Printf ("<%s_1> .. <%s_n>", names.GetData());
567             }
568         }
569     }
570 }
571 
572 const CommandArgumentType
573 CommandObject::LookupArgumentName (const char *arg_name)
574 {
575     CommandArgumentType return_type = eArgTypeLastArg;
576 
577     std::string arg_name_str (arg_name);
578     size_t len = arg_name_str.length();
579     if (arg_name[0] == '<'
580         && arg_name[len-1] == '>')
581         arg_name_str = arg_name_str.substr (1, len-2);
582 
583     for (int i = 0; i < eArgTypeLastArg; ++i)
584         if (arg_name_str.compare (g_arguments_data[i].arg_name) == 0)
585             return_type = g_arguments_data[i].arg_type;
586 
587     return return_type;
588 }
589 
590 static const char *
591 BreakpointIDHelpTextCallback ()
592 {
593     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).";
594 }
595 
596 static const char *
597 BreakpointIDRangeHelpTextCallback ()
598 {
599     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.";
600 }
601 
602 CommandObject::ArgumentTableEntry
603 CommandObject::g_arguments_data[] =
604 {
605     { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, NULL, "A valid address in the target program's execution space." },
606     { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, NULL, "The name of an abbreviation (alias) for a debugger command." },
607     { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, NULL, "Command options to be used as part of an alias (abbreviation) definition.  (See 'help commands alias' for more information.)" },
608     { eArgTypeArchitecture, "arch", CommandCompletions::eNoCompletion, NULL, "The architecture name, e.g. i386 or x86_64." },
609     { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, NULL, "A Boolean value: 'true' or 'false'" },
610     { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, BreakpointIDHelpTextCallback, NULL },
611     { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, BreakpointIDRangeHelpTextCallback, NULL },
612     { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, NULL, "Number of bytes to use." },
613     { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, NULL, "A debugger command (may be multiple words), without any options or arguments." },
614     { eArgTypeCount, "count", CommandCompletions::eNoCompletion, NULL, "An unsigned integer." },
615     { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
616     { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
617     { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, NULL, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
618     { eArgTypeFilename, "filename", CommandCompletions::eNoCompletion, NULL, "The name of a file (can include path)." },
619     { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
620     { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, NULL, "Index into a thread's list of frames." },
621     { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
622     { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, NULL, "The name of a function." },
623     { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, NULL, "An index into a list." },
624     { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, NULL, "Line number in a source file." },
625     { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, NULL, "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." },
626     { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, NULL, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." },
627     { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, NULL, "A C++ method name." },
628     { eArgTypeName, "name", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
629     { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
630     { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, NULL, "The number of lines to use." },
631     { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, NULL, "The number of items per line to display." },
632     { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
633     { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
634     { eArgTypeOneLiner, "one-line-breakpoint-command", CommandCompletions::eNoCompletion, NULL, "A breakpoint command that is entered as a single line of text." },
635     { eArgTypePath, "path", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
636     { eArgTypePid, "pid", CommandCompletions::eNoCompletion, NULL, "The process ID number." },
637     { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
638     { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, NULL, "The name of the process." },
639     { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, NULL, "The name of the thread queue." },
640     { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, NULL, "A register name." },
641     { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, NULL, "A regular expression." },
642     { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, NULL, "Arguments to be passed to the target program when it starts executing." },
643     { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
644     { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, NULL, "The scripting language to be used for script-based commands.  Currently only Python is valid." },
645     { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, NULL, "The word for which you wish to search for information about." },
646     { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, NULL, "An Objective-C selector name." },
647     { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, NULL, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
648     { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, NULL, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
649     { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, NULL, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
650     { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, NULL, "The name of a settable internal debugger variable.  Type 'settings list' to see a complete list of such variables." },
651     { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, NULL, "The name of a shared library." },
652     { eArgTypeSourceFile, "source-file", CommandCompletions::eNoCompletion, NULL, "The name of a source file.." },
653     { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, NULL, "Specify a sort order when dumping lists." },
654     { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
655     { eArgTypeSymbol, "symbol", CommandCompletions::eNoCompletion, NULL, "Any symbol name (function name, variable, argument, etc.)" },
656     { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, NULL, "Thread ID number." },
657     { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, NULL, "Index into the process' list of threads." },
658     { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, NULL, "The thread's name." },
659     { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, NULL, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
660     { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, NULL, "The name of a variable in your program." },
661     { eArgTypeValue, "value", CommandCompletions::eNoCompletion, NULL, "A value could be anything, depending on where and how it is used." },
662     { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, NULL, "Help text goes here." },
663     { eArgTypeNone, "none", CommandCompletions::eNoCompletion, NULL, "No help available for this." },
664 };
665 
666 const CommandObject::ArgumentTableEntry*
667 CommandObject::GetArgumentTable ()
668 {
669     return CommandObject::g_arguments_data;
670 }
671 
672 
673