blob: c87a9d7cd58e50341cf8373eeaa68e8e70b8d562 [file] [log] [blame]
Chris Lattner24943d22010-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 Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +000017#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Interpreter/CommandInterpreter.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000019#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-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 Clayton238c0a12010-09-18 01:14:36 +000031 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000032 const char *name,
33 const char *help,
34 const char *syntax,
35 uint32_t flags
36) :
Daniel Malea004ccb32013-02-21 21:18:07 +000037 CommandObject (interpreter, name, help, syntax, flags),
38 m_can_be_removed(false)
Chris Lattner24943d22010-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 Chendc6c2632010-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 Lattner24943d22010-06-08 16:52:24 +000059 return_cmd_sp = pos->second;
Johnny Chendc6c2632010-12-01 01:04:22 +000060 }
Chris Lattner24943d22010-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 Clayton63094e02010-06-23 01:19:29 +000091CommandObjectMultiword::LoadSubCommand
92(
Greg Clayton63094e02010-06-23 01:19:29 +000093 const char *name,
94 const CommandObjectSP& cmd_obj
95)
Chris Lattner24943d22010-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;
Greg Clayton238c0a12010-09-18 01:14:36 +0000104 m_interpreter.CrossRegisterCommand (name, GetCommandName());
Chris Lattner24943d22010-06-08 16:52:24 +0000105 }
106 else
107 success = false;
108
109 return success;
110}
111
112bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000113CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000114{
Jim Inghamda26bd22012-06-08 21:56:10 +0000115 Args args (args_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000116 const size_t argc = args.GetArgumentCount();
117 if (argc == 0)
118 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000119 GenerateHelpText (result);
Chris Lattner24943d22010-06-08 16:52:24 +0000120 }
121 else
122 {
123 const char *sub_command = args.GetArgumentAtIndex (0);
124
125 if (sub_command)
126 {
127 if (::strcasecmp (sub_command, "help") == 0)
128 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000129 GenerateHelpText (result);
Chris Lattner24943d22010-06-08 16:52:24 +0000130 }
131 else if (!m_subcommand_dict.empty())
132 {
133 StringList matches;
134 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
135 if (sub_cmd_obj != NULL)
136 {
137 // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there
138 // the command-specific version of Execute will be called, with the processed arguments.
139
140 args.Shift();
141
Jim Inghamda26bd22012-06-08 21:56:10 +0000142 sub_cmd_obj->Execute (args_string, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000143 }
144 else
145 {
146 std::string error_msg;
Greg Clayton36da2aa2013-01-25 18:06:21 +0000147 const size_t num_subcmd_matches = matches.GetSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000148 if (num_subcmd_matches > 0)
149 error_msg.assign ("ambiguous command ");
150 else
151 error_msg.assign ("invalid command ");
152
153 error_msg.append ("'");
154 error_msg.append (GetCommandName());
155 error_msg.append (" ");
156 error_msg.append (sub_command);
157 error_msg.append ("'");
158
159 if (num_subcmd_matches > 0)
160 {
161 error_msg.append (" Possible completions:");
Greg Clayton36da2aa2013-01-25 18:06:21 +0000162 for (size_t i = 0; i < num_subcmd_matches; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000163 {
164 error_msg.append ("\n\t");
165 error_msg.append (matches.GetStringAtIndex (i));
166 }
167 }
168 error_msg.append ("\n");
Greg Clayton36da2aa2013-01-25 18:06:21 +0000169 result.AppendRawError (error_msg.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000170 result.SetStatus (eReturnStatusFailed);
171 }
172 }
173 else
174 {
175 result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
176 result.SetStatus (eReturnStatusFailed);
177 }
178 }
179 }
180
181 return result.Succeeded();
182}
183
184void
Greg Clayton238c0a12010-09-18 01:14:36 +0000185CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000186{
187 // First time through here, generate the help text for the object and
188 // push it to the return result object as well
189
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000190 Stream &output_stream = result.GetOutputStream();
Chris Lattner24943d22010-06-08 16:52:24 +0000191 output_stream.PutCString ("The following subcommands are supported:\n\n");
192
193 CommandMap::iterator pos;
Greg Clayton238c0a12010-09-18 01:14:36 +0000194 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000195
Greg Clayton65124ea2010-08-26 22:05:43 +0000196 if (max_len)
197 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner24943d22010-06-08 16:52:24 +0000198
199 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
200 {
201 std::string indented_command (" ");
202 indented_command.append (pos->first);
Caroline Ticefb355112010-10-01 17:46:38 +0000203 if (pos->second->WantsRawCommandString ())
204 {
205 std::string help_text (pos->second->GetHelp());
206 help_text.append (" This command takes 'raw' input (no need to quote stuff).");
207 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
208 indented_command.c_str(),
209 "--",
210 help_text.c_str(),
211 max_len);
212 }
213 else
214 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
215 indented_command.c_str(),
216 "--",
217 pos->second->GetHelp(),
218 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000219 }
220
221 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
222
223 result.SetStatus (eReturnStatusSuccessFinishNoResult);
224}
225
226int
227CommandObjectMultiword::HandleCompletion
228(
229 Args &input,
230 int &cursor_index,
231 int &cursor_char_position,
232 int match_start_point,
233 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000234 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000235 StringList &matches
236)
237{
Jim Ingham802f8b02010-06-30 05:02:46 +0000238 // Any of the command matches will provide a complete word, otherwise the individual
239 // completers will override this.
240 word_complete = true;
241
Chris Lattner24943d22010-06-08 16:52:24 +0000242 if (cursor_index == 0)
243 {
Greg Clayton63094e02010-06-23 01:19:29 +0000244 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
245 input.GetArgumentAtIndex(0),
246 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000247
248 if (matches.GetSize() == 1
249 && matches.GetStringAtIndex(0) != NULL
250 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
251 {
252 StringList temp_matches;
Greg Clayton63094e02010-06-23 01:19:29 +0000253 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
254 &temp_matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000255 if (cmd_obj != NULL)
256 {
257 matches.DeleteStringAtIndex (0);
258 input.Shift();
259 cursor_char_position = 0;
260 input.AppendArgument ("");
Greg Clayton238c0a12010-09-18 01:14:36 +0000261 return cmd_obj->HandleCompletion (input,
262 cursor_index,
Greg Clayton63094e02010-06-23 01:19:29 +0000263 cursor_char_position,
264 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000265 max_return_elements,
266 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000267 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000268 }
269 else
270 return matches.GetSize();
271 }
272 else
273 return matches.GetSize();
274 }
275 else
276 {
Greg Clayton63094e02010-06-23 01:19:29 +0000277 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
278 &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000279 if (sub_command_object == NULL)
280 {
281 return matches.GetSize();
282 }
283 else
284 {
285 // Remove the one match that we got from calling GetSubcommandObject.
286 matches.DeleteStringAtIndex(0);
287 input.Shift();
288 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +0000289 return sub_command_object->HandleCompletion (input,
Greg Clayton63094e02010-06-23 01:19:29 +0000290 cursor_index,
291 cursor_char_position,
292 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000293 max_return_elements,
294 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000295 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000296 }
297
298 }
299}
300
Jim Ingham767af882010-07-07 03:36:20 +0000301const char *
302CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
303{
Jim Ingham767af882010-07-07 03:36:20 +0000304 index++;
Greg Clayton578ddbb2010-07-20 22:54:09 +0000305 if (current_command_args.GetArgumentCount() <= index)
306 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000307 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
308 if (sub_command_object == NULL)
309 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000310 return sub_command_object->GetRepeatCommand(current_command_args, index);
311}
312
Greg Clayton13193d52012-10-13 02:07:45 +0000313
314void
315CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
316 const char *search_word,
317 StringList &commands_found,
318 StringList &commands_help)
319{
320 CommandObject::CommandMap::const_iterator pos;
321
322 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
323 {
324 const char * command_name = pos->first.c_str();
325 CommandObject *sub_cmd_obj = pos->second.get();
326 StreamString complete_command_name;
327
328 complete_command_name.Printf ("%s %s", prefix, command_name);
329
330 if (sub_cmd_obj->HelpTextContainsWord (search_word))
331 {
332 commands_found.AppendString (complete_command_name.GetData());
333 commands_help.AppendString (sub_cmd_obj->GetHelp());
334 }
335
336 if (sub_cmd_obj->IsMultiwordObject())
337 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
338 search_word,
339 commands_found,
340 commands_help);
341 }
342}
343
344
345
346CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter,
347 const char *name,
348 const char *help,
349 const char *syntax,
350 uint32_t flags) :
351 CommandObject (interpreter, name, help, syntax, flags)
352{
353}
354
355CommandObjectProxy::~CommandObjectProxy ()
356{
357}
358
359const char *
360CommandObjectProxy::GetHelpLong ()
361{
362 CommandObject *proxy_command = GetProxyCommandObject();
363 if (proxy_command)
364 return proxy_command->GetHelpLong();
365 return NULL;
366}
367
368void
369CommandObjectProxy::AddObject (const char *obj_name)
370{
371 CommandObject *proxy_command = GetProxyCommandObject();
372 if (proxy_command)
373 return proxy_command->AddObject (obj_name);
374}
375
376bool
377CommandObjectProxy::IsCrossRefObject ()
378{
379 CommandObject *proxy_command = GetProxyCommandObject();
380 if (proxy_command)
381 return proxy_command->IsCrossRefObject();
382 return false;
383}
384
385bool
386CommandObjectProxy::IsRemovable() const
387{
388 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
389 if (proxy_command)
390 return proxy_command->IsRemovable();
391 return false;
392}
393
394bool
395CommandObjectProxy::IsMultiwordObject ()
396{
397 CommandObject *proxy_command = GetProxyCommandObject();
398 if (proxy_command)
399 return proxy_command->IsMultiwordObject();
400 return false;
401}
402
403lldb::CommandObjectSP
404CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
405{
406 CommandObject *proxy_command = GetProxyCommandObject();
407 if (proxy_command)
408 return proxy_command->GetSubcommandSP(sub_cmd, matches);
409 return lldb::CommandObjectSP();
410}
411
412CommandObject *
413CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
414{
415 CommandObject *proxy_command = GetProxyCommandObject();
416 if (proxy_command)
417 return proxy_command->GetSubcommandObject(sub_cmd, matches);
418 return NULL;
419}
420
421void
422CommandObjectProxy::AproposAllSubCommands (const char *prefix,
423 const char *search_word,
424 StringList &commands_found,
425 StringList &commands_help)
426{
427 CommandObject *proxy_command = GetProxyCommandObject();
428 if (proxy_command)
429 return proxy_command->AproposAllSubCommands (prefix,
430 search_word,
431 commands_found,
432 commands_help);
433}
434
435bool
436CommandObjectProxy::LoadSubCommand (const char *cmd_name,
437 const lldb::CommandObjectSP& command_sp)
438{
439 CommandObject *proxy_command = GetProxyCommandObject();
440 if (proxy_command)
441 return proxy_command->LoadSubCommand (cmd_name, command_sp);
442 return false;
443}
444
445bool
446CommandObjectProxy::WantsRawCommandString()
447{
448 CommandObject *proxy_command = GetProxyCommandObject();
449 if (proxy_command)
450 return proxy_command->WantsRawCommandString();
451 return false;
452}
453
454bool
455CommandObjectProxy::WantsCompletion()
456{
457 CommandObject *proxy_command = GetProxyCommandObject();
458 if (proxy_command)
459 return proxy_command->WantsCompletion();
460 return false;
461}
462
463
464Options *
465CommandObjectProxy::GetOptions ()
466{
467 CommandObject *proxy_command = GetProxyCommandObject();
468 if (proxy_command)
469 return proxy_command->GetOptions ();
470 return NULL;
471}
472
473
474int
475CommandObjectProxy::HandleCompletion (Args &input,
476 int &cursor_index,
477 int &cursor_char_position,
478 int match_start_point,
479 int max_return_elements,
480 bool &word_complete,
481 StringList &matches)
482{
483 CommandObject *proxy_command = GetProxyCommandObject();
484 if (proxy_command)
485 return proxy_command->HandleCompletion (input,
486 cursor_index,
487 cursor_char_position,
488 match_start_point,
489 max_return_elements,
490 word_complete,
491 matches);
492 matches.Clear();
493 return 0;
494}
495int
496CommandObjectProxy::HandleArgumentCompletion (Args &input,
497 int &cursor_index,
498 int &cursor_char_position,
499 OptionElementVector &opt_element_vector,
500 int match_start_point,
501 int max_return_elements,
502 bool &word_complete,
503 StringList &matches)
504{
505 CommandObject *proxy_command = GetProxyCommandObject();
506 if (proxy_command)
507 return proxy_command->HandleArgumentCompletion (input,
508 cursor_index,
509 cursor_char_position,
510 opt_element_vector,
511 match_start_point,
512 max_return_elements,
513 word_complete,
514 matches);
515 matches.Clear();
516 return 0;
517}
518
519const char *
520CommandObjectProxy::GetRepeatCommand (Args &current_command_args,
521 uint32_t index)
522{
523 CommandObject *proxy_command = GetProxyCommandObject();
524 if (proxy_command)
525 return proxy_command->GetRepeatCommand (current_command_args, index);
526 return NULL;
527}
528
529bool
530CommandObjectProxy::Execute (const char *args_string,
531 CommandReturnObject &result)
532{
533 CommandObject *proxy_command = GetProxyCommandObject();
534 if (proxy_command)
535 return proxy_command->Execute (args_string, result);
536 result.AppendError ("command is not implemented");
537 result.SetStatus (eReturnStatusFailed);
538 return false;
539}
540
541