blob: 249863b4e8a8818a69f3c360645194d326d33ac5 [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
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
13// Project includes
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000014#include "lldb/Interpreter/CommandObjectMultiword.h"
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"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "lldb/Interpreter/CommandReturnObject.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019
20using namespace lldb;
21using namespace lldb_private;
22
23//-------------------------------------------------------------------------
24// CommandObjectMultiword
25//-------------------------------------------------------------------------
26
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000027CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
28 const char *name,
29 const char *help,
30 const char *syntax,
Kate Stoneb9c1b512016-09-06 20:57:50 +000031 uint32_t flags)
32 : CommandObject(interpreter, name, help, syntax, flags),
33 m_can_be_removed(false) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034
Eugene Zelenko26cac3a2016-02-20 00:58:29 +000035CommandObjectMultiword::~CommandObjectMultiword() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036
Kate Stoneb9c1b512016-09-06 20:57:50 +000037CommandObjectSP CommandObjectMultiword::GetSubcommandSP(const char *sub_cmd,
38 StringList *matches) {
39 CommandObjectSP return_cmd_sp;
40 CommandObject::CommandMap::iterator pos;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 if (!m_subcommand_dict.empty()) {
43 pos = m_subcommand_dict.find(sub_cmd);
44 if (pos != m_subcommand_dict.end()) {
45 // An exact match; append the sub_cmd to the 'matches' string list.
46 if (matches)
47 matches->AppendString(sub_cmd);
48 return_cmd_sp = pos->second;
49 } else {
50 StringList local_matches;
51 if (matches == nullptr)
52 matches = &local_matches;
53 int num_matches =
54 AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 if (num_matches == 1) {
57 // Cleaner, but slightly less efficient would be to call back into this
58 // function, since I now
59 // know I have an exact match...
Chris Lattner30fdc8d2010-06-08 16:52:24 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 sub_cmd = matches->GetStringAtIndex(0);
62 pos = m_subcommand_dict.find(sub_cmd);
63 if (pos != m_subcommand_dict.end())
64 return_cmd_sp = pos->second;
65 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 }
68 return return_cmd_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069}
70
71CommandObject *
Kate Stoneb9c1b512016-09-06 20:57:50 +000072CommandObjectMultiword::GetSubcommandObject(const char *sub_cmd,
73 StringList *matches) {
74 return GetSubcommandSP(sub_cmd, matches).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075}
76
Kate Stoneb9c1b512016-09-06 20:57:50 +000077bool CommandObjectMultiword::LoadSubCommand(const char *name,
78 const CommandObjectSP &cmd_obj) {
79 if (cmd_obj)
80 assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) &&
81 "tried to add a CommandObject from a different interpreter");
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 CommandMap::iterator pos;
84 bool success = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000085
Kate Stoneb9c1b512016-09-06 20:57:50 +000086 pos = m_subcommand_dict.find(name);
87 if (pos == m_subcommand_dict.end()) {
88 m_subcommand_dict[name] = cmd_obj;
89 } else
90 success = false;
91
92 return success;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093}
94
Kate Stoneb9c1b512016-09-06 20:57:50 +000095bool CommandObjectMultiword::Execute(const char *args_string,
96 CommandReturnObject &result) {
97 Args args(args_string);
98 const size_t argc = args.GetArgumentCount();
99 if (argc == 0) {
100 this->CommandObject::GenerateHelpText(result);
101 } else {
102 const char *sub_command = args.GetArgumentAtIndex(0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 if (sub_command) {
105 if (::strcasecmp(sub_command, "help") == 0) {
106 this->CommandObject::GenerateHelpText(result);
107 } else if (!m_subcommand_dict.empty()) {
108 StringList matches;
109 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
110 if (sub_cmd_obj != nullptr) {
111 // Now call CommandObject::Execute to process and options in
112 // 'rest_of_line'. From there
113 // the command-specific version of Execute will be called, with the
114 // processed arguments.
115
116 args.Shift();
117
118 sub_cmd_obj->Execute(args_string, result);
119 } else {
120 std::string error_msg;
121 const size_t num_subcmd_matches = matches.GetSize();
122 if (num_subcmd_matches > 0)
123 error_msg.assign("ambiguous command ");
124 else
125 error_msg.assign("invalid command ");
126
127 error_msg.append("'");
128 error_msg.append(GetCommandName());
129 error_msg.append(" ");
130 error_msg.append(sub_command);
131 error_msg.append("'.");
132
133 if (num_subcmd_matches > 0) {
134 error_msg.append(" Possible completions:");
135 for (size_t i = 0; i < num_subcmd_matches; i++) {
136 error_msg.append("\n\t");
137 error_msg.append(matches.GetStringAtIndex(i));
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 }
140 error_msg.append("\n");
141 result.AppendRawError(error_msg.c_str());
142 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000143 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 } else {
145 result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
Zachary Turnera4496982016-10-05 21:14:38 +0000146 GetCommandName().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 result.SetStatus(eReturnStatusFailed);
148 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151
Kate Stoneb9c1b512016-09-06 20:57:50 +0000152 return result.Succeeded();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153}
154
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
156 // First time through here, generate the help text for the object and
157 // push it to the return result object as well
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000158
Kate Stoneb9c1b512016-09-06 20:57:50 +0000159 CommandObject::GenerateHelpText(output_stream);
160 output_stream.PutCString("\nThe following subcommands are supported:\n\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162 CommandMap::iterator pos;
163 uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165 if (max_len)
166 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
169 std::string indented_command(" ");
170 indented_command.append(pos->first);
171 if (pos->second->WantsRawCommandString()) {
172 std::string help_text(pos->second->GetHelp());
173 help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
174 m_interpreter.OutputFormattedHelpText(output_stream,
175 indented_command.c_str(), "--",
176 help_text.c_str(), max_len);
177 } else
178 m_interpreter.OutputFormattedHelpText(output_stream,
179 indented_command.c_str(), "--",
180 pos->second->GetHelp(), max_len);
181 }
182
183 output_stream.PutCString("\nFor more help on any particular subcommand, type "
184 "'help <command> <subcommand>'.\n");
185}
186
187int CommandObjectMultiword::HandleCompletion(Args &input, int &cursor_index,
188 int &cursor_char_position,
189 int match_start_point,
190 int max_return_elements,
191 bool &word_complete,
192 StringList &matches) {
193 // Any of the command matches will provide a complete word, otherwise the
194 // individual
195 // completers will override this.
196 word_complete = true;
197
198 const char *arg0 = input.GetArgumentAtIndex(0);
199 if (cursor_index == 0) {
200 AddNamesMatchingPartialString(m_subcommand_dict, arg0, matches);
201
202 if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != nullptr &&
203 strcmp(arg0, matches.GetStringAtIndex(0)) == 0) {
204 StringList temp_matches;
205 CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
206 if (cmd_obj != nullptr) {
207 if (input.GetArgumentCount() == 1) {
208 word_complete = true;
209 } else {
210 matches.DeleteStringAtIndex(0);
211 input.Shift();
212 cursor_char_position = 0;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000213 input.AppendArgument(llvm::StringRef());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214 return cmd_obj->HandleCompletion(
215 input, cursor_index, cursor_char_position, match_start_point,
216 max_return_elements, word_complete, matches);
Caroline Ticee139cf22010-10-01 17:46:38 +0000217 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000219 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220 return matches.GetSize();
221 } else {
222 CommandObject *sub_command_object = GetSubcommandObject(arg0, &matches);
223 if (sub_command_object == nullptr) {
224 return matches.GetSize();
225 } else {
226 // Remove the one match that we got from calling GetSubcommandObject.
227 matches.DeleteStringAtIndex(0);
228 input.Shift();
229 cursor_index--;
230 return sub_command_object->HandleCompletion(
231 input, cursor_index, cursor_char_position, match_start_point,
232 max_return_elements, word_complete, matches);
233 }
234 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000235}
236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237const char *CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
238 uint32_t index) {
239 index++;
240 if (current_command_args.GetArgumentCount() <= index)
241 return nullptr;
242 CommandObject *sub_command_object =
243 GetSubcommandObject(current_command_args.GetArgumentAtIndex(index));
244 if (sub_command_object == nullptr)
245 return nullptr;
246 return sub_command_object->GetRepeatCommand(current_command_args, index);
247}
248
249void CommandObjectMultiword::AproposAllSubCommands(const char *prefix,
250 const char *search_word,
251 StringList &commands_found,
252 StringList &commands_help) {
253 CommandObject::CommandMap::const_iterator pos;
254
255 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
256 const char *command_name = pos->first.c_str();
257 CommandObject *sub_cmd_obj = pos->second.get();
258 StreamString complete_command_name;
259
260 complete_command_name.Printf("%s %s", prefix, command_name);
261
262 if (sub_cmd_obj->HelpTextContainsWord(search_word)) {
263 commands_found.AppendString(complete_command_name.GetData());
264 commands_help.AppendString(sub_cmd_obj->GetHelp());
265 }
266
267 if (sub_cmd_obj->IsMultiwordObject())
268 sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetData(),
269 search_word, commands_found,
270 commands_help);
271 }
272}
273
274CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
275 const char *name, const char *help,
276 const char *syntax, uint32_t flags)
277 : CommandObject(interpreter, name, help, syntax, flags) {}
278
279CommandObjectProxy::~CommandObjectProxy() = default;
280
Zachary Turner442f6532016-11-12 20:41:02 +0000281llvm::StringRef CommandObjectProxy::GetHelpLong() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 CommandObject *proxy_command = GetProxyCommandObject();
283 if (proxy_command)
284 return proxy_command->GetHelpLong();
Zachary Turner442f6532016-11-12 20:41:02 +0000285 return llvm::StringRef();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286}
287
288bool CommandObjectProxy::IsRemovable() const {
289 const CommandObject *proxy_command =
290 const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
291 if (proxy_command)
292 return proxy_command->IsRemovable();
293 return false;
294}
295
296bool CommandObjectProxy::IsMultiwordObject() {
297 CommandObject *proxy_command = GetProxyCommandObject();
298 if (proxy_command)
299 return proxy_command->IsMultiwordObject();
300 return false;
301}
302
303CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
304 CommandObject *proxy_command = GetProxyCommandObject();
305 if (proxy_command)
306 return proxy_command->GetAsMultiwordCommand();
307 return nullptr;
308}
309
310void CommandObjectProxy::GenerateHelpText(Stream &result) {
311 CommandObject *proxy_command = GetProxyCommandObject();
312 if (proxy_command)
313 return proxy_command->GenerateHelpText(result);
314}
315
316lldb::CommandObjectSP CommandObjectProxy::GetSubcommandSP(const char *sub_cmd,
317 StringList *matches) {
318 CommandObject *proxy_command = GetProxyCommandObject();
319 if (proxy_command)
320 return proxy_command->GetSubcommandSP(sub_cmd, matches);
321 return lldb::CommandObjectSP();
322}
323
324CommandObject *CommandObjectProxy::GetSubcommandObject(const char *sub_cmd,
325 StringList *matches) {
326 CommandObject *proxy_command = GetProxyCommandObject();
327 if (proxy_command)
328 return proxy_command->GetSubcommandObject(sub_cmd, matches);
329 return nullptr;
330}
331
332void CommandObjectProxy::AproposAllSubCommands(const char *prefix,
333 const char *search_word,
334 StringList &commands_found,
335 StringList &commands_help) {
336 CommandObject *proxy_command = GetProxyCommandObject();
337 if (proxy_command)
338 return proxy_command->AproposAllSubCommands(prefix, search_word,
339 commands_found, commands_help);
340}
341
342bool CommandObjectProxy::LoadSubCommand(
343 const char *cmd_name, const lldb::CommandObjectSP &command_sp) {
344 CommandObject *proxy_command = GetProxyCommandObject();
345 if (proxy_command)
346 return proxy_command->LoadSubCommand(cmd_name, command_sp);
347 return false;
348}
349
350bool CommandObjectProxy::WantsRawCommandString() {
351 CommandObject *proxy_command = GetProxyCommandObject();
352 if (proxy_command)
353 return proxy_command->WantsRawCommandString();
354 return false;
355}
356
357bool CommandObjectProxy::WantsCompletion() {
358 CommandObject *proxy_command = GetProxyCommandObject();
359 if (proxy_command)
360 return proxy_command->WantsCompletion();
361 return false;
362}
363
364Options *CommandObjectProxy::GetOptions() {
365 CommandObject *proxy_command = GetProxyCommandObject();
366 if (proxy_command)
367 return proxy_command->GetOptions();
368 return nullptr;
369}
370
371int CommandObjectProxy::HandleCompletion(Args &input, int &cursor_index,
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000372 int &cursor_char_position,
373 int match_start_point,
374 int max_return_elements,
375 bool &word_complete,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376 StringList &matches) {
377 CommandObject *proxy_command = GetProxyCommandObject();
378 if (proxy_command)
379 return proxy_command->HandleCompletion(
380 input, cursor_index, cursor_char_position, match_start_point,
381 max_return_elements, word_complete, matches);
382 matches.Clear();
383 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384}
385
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386int CommandObjectProxy::HandleArgumentCompletion(
387 Args &input, int &cursor_index, int &cursor_char_position,
388 OptionElementVector &opt_element_vector, int match_start_point,
389 int max_return_elements, bool &word_complete, StringList &matches) {
390 CommandObject *proxy_command = GetProxyCommandObject();
391 if (proxy_command)
392 return proxy_command->HandleArgumentCompletion(
393 input, cursor_index, cursor_char_position, opt_element_vector,
394 match_start_point, max_return_elements, word_complete, matches);
395 matches.Clear();
396 return 0;
Jim Inghamebc09c32010-07-07 03:36:20 +0000397}
398
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399const char *CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
400 uint32_t index) {
401 CommandObject *proxy_command = GetProxyCommandObject();
402 if (proxy_command)
403 return proxy_command->GetRepeatCommand(current_command_args, index);
404 return nullptr;
Greg Clayton998255b2012-10-13 02:07:45 +0000405}
406
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407bool CommandObjectProxy::Execute(const char *args_string,
408 CommandReturnObject &result) {
409 CommandObject *proxy_command = GetProxyCommandObject();
410 if (proxy_command)
411 return proxy_command->Execute(args_string, result);
412 result.AppendError("command is not implemented");
413 result.SetStatus(eReturnStatusFailed);
414 return false;
Greg Clayton998255b2012-10-13 02:07:45 +0000415}