blob: bfb5132a6443e99c3ab9b7007876d2773b30aa6b [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;
Chris Lattner24943d22010-06-08 16:52:24 +0000104 }
105 else
106 success = false;
107
108 return success;
109}
110
111bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000112CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000113{
Jim Inghamda26bd22012-06-08 21:56:10 +0000114 Args args (args_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000115 const size_t argc = args.GetArgumentCount();
116 if (argc == 0)
117 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000118 GenerateHelpText (result);
Chris Lattner24943d22010-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 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000128 GenerateHelpText (result);
Chris Lattner24943d22010-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 Inghamda26bd22012-06-08 21:56:10 +0000141 sub_cmd_obj->Execute (args_string, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000142 }
143 else
144 {
145 std::string error_msg;
Greg Clayton36da2aa2013-01-25 18:06:21 +0000146 const size_t num_subcmd_matches = matches.GetSize();
Chris Lattner24943d22010-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 Clayton36da2aa2013-01-25 18:06:21 +0000161 for (size_t i = 0; i < num_subcmd_matches; i++)
Chris Lattner24943d22010-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 Clayton36da2aa2013-01-25 18:06:21 +0000168 result.AppendRawError (error_msg.c_str());
Chris Lattner24943d22010-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
Greg Clayton238c0a12010-09-18 01:14:36 +0000184CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
Chris Lattner24943d22010-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
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000189 Stream &output_stream = result.GetOutputStream();
Chris Lattner24943d22010-06-08 16:52:24 +0000190 output_stream.PutCString ("The following subcommands are supported:\n\n");
191
192 CommandMap::iterator pos;
Greg Clayton238c0a12010-09-18 01:14:36 +0000193 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000194
Greg Clayton65124ea2010-08-26 22:05:43 +0000195 if (max_len)
196 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner24943d22010-06-08 16:52:24 +0000197
198 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
199 {
200 std::string indented_command (" ");
201 indented_command.append (pos->first);
Caroline Ticefb355112010-10-01 17:46:38 +0000202 if (pos->second->WantsRawCommandString ())
203 {
204 std::string help_text (pos->second->GetHelp());
205 help_text.append (" This command takes 'raw' input (no need to quote stuff).");
206 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
207 indented_command.c_str(),
208 "--",
209 help_text.c_str(),
210 max_len);
211 }
212 else
213 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
214 indented_command.c_str(),
215 "--",
216 pos->second->GetHelp(),
217 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000218 }
219
220 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
221
222 result.SetStatus (eReturnStatusSuccessFinishNoResult);
223}
224
225int
226CommandObjectMultiword::HandleCompletion
227(
228 Args &input,
229 int &cursor_index,
230 int &cursor_char_position,
231 int match_start_point,
232 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000233 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000234 StringList &matches
235)
236{
Jim Ingham802f8b02010-06-30 05:02:46 +0000237 // Any of the command matches will provide a complete word, otherwise the individual
238 // completers will override this.
239 word_complete = true;
240
Chris Lattner24943d22010-06-08 16:52:24 +0000241 if (cursor_index == 0)
242 {
Greg Clayton63094e02010-06-23 01:19:29 +0000243 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
244 input.GetArgumentAtIndex(0),
245 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000246
247 if (matches.GetSize() == 1
248 && matches.GetStringAtIndex(0) != NULL
249 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
250 {
251 StringList temp_matches;
Greg Clayton63094e02010-06-23 01:19:29 +0000252 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
253 &temp_matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000254 if (cmd_obj != NULL)
255 {
256 matches.DeleteStringAtIndex (0);
257 input.Shift();
258 cursor_char_position = 0;
259 input.AppendArgument ("");
Greg Clayton238c0a12010-09-18 01:14:36 +0000260 return cmd_obj->HandleCompletion (input,
261 cursor_index,
Greg Clayton63094e02010-06-23 01:19:29 +0000262 cursor_char_position,
263 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000264 max_return_elements,
265 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000266 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000267 }
268 else
269 return matches.GetSize();
270 }
271 else
272 return matches.GetSize();
273 }
274 else
275 {
Greg Clayton63094e02010-06-23 01:19:29 +0000276 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
277 &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000278 if (sub_command_object == NULL)
279 {
280 return matches.GetSize();
281 }
282 else
283 {
284 // Remove the one match that we got from calling GetSubcommandObject.
285 matches.DeleteStringAtIndex(0);
286 input.Shift();
287 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +0000288 return sub_command_object->HandleCompletion (input,
Greg Clayton63094e02010-06-23 01:19:29 +0000289 cursor_index,
290 cursor_char_position,
291 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000292 max_return_elements,
293 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000294 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000295 }
296
297 }
298}
299
Jim Ingham767af882010-07-07 03:36:20 +0000300const char *
301CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
302{
Jim Ingham767af882010-07-07 03:36:20 +0000303 index++;
Greg Clayton578ddbb2010-07-20 22:54:09 +0000304 if (current_command_args.GetArgumentCount() <= index)
305 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000306 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
307 if (sub_command_object == NULL)
308 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000309 return sub_command_object->GetRepeatCommand(current_command_args, index);
310}
311
Greg Clayton13193d52012-10-13 02:07:45 +0000312
313void
314CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
315 const char *search_word,
316 StringList &commands_found,
317 StringList &commands_help)
318{
319 CommandObject::CommandMap::const_iterator pos;
320
321 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
322 {
323 const char * command_name = pos->first.c_str();
324 CommandObject *sub_cmd_obj = pos->second.get();
325 StreamString complete_command_name;
326
327 complete_command_name.Printf ("%s %s", prefix, command_name);
328
329 if (sub_cmd_obj->HelpTextContainsWord (search_word))
330 {
331 commands_found.AppendString (complete_command_name.GetData());
332 commands_help.AppendString (sub_cmd_obj->GetHelp());
333 }
334
335 if (sub_cmd_obj->IsMultiwordObject())
336 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
337 search_word,
338 commands_found,
339 commands_help);
340 }
341}
342
343
344
345CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter,
346 const char *name,
347 const char *help,
348 const char *syntax,
349 uint32_t flags) :
350 CommandObject (interpreter, name, help, syntax, flags)
351{
352}
353
354CommandObjectProxy::~CommandObjectProxy ()
355{
356}
357
358const char *
359CommandObjectProxy::GetHelpLong ()
360{
361 CommandObject *proxy_command = GetProxyCommandObject();
362 if (proxy_command)
363 return proxy_command->GetHelpLong();
364 return NULL;
365}
366
Greg Clayton13193d52012-10-13 02:07:45 +0000367bool
368CommandObjectProxy::IsRemovable() const
369{
370 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
371 if (proxy_command)
372 return proxy_command->IsRemovable();
373 return false;
374}
375
376bool
377CommandObjectProxy::IsMultiwordObject ()
378{
379 CommandObject *proxy_command = GetProxyCommandObject();
380 if (proxy_command)
381 return proxy_command->IsMultiwordObject();
382 return false;
383}
384
385lldb::CommandObjectSP
386CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
387{
388 CommandObject *proxy_command = GetProxyCommandObject();
389 if (proxy_command)
390 return proxy_command->GetSubcommandSP(sub_cmd, matches);
391 return lldb::CommandObjectSP();
392}
393
394CommandObject *
395CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
396{
397 CommandObject *proxy_command = GetProxyCommandObject();
398 if (proxy_command)
399 return proxy_command->GetSubcommandObject(sub_cmd, matches);
400 return NULL;
401}
402
403void
404CommandObjectProxy::AproposAllSubCommands (const char *prefix,
405 const char *search_word,
406 StringList &commands_found,
407 StringList &commands_help)
408{
409 CommandObject *proxy_command = GetProxyCommandObject();
410 if (proxy_command)
411 return proxy_command->AproposAllSubCommands (prefix,
412 search_word,
413 commands_found,
414 commands_help);
415}
416
417bool
418CommandObjectProxy::LoadSubCommand (const char *cmd_name,
419 const lldb::CommandObjectSP& command_sp)
420{
421 CommandObject *proxy_command = GetProxyCommandObject();
422 if (proxy_command)
423 return proxy_command->LoadSubCommand (cmd_name, command_sp);
424 return false;
425}
426
427bool
428CommandObjectProxy::WantsRawCommandString()
429{
430 CommandObject *proxy_command = GetProxyCommandObject();
431 if (proxy_command)
432 return proxy_command->WantsRawCommandString();
433 return false;
434}
435
436bool
437CommandObjectProxy::WantsCompletion()
438{
439 CommandObject *proxy_command = GetProxyCommandObject();
440 if (proxy_command)
441 return proxy_command->WantsCompletion();
442 return false;
443}
444
445
446Options *
447CommandObjectProxy::GetOptions ()
448{
449 CommandObject *proxy_command = GetProxyCommandObject();
450 if (proxy_command)
451 return proxy_command->GetOptions ();
452 return NULL;
453}
454
455
456int
457CommandObjectProxy::HandleCompletion (Args &input,
458 int &cursor_index,
459 int &cursor_char_position,
460 int match_start_point,
461 int max_return_elements,
462 bool &word_complete,
463 StringList &matches)
464{
465 CommandObject *proxy_command = GetProxyCommandObject();
466 if (proxy_command)
467 return proxy_command->HandleCompletion (input,
468 cursor_index,
469 cursor_char_position,
470 match_start_point,
471 max_return_elements,
472 word_complete,
473 matches);
474 matches.Clear();
475 return 0;
476}
477int
478CommandObjectProxy::HandleArgumentCompletion (Args &input,
479 int &cursor_index,
480 int &cursor_char_position,
481 OptionElementVector &opt_element_vector,
482 int match_start_point,
483 int max_return_elements,
484 bool &word_complete,
485 StringList &matches)
486{
487 CommandObject *proxy_command = GetProxyCommandObject();
488 if (proxy_command)
489 return proxy_command->HandleArgumentCompletion (input,
490 cursor_index,
491 cursor_char_position,
492 opt_element_vector,
493 match_start_point,
494 max_return_elements,
495 word_complete,
496 matches);
497 matches.Clear();
498 return 0;
499}
500
501const char *
502CommandObjectProxy::GetRepeatCommand (Args &current_command_args,
503 uint32_t index)
504{
505 CommandObject *proxy_command = GetProxyCommandObject();
506 if (proxy_command)
507 return proxy_command->GetRepeatCommand (current_command_args, index);
508 return NULL;
509}
510
511bool
512CommandObjectProxy::Execute (const char *args_string,
513 CommandReturnObject &result)
514{
515 CommandObject *proxy_command = GetProxyCommandObject();
516 if (proxy_command)
517 return proxy_command->Execute (args_string, result);
518 result.AppendError ("command is not implemented");
519 result.SetStatus (eReturnStatusFailed);
520 return false;
521}
522
523