blob: 69b178da46ba674bec5d4bb8a744ac8c0955373c [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "lldb/Interpreter/CommandObjectMultiword.h"
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16// Project includes
Greg Clayton66111032010-06-23 01:19:29 +000017#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Interpreter/CommandInterpreter.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000019#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020#include "lldb/Interpreter/CommandReturnObject.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25//-------------------------------------------------------------------------
26// CommandObjectMultiword
27//-------------------------------------------------------------------------
28
29CommandObjectMultiword::CommandObjectMultiword
30(
Greg Claytona7015092010-09-18 01:14:36 +000031 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032 const char *name,
33 const char *help,
34 const char *syntax,
35 uint32_t flags
36) :
Daniel Malead82ac9e2013-02-21 21:18:07 +000037 CommandObject (interpreter, name, help, syntax, flags),
38 m_can_be_removed(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039{
40}
41
42CommandObjectMultiword::~CommandObjectMultiword ()
43{
44}
45
46CommandObjectSP
47CommandObjectMultiword::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);
Johnny Chence814962010-12-01 01:04:22 +000055 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);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059 return_cmd_sp = pos->second;
Johnny Chence814962010-12-01 01:04:22 +000060 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061 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
84CommandObject *
85CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
86{
87 return GetSubcommandSP(sub_cmd, matches).get();
88}
89
90bool
Greg Clayton66111032010-06-23 01:19:29 +000091CommandObjectMultiword::LoadSubCommand
92(
Greg Clayton66111032010-06-23 01:19:29 +000093 const char *name,
94 const CommandObjectSP& cmd_obj
95)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000096{
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;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000104 }
105 else
106 success = false;
107
108 return success;
109}
110
111bool
Jim Ingham5a988412012-06-08 21:56:10 +0000112CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113{
Jim Ingham5a988412012-06-08 21:56:10 +0000114 Args args (args_string);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115 const size_t argc = args.GetArgumentCount();
116 if (argc == 0)
117 {
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000118 this->CommandObject::GenerateHelpText (result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119 }
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 {
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000128 this->CommandObject::GenerateHelpText (result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000129 }
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
Jim Ingham5a988412012-06-08 21:56:10 +0000141 sub_cmd_obj->Execute (args_string, result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000142 }
143 else
144 {
145 std::string error_msg;
Greg Claytonc7bece562013-01-25 18:06:21 +0000146 const size_t num_subcmd_matches = matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147 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:");
Greg Claytonc7bece562013-01-25 18:06:21 +0000161 for (size_t i = 0; i < num_subcmd_matches; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 {
163 error_msg.append ("\n\t");
164 error_msg.append (matches.GetStringAtIndex (i));
165 }
166 }
167 error_msg.append ("\n");
Greg Claytonc7bece562013-01-25 18:06:21 +0000168 result.AppendRawError (error_msg.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 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
183void
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000184CommandObjectMultiword::GenerateHelpText (Stream &output_stream)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000185{
186 // First time through here, generate the help text for the object and
187 // push it to the return result object as well
188
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000189 output_stream.PutCString ("The following subcommands are supported:\n\n");
190
191 CommandMap::iterator pos;
Greg Claytona7015092010-09-18 01:14:36 +0000192 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193
Greg Clayton12fc3e02010-08-26 22:05:43 +0000194 if (max_len)
195 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000196
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);
Caroline Ticee139cf22010-10-01 17:46:38 +0000201 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).");
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000205 m_interpreter.OutputFormattedHelpText (output_stream,
Caroline Ticee139cf22010-10-01 17:46:38 +0000206 indented_command.c_str(),
207 "--",
208 help_text.c_str(),
209 max_len);
210 }
211 else
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000212 m_interpreter.OutputFormattedHelpText (output_stream,
Caroline Ticee139cf22010-10-01 17:46:38 +0000213 indented_command.c_str(),
214 "--",
215 pos->second->GetHelp(),
216 max_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000217 }
218
219 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000220}
221
222int
223CommandObjectMultiword::HandleCompletion
224(
225 Args &input,
226 int &cursor_index,
227 int &cursor_char_position,
228 int match_start_point,
229 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000230 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231 StringList &matches
232)
233{
Jim Ingham558ce122010-06-30 05:02:46 +0000234 // Any of the command matches will provide a complete word, otherwise the individual
235 // completers will override this.
236 word_complete = true;
237
Greg Clayton765d2e22013-12-10 19:14:04 +0000238 const char *arg0 = input.GetArgumentAtIndex(0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000239 if (cursor_index == 0)
240 {
Greg Clayton66111032010-06-23 01:19:29 +0000241 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
Greg Clayton765d2e22013-12-10 19:14:04 +0000242 arg0,
Greg Clayton66111032010-06-23 01:19:29 +0000243 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244
245 if (matches.GetSize() == 1
246 && matches.GetStringAtIndex(0) != NULL
Greg Clayton765d2e22013-12-10 19:14:04 +0000247 && strcmp (arg0, matches.GetStringAtIndex(0)) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000248 {
249 StringList temp_matches;
Greg Clayton765d2e22013-12-10 19:14:04 +0000250 CommandObject *cmd_obj = GetSubcommandObject (arg0,
Greg Clayton66111032010-06-23 01:19:29 +0000251 &temp_matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252 if (cmd_obj != NULL)
253 {
254 matches.DeleteStringAtIndex (0);
255 input.Shift();
256 cursor_char_position = 0;
257 input.AppendArgument ("");
Greg Claytona7015092010-09-18 01:14:36 +0000258 return cmd_obj->HandleCompletion (input,
259 cursor_index,
Greg Clayton66111032010-06-23 01:19:29 +0000260 cursor_char_position,
261 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +0000262 max_return_elements,
263 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000264 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000265 }
266 else
267 return matches.GetSize();
268 }
269 else
270 return matches.GetSize();
271 }
272 else
273 {
Greg Clayton765d2e22013-12-10 19:14:04 +0000274 CommandObject *sub_command_object = GetSubcommandObject (arg0,
Greg Clayton66111032010-06-23 01:19:29 +0000275 &matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 if (sub_command_object == NULL)
277 {
278 return matches.GetSize();
279 }
280 else
281 {
282 // Remove the one match that we got from calling GetSubcommandObject.
283 matches.DeleteStringAtIndex(0);
284 input.Shift();
285 cursor_index--;
Greg Claytona7015092010-09-18 01:14:36 +0000286 return sub_command_object->HandleCompletion (input,
Greg Clayton66111032010-06-23 01:19:29 +0000287 cursor_index,
288 cursor_char_position,
289 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +0000290 max_return_elements,
291 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000292 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293 }
294
295 }
296}
297
Jim Inghamebc09c32010-07-07 03:36:20 +0000298const char *
299CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
300{
Jim Inghamebc09c32010-07-07 03:36:20 +0000301 index++;
Greg Claytonede05852010-07-20 22:54:09 +0000302 if (current_command_args.GetArgumentCount() <= index)
303 return NULL;
Jim Inghamebc09c32010-07-07 03:36:20 +0000304 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
305 if (sub_command_object == NULL)
306 return NULL;
Jim Inghamebc09c32010-07-07 03:36:20 +0000307 return sub_command_object->GetRepeatCommand(current_command_args, index);
308}
309
Greg Clayton998255b2012-10-13 02:07:45 +0000310
311void
312CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
313 const char *search_word,
314 StringList &commands_found,
315 StringList &commands_help)
316{
317 CommandObject::CommandMap::const_iterator pos;
318
319 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
320 {
321 const char * command_name = pos->first.c_str();
322 CommandObject *sub_cmd_obj = pos->second.get();
323 StreamString complete_command_name;
324
325 complete_command_name.Printf ("%s %s", prefix, command_name);
326
327 if (sub_cmd_obj->HelpTextContainsWord (search_word))
328 {
329 commands_found.AppendString (complete_command_name.GetData());
330 commands_help.AppendString (sub_cmd_obj->GetHelp());
331 }
332
333 if (sub_cmd_obj->IsMultiwordObject())
334 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
335 search_word,
336 commands_found,
337 commands_help);
338 }
339}
340
341
342
343CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter,
344 const char *name,
345 const char *help,
346 const char *syntax,
347 uint32_t flags) :
348 CommandObject (interpreter, name, help, syntax, flags)
349{
350}
351
352CommandObjectProxy::~CommandObjectProxy ()
353{
354}
355
356const char *
357CommandObjectProxy::GetHelpLong ()
358{
359 CommandObject *proxy_command = GetProxyCommandObject();
360 if (proxy_command)
361 return proxy_command->GetHelpLong();
362 return NULL;
363}
364
Greg Clayton998255b2012-10-13 02:07:45 +0000365bool
366CommandObjectProxy::IsRemovable() const
367{
368 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
369 if (proxy_command)
370 return proxy_command->IsRemovable();
371 return false;
372}
373
374bool
375CommandObjectProxy::IsMultiwordObject ()
376{
377 CommandObject *proxy_command = GetProxyCommandObject();
378 if (proxy_command)
379 return proxy_command->IsMultiwordObject();
380 return false;
381}
382
383lldb::CommandObjectSP
384CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
385{
386 CommandObject *proxy_command = GetProxyCommandObject();
387 if (proxy_command)
388 return proxy_command->GetSubcommandSP(sub_cmd, matches);
389 return lldb::CommandObjectSP();
390}
391
392CommandObject *
393CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
394{
395 CommandObject *proxy_command = GetProxyCommandObject();
396 if (proxy_command)
397 return proxy_command->GetSubcommandObject(sub_cmd, matches);
398 return NULL;
399}
400
401void
402CommandObjectProxy::AproposAllSubCommands (const char *prefix,
403 const char *search_word,
404 StringList &commands_found,
405 StringList &commands_help)
406{
407 CommandObject *proxy_command = GetProxyCommandObject();
408 if (proxy_command)
409 return proxy_command->AproposAllSubCommands (prefix,
410 search_word,
411 commands_found,
412 commands_help);
413}
414
415bool
416CommandObjectProxy::LoadSubCommand (const char *cmd_name,
417 const lldb::CommandObjectSP& command_sp)
418{
419 CommandObject *proxy_command = GetProxyCommandObject();
420 if (proxy_command)
421 return proxy_command->LoadSubCommand (cmd_name, command_sp);
422 return false;
423}
424
425bool
426CommandObjectProxy::WantsRawCommandString()
427{
428 CommandObject *proxy_command = GetProxyCommandObject();
429 if (proxy_command)
430 return proxy_command->WantsRawCommandString();
431 return false;
432}
433
434bool
435CommandObjectProxy::WantsCompletion()
436{
437 CommandObject *proxy_command = GetProxyCommandObject();
438 if (proxy_command)
439 return proxy_command->WantsCompletion();
440 return false;
441}
442
443
444Options *
445CommandObjectProxy::GetOptions ()
446{
447 CommandObject *proxy_command = GetProxyCommandObject();
448 if (proxy_command)
449 return proxy_command->GetOptions ();
450 return NULL;
451}
452
453
454int
455CommandObjectProxy::HandleCompletion (Args &input,
456 int &cursor_index,
457 int &cursor_char_position,
458 int match_start_point,
459 int max_return_elements,
460 bool &word_complete,
461 StringList &matches)
462{
463 CommandObject *proxy_command = GetProxyCommandObject();
464 if (proxy_command)
465 return proxy_command->HandleCompletion (input,
466 cursor_index,
467 cursor_char_position,
468 match_start_point,
469 max_return_elements,
470 word_complete,
471 matches);
472 matches.Clear();
473 return 0;
474}
475int
476CommandObjectProxy::HandleArgumentCompletion (Args &input,
477 int &cursor_index,
478 int &cursor_char_position,
479 OptionElementVector &opt_element_vector,
480 int match_start_point,
481 int max_return_elements,
482 bool &word_complete,
483 StringList &matches)
484{
485 CommandObject *proxy_command = GetProxyCommandObject();
486 if (proxy_command)
487 return proxy_command->HandleArgumentCompletion (input,
488 cursor_index,
489 cursor_char_position,
490 opt_element_vector,
491 match_start_point,
492 max_return_elements,
493 word_complete,
494 matches);
495 matches.Clear();
496 return 0;
497}
498
499const char *
500CommandObjectProxy::GetRepeatCommand (Args &current_command_args,
501 uint32_t index)
502{
503 CommandObject *proxy_command = GetProxyCommandObject();
504 if (proxy_command)
505 return proxy_command->GetRepeatCommand (current_command_args, index);
506 return NULL;
507}
508
509bool
510CommandObjectProxy::Execute (const char *args_string,
511 CommandReturnObject &result)
512{
513 CommandObject *proxy_command = GetProxyCommandObject();
514 if (proxy_command)
515 return proxy_command->Execute (args_string, result);
516 result.AppendError ("command is not implemented");
517 result.SetStatus (eReturnStatusFailed);
518 return false;
519}
520
521