blob: ed70551ef3723f268768ed2ac24e166486fd6e0c [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
10#include "lldb/Interpreter/CommandObjectMultiword.h"
11// C Includes
12// C++ Includes
13// Other libraries and framework includes
14// Project includes
Greg Clayton66111032010-06-23 01:19:29 +000015#include "lldb/Core/Debugger.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include "lldb/Interpreter/CommandInterpreter.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000017#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Interpreter/CommandReturnObject.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23//-------------------------------------------------------------------------
24// CommandObjectMultiword
25//-------------------------------------------------------------------------
26
27CommandObjectMultiword::CommandObjectMultiword
28(
Greg Claytona7015092010-09-18 01:14:36 +000029 CommandInterpreter &interpreter,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030 const char *name,
31 const char *help,
32 const char *syntax,
33 uint32_t flags
34) :
Daniel Malead82ac9e2013-02-21 21:18:07 +000035 CommandObject (interpreter, name, help, syntax, flags),
36 m_can_be_removed(false)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037{
38}
39
40CommandObjectMultiword::~CommandObjectMultiword ()
41{
42}
43
44CommandObjectSP
45CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
46{
47 CommandObjectSP return_cmd_sp;
48 CommandObject::CommandMap::iterator pos;
49
50 if (!m_subcommand_dict.empty())
51 {
52 pos = m_subcommand_dict.find (sub_cmd);
Johnny Chence814962010-12-01 01:04:22 +000053 if (pos != m_subcommand_dict.end()) {
54 // An exact match; append the sub_cmd to the 'matches' string list.
55 if (matches)
56 matches->AppendString(sub_cmd);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057 return_cmd_sp = pos->second;
Johnny Chence814962010-12-01 01:04:22 +000058 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059 else
60 {
61
62 StringList local_matches;
63 if (matches == NULL)
64 matches = &local_matches;
65 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
66
67 if (num_matches == 1)
68 {
69 // Cleaner, but slightly less efficient would be to call back into this function, since I now
70 // know I have an exact match...
71
72 sub_cmd = matches->GetStringAtIndex(0);
73 pos = m_subcommand_dict.find(sub_cmd);
74 if (pos != m_subcommand_dict.end())
75 return_cmd_sp = pos->second;
76 }
77 }
78 }
79 return return_cmd_sp;
80}
81
82CommandObject *
83CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
84{
85 return GetSubcommandSP(sub_cmd, matches).get();
86}
87
88bool
Greg Clayton66111032010-06-23 01:19:29 +000089CommandObjectMultiword::LoadSubCommand
90(
Greg Clayton66111032010-06-23 01:19:29 +000091 const char *name,
92 const CommandObjectSP& cmd_obj
93)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000094{
Enrico Granata415717812016-02-06 01:36:07 +000095 if (cmd_obj.get())
96 assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter");
97
Chris Lattner30fdc8d2010-06-08 16:52:24 +000098 CommandMap::iterator pos;
99 bool success = true;
100
101 pos = m_subcommand_dict.find(name);
102 if (pos == m_subcommand_dict.end())
103 {
104 m_subcommand_dict[name] = cmd_obj;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105 }
106 else
107 success = false;
108
109 return success;
110}
111
112bool
Jim Ingham5a988412012-06-08 21:56:10 +0000113CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114{
Jim Ingham5a988412012-06-08 21:56:10 +0000115 Args args (args_string);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000116 const size_t argc = args.GetArgumentCount();
117 if (argc == 0)
118 {
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000119 this->CommandObject::GenerateHelpText (result);
Chris Lattner30fdc8d2010-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 {
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000129 this->CommandObject::GenerateHelpText (result);
Chris Lattner30fdc8d2010-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 Ingham5a988412012-06-08 21:56:10 +0000142 sub_cmd_obj->Execute (args_string, result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 }
144 else
145 {
146 std::string error_msg;
Greg Claytonc7bece562013-01-25 18:06:21 +0000147 const size_t num_subcmd_matches = matches.GetSize();
Chris Lattner30fdc8d2010-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);
Adrian McCarthy2304b6f2015-04-23 20:00:25 +0000157 error_msg.append ("'.");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158
159 if (num_subcmd_matches > 0)
160 {
161 error_msg.append (" Possible completions:");
Greg Claytonc7bece562013-01-25 18:06:21 +0000162 for (size_t i = 0; i < num_subcmd_matches; i++)
Chris Lattner30fdc8d2010-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 Claytonc7bece562013-01-25 18:06:21 +0000169 result.AppendRawError (error_msg.c_str());
Chris Lattner30fdc8d2010-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
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000185CommandObjectMultiword::GenerateHelpText (Stream &output_stream)
Chris Lattner30fdc8d2010-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
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000190 output_stream.PutCString ("The following subcommands are supported:\n\n");
191
192 CommandMap::iterator pos;
Greg Claytona7015092010-09-18 01:14:36 +0000193 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000194
Greg Clayton12fc3e02010-08-26 22:05:43 +0000195 if (max_len)
196 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner30fdc8d2010-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 Ticee139cf22010-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).");
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000206 m_interpreter.OutputFormattedHelpText (output_stream,
Caroline Ticee139cf22010-10-01 17:46:38 +0000207 indented_command.c_str(),
208 "--",
209 help_text.c_str(),
210 max_len);
211 }
212 else
Enrico Granata9b62d1d2013-06-12 01:50:57 +0000213 m_interpreter.OutputFormattedHelpText (output_stream,
Caroline Ticee139cf22010-10-01 17:46:38 +0000214 indented_command.c_str(),
215 "--",
216 pos->second->GetHelp(),
217 max_len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000218 }
219
220 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000221}
222
223int
224CommandObjectMultiword::HandleCompletion
225(
226 Args &input,
227 int &cursor_index,
228 int &cursor_char_position,
229 int match_start_point,
230 int max_return_elements,
Jim Ingham558ce122010-06-30 05:02:46 +0000231 bool &word_complete,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000232 StringList &matches
233)
234{
Jim Ingham558ce122010-06-30 05:02:46 +0000235 // Any of the command matches will provide a complete word, otherwise the individual
236 // completers will override this.
237 word_complete = true;
238
Greg Clayton765d2e22013-12-10 19:14:04 +0000239 const char *arg0 = input.GetArgumentAtIndex(0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000240 if (cursor_index == 0)
241 {
Greg Clayton66111032010-06-23 01:19:29 +0000242 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
Greg Clayton765d2e22013-12-10 19:14:04 +0000243 arg0,
Greg Clayton66111032010-06-23 01:19:29 +0000244 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000245
246 if (matches.GetSize() == 1
247 && matches.GetStringAtIndex(0) != NULL
Greg Clayton765d2e22013-12-10 19:14:04 +0000248 && strcmp (arg0, matches.GetStringAtIndex(0)) == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000249 {
250 StringList temp_matches;
Greg Clayton765d2e22013-12-10 19:14:04 +0000251 CommandObject *cmd_obj = GetSubcommandObject (arg0,
Greg Clayton66111032010-06-23 01:19:29 +0000252 &temp_matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000253 if (cmd_obj != NULL)
254 {
Greg Clayton7d1069d2015-02-25 00:32:43 +0000255 if (input.GetArgumentCount() == 1)
256 {
257 word_complete = true;
258 }
259 else
260 {
261 matches.DeleteStringAtIndex (0);
262 input.Shift();
263 cursor_char_position = 0;
264 input.AppendArgument ("");
265 return cmd_obj->HandleCompletion (input,
266 cursor_index,
267 cursor_char_position,
268 match_start_point,
269 max_return_elements,
270 word_complete,
271 matches);
272 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000273 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000274 }
Greg Clayton7d1069d2015-02-25 00:32:43 +0000275 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000276 }
277 else
278 {
Greg Clayton765d2e22013-12-10 19:14:04 +0000279 CommandObject *sub_command_object = GetSubcommandObject (arg0,
Greg Clayton66111032010-06-23 01:19:29 +0000280 &matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000281 if (sub_command_object == NULL)
282 {
283 return matches.GetSize();
284 }
285 else
286 {
287 // Remove the one match that we got from calling GetSubcommandObject.
288 matches.DeleteStringAtIndex(0);
289 input.Shift();
290 cursor_index--;
Greg Claytona7015092010-09-18 01:14:36 +0000291 return sub_command_object->HandleCompletion (input,
Greg Clayton66111032010-06-23 01:19:29 +0000292 cursor_index,
293 cursor_char_position,
294 match_start_point,
Jim Ingham558ce122010-06-30 05:02:46 +0000295 max_return_elements,
296 word_complete,
Greg Clayton66111032010-06-23 01:19:29 +0000297 matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000298 }
299
300 }
301}
302
Jim Inghamebc09c32010-07-07 03:36:20 +0000303const char *
304CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
305{
Jim Inghamebc09c32010-07-07 03:36:20 +0000306 index++;
Greg Claytonede05852010-07-20 22:54:09 +0000307 if (current_command_args.GetArgumentCount() <= index)
308 return NULL;
Jim Inghamebc09c32010-07-07 03:36:20 +0000309 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
310 if (sub_command_object == NULL)
311 return NULL;
Jim Inghamebc09c32010-07-07 03:36:20 +0000312 return sub_command_object->GetRepeatCommand(current_command_args, index);
313}
314
Greg Clayton998255b2012-10-13 02:07:45 +0000315
316void
317CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
318 const char *search_word,
319 StringList &commands_found,
320 StringList &commands_help)
321{
322 CommandObject::CommandMap::const_iterator pos;
323
324 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
325 {
326 const char * command_name = pos->first.c_str();
327 CommandObject *sub_cmd_obj = pos->second.get();
328 StreamString complete_command_name;
329
330 complete_command_name.Printf ("%s %s", prefix, command_name);
331
332 if (sub_cmd_obj->HelpTextContainsWord (search_word))
333 {
334 commands_found.AppendString (complete_command_name.GetData());
335 commands_help.AppendString (sub_cmd_obj->GetHelp());
336 }
337
338 if (sub_cmd_obj->IsMultiwordObject())
339 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
340 search_word,
341 commands_found,
342 commands_help);
343 }
344}
345
346
347
348CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter,
349 const char *name,
350 const char *help,
351 const char *syntax,
352 uint32_t flags) :
353 CommandObject (interpreter, name, help, syntax, flags)
354{
355}
356
357CommandObjectProxy::~CommandObjectProxy ()
358{
359}
360
361const char *
362CommandObjectProxy::GetHelpLong ()
363{
364 CommandObject *proxy_command = GetProxyCommandObject();
365 if (proxy_command)
366 return proxy_command->GetHelpLong();
367 return NULL;
368}
369
Greg Clayton998255b2012-10-13 02:07:45 +0000370bool
371CommandObjectProxy::IsRemovable() const
372{
373 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
374 if (proxy_command)
375 return proxy_command->IsRemovable();
376 return false;
377}
378
379bool
380CommandObjectProxy::IsMultiwordObject ()
381{
382 CommandObject *proxy_command = GetProxyCommandObject();
383 if (proxy_command)
384 return proxy_command->IsMultiwordObject();
385 return false;
386}
387
Jim Ingham24714342015-11-05 01:18:07 +0000388void
389CommandObjectProxy::GenerateHelpText (Stream &result)
390{
391 CommandObject *proxy_command = GetProxyCommandObject();
392 if (proxy_command)
393 return proxy_command->GenerateHelpText(result);
394}
395
Greg Clayton998255b2012-10-13 02:07:45 +0000396lldb::CommandObjectSP
397CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
398{
399 CommandObject *proxy_command = GetProxyCommandObject();
400 if (proxy_command)
401 return proxy_command->GetSubcommandSP(sub_cmd, matches);
402 return lldb::CommandObjectSP();
403}
404
405CommandObject *
406CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
407{
408 CommandObject *proxy_command = GetProxyCommandObject();
409 if (proxy_command)
410 return proxy_command->GetSubcommandObject(sub_cmd, matches);
411 return NULL;
412}
413
414void
415CommandObjectProxy::AproposAllSubCommands (const char *prefix,
416 const char *search_word,
417 StringList &commands_found,
418 StringList &commands_help)
419{
420 CommandObject *proxy_command = GetProxyCommandObject();
421 if (proxy_command)
422 return proxy_command->AproposAllSubCommands (prefix,
423 search_word,
424 commands_found,
425 commands_help);
426}
427
428bool
429CommandObjectProxy::LoadSubCommand (const char *cmd_name,
430 const lldb::CommandObjectSP& command_sp)
431{
432 CommandObject *proxy_command = GetProxyCommandObject();
433 if (proxy_command)
434 return proxy_command->LoadSubCommand (cmd_name, command_sp);
435 return false;
436}
437
438bool
439CommandObjectProxy::WantsRawCommandString()
440{
441 CommandObject *proxy_command = GetProxyCommandObject();
442 if (proxy_command)
443 return proxy_command->WantsRawCommandString();
444 return false;
445}
446
447bool
448CommandObjectProxy::WantsCompletion()
449{
450 CommandObject *proxy_command = GetProxyCommandObject();
451 if (proxy_command)
452 return proxy_command->WantsCompletion();
453 return false;
454}
455
456
457Options *
458CommandObjectProxy::GetOptions ()
459{
460 CommandObject *proxy_command = GetProxyCommandObject();
461 if (proxy_command)
462 return proxy_command->GetOptions ();
463 return NULL;
464}
465
466
467int
468CommandObjectProxy::HandleCompletion (Args &input,
469 int &cursor_index,
470 int &cursor_char_position,
471 int match_start_point,
472 int max_return_elements,
473 bool &word_complete,
474 StringList &matches)
475{
476 CommandObject *proxy_command = GetProxyCommandObject();
477 if (proxy_command)
478 return proxy_command->HandleCompletion (input,
479 cursor_index,
480 cursor_char_position,
481 match_start_point,
482 max_return_elements,
483 word_complete,
484 matches);
485 matches.Clear();
486 return 0;
487}
488int
489CommandObjectProxy::HandleArgumentCompletion (Args &input,
490 int &cursor_index,
491 int &cursor_char_position,
492 OptionElementVector &opt_element_vector,
493 int match_start_point,
494 int max_return_elements,
495 bool &word_complete,
496 StringList &matches)
497{
498 CommandObject *proxy_command = GetProxyCommandObject();
499 if (proxy_command)
500 return proxy_command->HandleArgumentCompletion (input,
501 cursor_index,
502 cursor_char_position,
503 opt_element_vector,
504 match_start_point,
505 max_return_elements,
506 word_complete,
507 matches);
508 matches.Clear();
509 return 0;
510}
511
512const char *
513CommandObjectProxy::GetRepeatCommand (Args &current_command_args,
514 uint32_t index)
515{
516 CommandObject *proxy_command = GetProxyCommandObject();
517 if (proxy_command)
518 return proxy_command->GetRepeatCommand (current_command_args, index);
519 return NULL;
520}
521
522bool
523CommandObjectProxy::Execute (const char *args_string,
524 CommandReturnObject &result)
525{
526 CommandObject *proxy_command = GetProxyCommandObject();
527 if (proxy_command)
528 return proxy_command->Execute (args_string, result);
529 result.AppendError ("command is not implemented");
530 result.SetStatus (eReturnStatusFailed);
531 return false;
532}
533
534