blob: d2e281197dabcf88cfbff82b83821191de510839 [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) :
Greg Clayton238c0a12010-09-18 01:14:36 +000037 CommandObject (interpreter, name, help, syntax, flags)
Chris Lattner24943d22010-06-08 16:52:24 +000038{
39}
40
41CommandObjectMultiword::~CommandObjectMultiword ()
42{
43}
44
45CommandObjectSP
46CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
47{
48 CommandObjectSP return_cmd_sp;
49 CommandObject::CommandMap::iterator pos;
50
51 if (!m_subcommand_dict.empty())
52 {
53 pos = m_subcommand_dict.find (sub_cmd);
Johnny Chendc6c2632010-12-01 01:04:22 +000054 if (pos != m_subcommand_dict.end()) {
55 // An exact match; append the sub_cmd to the 'matches' string list.
56 if (matches)
57 matches->AppendString(sub_cmd);
Chris Lattner24943d22010-06-08 16:52:24 +000058 return_cmd_sp = pos->second;
Johnny Chendc6c2632010-12-01 01:04:22 +000059 }
Chris Lattner24943d22010-06-08 16:52:24 +000060 else
61 {
62
63 StringList local_matches;
64 if (matches == NULL)
65 matches = &local_matches;
66 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
67
68 if (num_matches == 1)
69 {
70 // Cleaner, but slightly less efficient would be to call back into this function, since I now
71 // know I have an exact match...
72
73 sub_cmd = matches->GetStringAtIndex(0);
74 pos = m_subcommand_dict.find(sub_cmd);
75 if (pos != m_subcommand_dict.end())
76 return_cmd_sp = pos->second;
77 }
78 }
79 }
80 return return_cmd_sp;
81}
82
83CommandObject *
84CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
85{
86 return GetSubcommandSP(sub_cmd, matches).get();
87}
88
89bool
Greg Clayton63094e02010-06-23 01:19:29 +000090CommandObjectMultiword::LoadSubCommand
91(
Greg Clayton63094e02010-06-23 01:19:29 +000092 const char *name,
93 const CommandObjectSP& cmd_obj
94)
Chris Lattner24943d22010-06-08 16:52:24 +000095{
96 CommandMap::iterator pos;
97 bool success = true;
98
99 pos = m_subcommand_dict.find(name);
100 if (pos == m_subcommand_dict.end())
101 {
102 m_subcommand_dict[name] = cmd_obj;
Greg Clayton238c0a12010-09-18 01:14:36 +0000103 m_interpreter.CrossRegisterCommand (name, GetCommandName());
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;
146 int 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 (int 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(), error_msg.size());
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
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
367void
368CommandObjectProxy::AddObject (const char *obj_name)
369{
370 CommandObject *proxy_command = GetProxyCommandObject();
371 if (proxy_command)
372 return proxy_command->AddObject (obj_name);
373}
374
375bool
376CommandObjectProxy::IsCrossRefObject ()
377{
378 CommandObject *proxy_command = GetProxyCommandObject();
379 if (proxy_command)
380 return proxy_command->IsCrossRefObject();
381 return false;
382}
383
384bool
385CommandObjectProxy::IsRemovable() const
386{
387 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
388 if (proxy_command)
389 return proxy_command->IsRemovable();
390 return false;
391}
392
393bool
394CommandObjectProxy::IsMultiwordObject ()
395{
396 CommandObject *proxy_command = GetProxyCommandObject();
397 if (proxy_command)
398 return proxy_command->IsMultiwordObject();
399 return false;
400}
401
402lldb::CommandObjectSP
403CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
404{
405 CommandObject *proxy_command = GetProxyCommandObject();
406 if (proxy_command)
407 return proxy_command->GetSubcommandSP(sub_cmd, matches);
408 return lldb::CommandObjectSP();
409}
410
411CommandObject *
412CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
413{
414 CommandObject *proxy_command = GetProxyCommandObject();
415 if (proxy_command)
416 return proxy_command->GetSubcommandObject(sub_cmd, matches);
417 return NULL;
418}
419
420void
421CommandObjectProxy::AproposAllSubCommands (const char *prefix,
422 const char *search_word,
423 StringList &commands_found,
424 StringList &commands_help)
425{
426 CommandObject *proxy_command = GetProxyCommandObject();
427 if (proxy_command)
428 return proxy_command->AproposAllSubCommands (prefix,
429 search_word,
430 commands_found,
431 commands_help);
432}
433
434bool
435CommandObjectProxy::LoadSubCommand (const char *cmd_name,
436 const lldb::CommandObjectSP& command_sp)
437{
438 CommandObject *proxy_command = GetProxyCommandObject();
439 if (proxy_command)
440 return proxy_command->LoadSubCommand (cmd_name, command_sp);
441 return false;
442}
443
444bool
445CommandObjectProxy::WantsRawCommandString()
446{
447 CommandObject *proxy_command = GetProxyCommandObject();
448 if (proxy_command)
449 return proxy_command->WantsRawCommandString();
450 return false;
451}
452
453bool
454CommandObjectProxy::WantsCompletion()
455{
456 CommandObject *proxy_command = GetProxyCommandObject();
457 if (proxy_command)
458 return proxy_command->WantsCompletion();
459 return false;
460}
461
462
463Options *
464CommandObjectProxy::GetOptions ()
465{
466 CommandObject *proxy_command = GetProxyCommandObject();
467 if (proxy_command)
468 return proxy_command->GetOptions ();
469 return NULL;
470}
471
472
473int
474CommandObjectProxy::HandleCompletion (Args &input,
475 int &cursor_index,
476 int &cursor_char_position,
477 int match_start_point,
478 int max_return_elements,
479 bool &word_complete,
480 StringList &matches)
481{
482 CommandObject *proxy_command = GetProxyCommandObject();
483 if (proxy_command)
484 return proxy_command->HandleCompletion (input,
485 cursor_index,
486 cursor_char_position,
487 match_start_point,
488 max_return_elements,
489 word_complete,
490 matches);
491 matches.Clear();
492 return 0;
493}
494int
495CommandObjectProxy::HandleArgumentCompletion (Args &input,
496 int &cursor_index,
497 int &cursor_char_position,
498 OptionElementVector &opt_element_vector,
499 int match_start_point,
500 int max_return_elements,
501 bool &word_complete,
502 StringList &matches)
503{
504 CommandObject *proxy_command = GetProxyCommandObject();
505 if (proxy_command)
506 return proxy_command->HandleArgumentCompletion (input,
507 cursor_index,
508 cursor_char_position,
509 opt_element_vector,
510 match_start_point,
511 max_return_elements,
512 word_complete,
513 matches);
514 matches.Clear();
515 return 0;
516}
517
518const char *
519CommandObjectProxy::GetRepeatCommand (Args &current_command_args,
520 uint32_t index)
521{
522 CommandObject *proxy_command = GetProxyCommandObject();
523 if (proxy_command)
524 return proxy_command->GetRepeatCommand (current_command_args, index);
525 return NULL;
526}
527
528bool
529CommandObjectProxy::Execute (const char *args_string,
530 CommandReturnObject &result)
531{
532 CommandObject *proxy_command = GetProxyCommandObject();
533 if (proxy_command)
534 return proxy_command->Execute (args_string, result);
535 result.AppendError ("command is not implemented");
536 result.SetStatus (eReturnStatusFailed);
537 return false;
538}
539
540