1 //===-- CommandObjectMultiword.cpp ------------------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/lldb-python.h"
11
12 #include "lldb/Interpreter/CommandObjectMultiword.h"
13 // C Includes
14 // C++ Includes
15 // Other libraries and framework includes
16 // Project includes
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Interpreter/Options.h"
20 #include "lldb/Interpreter/CommandReturnObject.h"
21
22 using namespace lldb;
23 using namespace lldb_private;
24
25 //-------------------------------------------------------------------------
26 // CommandObjectMultiword
27 //-------------------------------------------------------------------------
28
CommandObjectMultiword(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)29 CommandObjectMultiword::CommandObjectMultiword
30 (
31 CommandInterpreter &interpreter,
32 const char *name,
33 const char *help,
34 const char *syntax,
35 uint32_t flags
36 ) :
37 CommandObject (interpreter, name, help, syntax, flags),
38 m_can_be_removed(false)
39 {
40 }
41
~CommandObjectMultiword()42 CommandObjectMultiword::~CommandObjectMultiword ()
43 {
44 }
45
46 CommandObjectSP
GetSubcommandSP(const char * sub_cmd,StringList * matches)47 CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
48 {
49 CommandObjectSP return_cmd_sp;
50 CommandObject::CommandMap::iterator pos;
51
52 if (!m_subcommand_dict.empty())
53 {
54 pos = m_subcommand_dict.find (sub_cmd);
55 if (pos != m_subcommand_dict.end()) {
56 // An exact match; append the sub_cmd to the 'matches' string list.
57 if (matches)
58 matches->AppendString(sub_cmd);
59 return_cmd_sp = pos->second;
60 }
61 else
62 {
63
64 StringList local_matches;
65 if (matches == NULL)
66 matches = &local_matches;
67 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
68
69 if (num_matches == 1)
70 {
71 // Cleaner, but slightly less efficient would be to call back into this function, since I now
72 // know I have an exact match...
73
74 sub_cmd = matches->GetStringAtIndex(0);
75 pos = m_subcommand_dict.find(sub_cmd);
76 if (pos != m_subcommand_dict.end())
77 return_cmd_sp = pos->second;
78 }
79 }
80 }
81 return return_cmd_sp;
82 }
83
84 CommandObject *
GetSubcommandObject(const char * sub_cmd,StringList * matches)85 CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
86 {
87 return GetSubcommandSP(sub_cmd, matches).get();
88 }
89
90 bool
LoadSubCommand(const char * name,const CommandObjectSP & cmd_obj)91 CommandObjectMultiword::LoadSubCommand
92 (
93 const char *name,
94 const CommandObjectSP& cmd_obj
95 )
96 {
97 CommandMap::iterator pos;
98 bool success = true;
99
100 pos = m_subcommand_dict.find(name);
101 if (pos == m_subcommand_dict.end())
102 {
103 m_subcommand_dict[name] = cmd_obj;
104 }
105 else
106 success = false;
107
108 return success;
109 }
110
111 bool
Execute(const char * args_string,CommandReturnObject & result)112 CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
113 {
114 Args args (args_string);
115 const size_t argc = args.GetArgumentCount();
116 if (argc == 0)
117 {
118 this->CommandObject::GenerateHelpText (result);
119 }
120 else
121 {
122 const char *sub_command = args.GetArgumentAtIndex (0);
123
124 if (sub_command)
125 {
126 if (::strcasecmp (sub_command, "help") == 0)
127 {
128 this->CommandObject::GenerateHelpText (result);
129 }
130 else if (!m_subcommand_dict.empty())
131 {
132 StringList matches;
133 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
134 if (sub_cmd_obj != NULL)
135 {
136 // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there
137 // the command-specific version of Execute will be called, with the processed arguments.
138
139 args.Shift();
140
141 sub_cmd_obj->Execute (args_string, result);
142 }
143 else
144 {
145 std::string error_msg;
146 const size_t num_subcmd_matches = matches.GetSize();
147 if (num_subcmd_matches > 0)
148 error_msg.assign ("ambiguous command ");
149 else
150 error_msg.assign ("invalid command ");
151
152 error_msg.append ("'");
153 error_msg.append (GetCommandName());
154 error_msg.append (" ");
155 error_msg.append (sub_command);
156 error_msg.append ("'");
157
158 if (num_subcmd_matches > 0)
159 {
160 error_msg.append (" Possible completions:");
161 for (size_t i = 0; i < num_subcmd_matches; i++)
162 {
163 error_msg.append ("\n\t");
164 error_msg.append (matches.GetStringAtIndex (i));
165 }
166 }
167 error_msg.append ("\n");
168 result.AppendRawError (error_msg.c_str());
169 result.SetStatus (eReturnStatusFailed);
170 }
171 }
172 else
173 {
174 result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
175 result.SetStatus (eReturnStatusFailed);
176 }
177 }
178 }
179
180 return result.Succeeded();
181 }
182
183 void
GenerateHelpText(Stream & output_stream)184 CommandObjectMultiword::GenerateHelpText (Stream &output_stream)
185 {
186 // First time through here, generate the help text for the object and
187 // push it to the return result object as well
188
189 output_stream.PutCString ("The following subcommands are supported:\n\n");
190
191 CommandMap::iterator pos;
192 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
193
194 if (max_len)
195 max_len += 4; // Indent the output by 4 spaces.
196
197 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
198 {
199 std::string indented_command (" ");
200 indented_command.append (pos->first);
201 if (pos->second->WantsRawCommandString ())
202 {
203 std::string help_text (pos->second->GetHelp());
204 help_text.append (" This command takes 'raw' input (no need to quote stuff).");
205 m_interpreter.OutputFormattedHelpText (output_stream,
206 indented_command.c_str(),
207 "--",
208 help_text.c_str(),
209 max_len);
210 }
211 else
212 m_interpreter.OutputFormattedHelpText (output_stream,
213 indented_command.c_str(),
214 "--",
215 pos->second->GetHelp(),
216 max_len);
217 }
218
219 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
220 }
221
222 int
HandleCompletion(Args & input,int & cursor_index,int & cursor_char_position,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)223 CommandObjectMultiword::HandleCompletion
224 (
225 Args &input,
226 int &cursor_index,
227 int &cursor_char_position,
228 int match_start_point,
229 int max_return_elements,
230 bool &word_complete,
231 StringList &matches
232 )
233 {
234 // Any of the command matches will provide a complete word, otherwise the individual
235 // completers will override this.
236 word_complete = true;
237
238 if (cursor_index == 0)
239 {
240 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
241 input.GetArgumentAtIndex(0),
242 matches);
243
244 if (matches.GetSize() == 1
245 && matches.GetStringAtIndex(0) != NULL
246 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
247 {
248 StringList temp_matches;
249 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
250 &temp_matches);
251 if (cmd_obj != NULL)
252 {
253 matches.DeleteStringAtIndex (0);
254 input.Shift();
255 cursor_char_position = 0;
256 input.AppendArgument ("");
257 return cmd_obj->HandleCompletion (input,
258 cursor_index,
259 cursor_char_position,
260 match_start_point,
261 max_return_elements,
262 word_complete,
263 matches);
264 }
265 else
266 return matches.GetSize();
267 }
268 else
269 return matches.GetSize();
270 }
271 else
272 {
273 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
274 &matches);
275 if (sub_command_object == NULL)
276 {
277 return matches.GetSize();
278 }
279 else
280 {
281 // Remove the one match that we got from calling GetSubcommandObject.
282 matches.DeleteStringAtIndex(0);
283 input.Shift();
284 cursor_index--;
285 return sub_command_object->HandleCompletion (input,
286 cursor_index,
287 cursor_char_position,
288 match_start_point,
289 max_return_elements,
290 word_complete,
291 matches);
292 }
293
294 }
295 }
296
297 const char *
GetRepeatCommand(Args & current_command_args,uint32_t index)298 CommandObjectMultiword::GetRepeatCommand (Args ¤t_command_args, uint32_t index)
299 {
300 index++;
301 if (current_command_args.GetArgumentCount() <= index)
302 return NULL;
303 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
304 if (sub_command_object == NULL)
305 return NULL;
306 return sub_command_object->GetRepeatCommand(current_command_args, index);
307 }
308
309
310 void
AproposAllSubCommands(const char * prefix,const char * search_word,StringList & commands_found,StringList & commands_help)311 CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
312 const char *search_word,
313 StringList &commands_found,
314 StringList &commands_help)
315 {
316 CommandObject::CommandMap::const_iterator pos;
317
318 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
319 {
320 const char * command_name = pos->first.c_str();
321 CommandObject *sub_cmd_obj = pos->second.get();
322 StreamString complete_command_name;
323
324 complete_command_name.Printf ("%s %s", prefix, command_name);
325
326 if (sub_cmd_obj->HelpTextContainsWord (search_word))
327 {
328 commands_found.AppendString (complete_command_name.GetData());
329 commands_help.AppendString (sub_cmd_obj->GetHelp());
330 }
331
332 if (sub_cmd_obj->IsMultiwordObject())
333 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
334 search_word,
335 commands_found,
336 commands_help);
337 }
338 }
339
340
341
CommandObjectProxy(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)342 CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter,
343 const char *name,
344 const char *help,
345 const char *syntax,
346 uint32_t flags) :
347 CommandObject (interpreter, name, help, syntax, flags)
348 {
349 }
350
~CommandObjectProxy()351 CommandObjectProxy::~CommandObjectProxy ()
352 {
353 }
354
355 const char *
GetHelpLong()356 CommandObjectProxy::GetHelpLong ()
357 {
358 CommandObject *proxy_command = GetProxyCommandObject();
359 if (proxy_command)
360 return proxy_command->GetHelpLong();
361 return NULL;
362 }
363
364 bool
IsRemovable() const365 CommandObjectProxy::IsRemovable() const
366 {
367 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
368 if (proxy_command)
369 return proxy_command->IsRemovable();
370 return false;
371 }
372
373 bool
IsMultiwordObject()374 CommandObjectProxy::IsMultiwordObject ()
375 {
376 CommandObject *proxy_command = GetProxyCommandObject();
377 if (proxy_command)
378 return proxy_command->IsMultiwordObject();
379 return false;
380 }
381
382 lldb::CommandObjectSP
GetSubcommandSP(const char * sub_cmd,StringList * matches)383 CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
384 {
385 CommandObject *proxy_command = GetProxyCommandObject();
386 if (proxy_command)
387 return proxy_command->GetSubcommandSP(sub_cmd, matches);
388 return lldb::CommandObjectSP();
389 }
390
391 CommandObject *
GetSubcommandObject(const char * sub_cmd,StringList * matches)392 CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
393 {
394 CommandObject *proxy_command = GetProxyCommandObject();
395 if (proxy_command)
396 return proxy_command->GetSubcommandObject(sub_cmd, matches);
397 return NULL;
398 }
399
400 void
AproposAllSubCommands(const char * prefix,const char * search_word,StringList & commands_found,StringList & commands_help)401 CommandObjectProxy::AproposAllSubCommands (const char *prefix,
402 const char *search_word,
403 StringList &commands_found,
404 StringList &commands_help)
405 {
406 CommandObject *proxy_command = GetProxyCommandObject();
407 if (proxy_command)
408 return proxy_command->AproposAllSubCommands (prefix,
409 search_word,
410 commands_found,
411 commands_help);
412 }
413
414 bool
LoadSubCommand(const char * cmd_name,const lldb::CommandObjectSP & command_sp)415 CommandObjectProxy::LoadSubCommand (const char *cmd_name,
416 const lldb::CommandObjectSP& command_sp)
417 {
418 CommandObject *proxy_command = GetProxyCommandObject();
419 if (proxy_command)
420 return proxy_command->LoadSubCommand (cmd_name, command_sp);
421 return false;
422 }
423
424 bool
WantsRawCommandString()425 CommandObjectProxy::WantsRawCommandString()
426 {
427 CommandObject *proxy_command = GetProxyCommandObject();
428 if (proxy_command)
429 return proxy_command->WantsRawCommandString();
430 return false;
431 }
432
433 bool
WantsCompletion()434 CommandObjectProxy::WantsCompletion()
435 {
436 CommandObject *proxy_command = GetProxyCommandObject();
437 if (proxy_command)
438 return proxy_command->WantsCompletion();
439 return false;
440 }
441
442
443 Options *
GetOptions()444 CommandObjectProxy::GetOptions ()
445 {
446 CommandObject *proxy_command = GetProxyCommandObject();
447 if (proxy_command)
448 return proxy_command->GetOptions ();
449 return NULL;
450 }
451
452
453 int
HandleCompletion(Args & input,int & cursor_index,int & cursor_char_position,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)454 CommandObjectProxy::HandleCompletion (Args &input,
455 int &cursor_index,
456 int &cursor_char_position,
457 int match_start_point,
458 int max_return_elements,
459 bool &word_complete,
460 StringList &matches)
461 {
462 CommandObject *proxy_command = GetProxyCommandObject();
463 if (proxy_command)
464 return proxy_command->HandleCompletion (input,
465 cursor_index,
466 cursor_char_position,
467 match_start_point,
468 max_return_elements,
469 word_complete,
470 matches);
471 matches.Clear();
472 return 0;
473 }
474 int
HandleArgumentCompletion(Args & input,int & cursor_index,int & cursor_char_position,OptionElementVector & opt_element_vector,int match_start_point,int max_return_elements,bool & word_complete,StringList & matches)475 CommandObjectProxy::HandleArgumentCompletion (Args &input,
476 int &cursor_index,
477 int &cursor_char_position,
478 OptionElementVector &opt_element_vector,
479 int match_start_point,
480 int max_return_elements,
481 bool &word_complete,
482 StringList &matches)
483 {
484 CommandObject *proxy_command = GetProxyCommandObject();
485 if (proxy_command)
486 return proxy_command->HandleArgumentCompletion (input,
487 cursor_index,
488 cursor_char_position,
489 opt_element_vector,
490 match_start_point,
491 max_return_elements,
492 word_complete,
493 matches);
494 matches.Clear();
495 return 0;
496 }
497
498 const char *
GetRepeatCommand(Args & current_command_args,uint32_t index)499 CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args,
500 uint32_t index)
501 {
502 CommandObject *proxy_command = GetProxyCommandObject();
503 if (proxy_command)
504 return proxy_command->GetRepeatCommand (current_command_args, index);
505 return NULL;
506 }
507
508 bool
Execute(const char * args_string,CommandReturnObject & result)509 CommandObjectProxy::Execute (const char *args_string,
510 CommandReturnObject &result)
511 {
512 CommandObject *proxy_command = GetProxyCommandObject();
513 if (proxy_command)
514 return proxy_command->Execute (args_string, result);
515 result.AppendError ("command is not implemented");
516 result.SetStatus (eReturnStatusFailed);
517 return false;
518 }
519
520
521