blob: 0d0aa108a4cebdd12cb8c405edffe9986688d730 [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
Zachary Turner98896832016-11-13 02:50:32 +000037CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
Kate Stoneb9c1b512016-09-06 20:57:50 +000038 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 *
Zachary Turner98896832016-11-13 02:50:32 +000072CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 StringList *matches) {
74 return GetSubcommandSP(sub_cmd, matches).get();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075}
76
Zachary Turner98896832016-11-13 02:50:32 +000077bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 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);
Zachary Turner2c84f902016-12-09 05:46:41 +0000101 return result.Succeeded();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103
Zachary Turner2c84f902016-12-09 05:46:41 +0000104 auto sub_command = args[0].ref;
105 if (sub_command.empty())
106 return result.Succeeded();
107
108 if (sub_command.equals_lower("help")) {
109 this->CommandObject::GenerateHelpText(result);
110 return result.Succeeded();
111 }
112
113 if (m_subcommand_dict.empty()) {
114 result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
115 GetCommandName().str().c_str());
116 result.SetStatus(eReturnStatusFailed);
117 return false;
118 }
119
120 StringList matches;
121 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
122 if (sub_cmd_obj != nullptr) {
123 // Now call CommandObject::Execute to process options in `rest_of_line`.
124 // From there the command-specific version of Execute will be called,
125 // with the processed arguments.
126
127 args.Shift();
128 sub_cmd_obj->Execute(args_string, result);
129 return result.Succeeded();
130 }
131
132 std::string error_msg;
133 const size_t num_subcmd_matches = matches.GetSize();
134 if (num_subcmd_matches > 0)
135 error_msg.assign("ambiguous command ");
136 else
137 error_msg.assign("invalid command ");
138
139 error_msg.append("'");
140 error_msg.append(GetCommandName());
141 error_msg.append(" ");
142 error_msg.append(sub_command);
143 error_msg.append("'.");
144
145 if (num_subcmd_matches > 0) {
146 error_msg.append(" Possible completions:");
147 for (size_t i = 0; i < num_subcmd_matches; i++) {
148 error_msg.append("\n\t");
149 error_msg.append(matches.GetStringAtIndex(i));
150 }
151 }
152 error_msg.append("\n");
153 result.AppendRawError(error_msg.c_str());
154 result.SetStatus(eReturnStatusFailed);
155 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156}
157
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
159 // First time through here, generate the help text for the object and
160 // push it to the return result object as well
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161
Kate Stoneb9c1b512016-09-06 20:57:50 +0000162 CommandObject::GenerateHelpText(output_stream);
163 output_stream.PutCString("\nThe following subcommands are supported:\n\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165 CommandMap::iterator pos;
166 uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 if (max_len)
169 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000170
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
172 std::string indented_command(" ");
173 indented_command.append(pos->first);
174 if (pos->second->WantsRawCommandString()) {
175 std::string help_text(pos->second->GetHelp());
176 help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
177 m_interpreter.OutputFormattedHelpText(output_stream,
178 indented_command.c_str(), "--",
179 help_text.c_str(), max_len);
180 } else
181 m_interpreter.OutputFormattedHelpText(output_stream,
182 indented_command.c_str(), "--",
183 pos->second->GetHelp(), max_len);
184 }
185
186 output_stream.PutCString("\nFor more help on any particular subcommand, type "
187 "'help <command> <subcommand>'.\n");
188}
189
190int CommandObjectMultiword::HandleCompletion(Args &input, int &cursor_index,
191 int &cursor_char_position,
192 int match_start_point,
193 int max_return_elements,
194 bool &word_complete,
195 StringList &matches) {
196 // Any of the command matches will provide a complete word, otherwise the
Zachary Turner2c84f902016-12-09 05:46:41 +0000197 // individual completers will override this.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198 word_complete = true;
199
Zachary Turner2c84f902016-12-09 05:46:41 +0000200 auto arg0 = input[0].ref;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000201 if (cursor_index == 0) {
202 AddNamesMatchingPartialString(m_subcommand_dict, arg0, matches);
203
204 if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != nullptr &&
Zachary Turner2c84f902016-12-09 05:46:41 +0000205 (arg0 == matches.GetStringAtIndex(0))) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 StringList temp_matches;
207 CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
208 if (cmd_obj != nullptr) {
209 if (input.GetArgumentCount() == 1) {
210 word_complete = true;
211 } else {
212 matches.DeleteStringAtIndex(0);
213 input.Shift();
214 cursor_char_position = 0;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000215 input.AppendArgument(llvm::StringRef());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216 return cmd_obj->HandleCompletion(
217 input, cursor_index, cursor_char_position, match_start_point,
218 max_return_elements, word_complete, matches);
Caroline Ticee139cf22010-10-01 17:46:38 +0000219 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000221 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000222 return matches.GetSize();
223 } else {
224 CommandObject *sub_command_object = GetSubcommandObject(arg0, &matches);
225 if (sub_command_object == nullptr) {
226 return matches.GetSize();
227 } else {
228 // Remove the one match that we got from calling GetSubcommandObject.
229 matches.DeleteStringAtIndex(0);
230 input.Shift();
231 cursor_index--;
232 return sub_command_object->HandleCompletion(
233 input, cursor_index, cursor_char_position, match_start_point,
234 max_return_elements, word_complete, matches);
235 }
236 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237}
238
Kate Stoneb9c1b512016-09-06 20:57:50 +0000239const char *CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
240 uint32_t index) {
241 index++;
242 if (current_command_args.GetArgumentCount() <= index)
243 return nullptr;
244 CommandObject *sub_command_object =
Zachary Turner2c84f902016-12-09 05:46:41 +0000245 GetSubcommandObject(current_command_args[index].ref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246 if (sub_command_object == nullptr)
247 return nullptr;
248 return sub_command_object->GetRepeatCommand(current_command_args, index);
249}
250
Zachary Turner98896832016-11-13 02:50:32 +0000251void CommandObjectMultiword::AproposAllSubCommands(llvm::StringRef prefix,
252 llvm::StringRef search_word,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000253 StringList &commands_found,
254 StringList &commands_help) {
255 CommandObject::CommandMap::const_iterator pos;
256
257 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
258 const char *command_name = pos->first.c_str();
259 CommandObject *sub_cmd_obj = pos->second.get();
260 StreamString complete_command_name;
261
Zachary Turner03c9f362016-11-14 23:23:31 +0000262 complete_command_name << prefix << " " << command_name;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263
264 if (sub_cmd_obj->HelpTextContainsWord(search_word)) {
Zachary Turnerc1564272016-11-16 21:15:24 +0000265 commands_found.AppendString(complete_command_name.GetString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 commands_help.AppendString(sub_cmd_obj->GetHelp());
267 }
268
269 if (sub_cmd_obj->IsMultiwordObject())
Zachary Turner98896832016-11-13 02:50:32 +0000270 sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetString(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271 search_word, commands_found,
272 commands_help);
273 }
274}
275
276CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
277 const char *name, const char *help,
278 const char *syntax, uint32_t flags)
279 : CommandObject(interpreter, name, help, syntax, flags) {}
280
281CommandObjectProxy::~CommandObjectProxy() = default;
282
Zachary Turner442f6532016-11-12 20:41:02 +0000283llvm::StringRef CommandObjectProxy::GetHelpLong() {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 CommandObject *proxy_command = GetProxyCommandObject();
285 if (proxy_command)
286 return proxy_command->GetHelpLong();
Zachary Turner442f6532016-11-12 20:41:02 +0000287 return llvm::StringRef();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000288}
289
290bool CommandObjectProxy::IsRemovable() const {
291 const CommandObject *proxy_command =
292 const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
293 if (proxy_command)
294 return proxy_command->IsRemovable();
295 return false;
296}
297
298bool CommandObjectProxy::IsMultiwordObject() {
299 CommandObject *proxy_command = GetProxyCommandObject();
300 if (proxy_command)
301 return proxy_command->IsMultiwordObject();
302 return false;
303}
304
305CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
306 CommandObject *proxy_command = GetProxyCommandObject();
307 if (proxy_command)
308 return proxy_command->GetAsMultiwordCommand();
309 return nullptr;
310}
311
312void CommandObjectProxy::GenerateHelpText(Stream &result) {
313 CommandObject *proxy_command = GetProxyCommandObject();
314 if (proxy_command)
315 return proxy_command->GenerateHelpText(result);
316}
317
Zachary Turner98896832016-11-13 02:50:32 +0000318lldb::CommandObjectSP
319CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
320 StringList *matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000321 CommandObject *proxy_command = GetProxyCommandObject();
322 if (proxy_command)
323 return proxy_command->GetSubcommandSP(sub_cmd, matches);
324 return lldb::CommandObjectSP();
325}
326
Zachary Turner98896832016-11-13 02:50:32 +0000327CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000328 StringList *matches) {
329 CommandObject *proxy_command = GetProxyCommandObject();
330 if (proxy_command)
331 return proxy_command->GetSubcommandObject(sub_cmd, matches);
332 return nullptr;
333}
334
Zachary Turner98896832016-11-13 02:50:32 +0000335void CommandObjectProxy::AproposAllSubCommands(llvm::StringRef prefix,
336 llvm::StringRef search_word,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337 StringList &commands_found,
338 StringList &commands_help) {
339 CommandObject *proxy_command = GetProxyCommandObject();
340 if (proxy_command)
341 return proxy_command->AproposAllSubCommands(prefix, search_word,
342 commands_found, commands_help);
343}
344
345bool CommandObjectProxy::LoadSubCommand(
Zachary Turner98896832016-11-13 02:50:32 +0000346 llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 CommandObject *proxy_command = GetProxyCommandObject();
348 if (proxy_command)
349 return proxy_command->LoadSubCommand(cmd_name, command_sp);
350 return false;
351}
352
353bool CommandObjectProxy::WantsRawCommandString() {
354 CommandObject *proxy_command = GetProxyCommandObject();
355 if (proxy_command)
356 return proxy_command->WantsRawCommandString();
357 return false;
358}
359
360bool CommandObjectProxy::WantsCompletion() {
361 CommandObject *proxy_command = GetProxyCommandObject();
362 if (proxy_command)
363 return proxy_command->WantsCompletion();
364 return false;
365}
366
367Options *CommandObjectProxy::GetOptions() {
368 CommandObject *proxy_command = GetProxyCommandObject();
369 if (proxy_command)
370 return proxy_command->GetOptions();
371 return nullptr;
372}
373
374int CommandObjectProxy::HandleCompletion(Args &input, int &cursor_index,
Eugene Zelenko26cac3a2016-02-20 00:58:29 +0000375 int &cursor_char_position,
376 int match_start_point,
377 int max_return_elements,
378 bool &word_complete,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379 StringList &matches) {
380 CommandObject *proxy_command = GetProxyCommandObject();
381 if (proxy_command)
382 return proxy_command->HandleCompletion(
383 input, cursor_index, cursor_char_position, match_start_point,
384 max_return_elements, word_complete, matches);
385 matches.Clear();
386 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000387}
388
Kate Stoneb9c1b512016-09-06 20:57:50 +0000389int CommandObjectProxy::HandleArgumentCompletion(
390 Args &input, int &cursor_index, int &cursor_char_position,
391 OptionElementVector &opt_element_vector, int match_start_point,
392 int max_return_elements, bool &word_complete, StringList &matches) {
393 CommandObject *proxy_command = GetProxyCommandObject();
394 if (proxy_command)
395 return proxy_command->HandleArgumentCompletion(
396 input, cursor_index, cursor_char_position, opt_element_vector,
397 match_start_point, max_return_elements, word_complete, matches);
398 matches.Clear();
399 return 0;
Jim Inghamebc09c32010-07-07 03:36:20 +0000400}
401
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402const char *CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
403 uint32_t index) {
404 CommandObject *proxy_command = GetProxyCommandObject();
405 if (proxy_command)
406 return proxy_command->GetRepeatCommand(current_command_args, index);
407 return nullptr;
Greg Clayton998255b2012-10-13 02:07:45 +0000408}
409
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410bool CommandObjectProxy::Execute(const char *args_string,
411 CommandReturnObject &result) {
412 CommandObject *proxy_command = GetProxyCommandObject();
413 if (proxy_command)
414 return proxy_command->Execute(args_string, result);
415 result.AppendError("command is not implemented");
416 result.SetStatus(eReturnStatusFailed);
417 return false;
Greg Clayton998255b2012-10-13 02:07:45 +0000418}