[PowerPC] Collect some CallLowering arguments into a struct. [NFC]
[llvm-project.git] / lldb / source / Commands / CommandObjectMultiword.cpp
blob67225d3d6b8db18259533e7485f8ee757219b830
1 //===-- CommandObjectMultiword.cpp ------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Interpreter/CommandObjectMultiword.h"
10 #include "lldb/Interpreter/CommandInterpreter.h"
11 #include "lldb/Interpreter/CommandReturnObject.h"
12 #include "lldb/Interpreter/Options.h"
14 using namespace lldb;
15 using namespace lldb_private;
17 // CommandObjectMultiword
19 CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
20 const char *name,
21 const char *help,
22 const char *syntax,
23 uint32_t flags)
24 : CommandObject(interpreter, name, help, syntax, flags),
25 m_can_be_removed(false) {}
27 CommandObjectMultiword::~CommandObjectMultiword() = default;
29 CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
30 StringList *matches) {
31 CommandObjectSP return_cmd_sp;
32 CommandObject::CommandMap::iterator pos;
34 if (!m_subcommand_dict.empty()) {
35 pos = m_subcommand_dict.find(sub_cmd);
36 if (pos != m_subcommand_dict.end()) {
37 // An exact match; append the sub_cmd to the 'matches' string list.
38 if (matches)
39 matches->AppendString(sub_cmd);
40 return_cmd_sp = pos->second;
41 } else {
42 StringList local_matches;
43 if (matches == nullptr)
44 matches = &local_matches;
45 int num_matches =
46 AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);
48 if (num_matches == 1) {
49 // Cleaner, but slightly less efficient would be to call back into this
50 // function, since I now know I have an exact match...
52 sub_cmd = matches->GetStringAtIndex(0);
53 pos = m_subcommand_dict.find(sub_cmd);
54 if (pos != m_subcommand_dict.end())
55 return_cmd_sp = pos->second;
59 return return_cmd_sp;
62 CommandObject *
63 CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
64 StringList *matches) {
65 return GetSubcommandSP(sub_cmd, matches).get();
68 bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
69 const CommandObjectSP &cmd_obj) {
70 if (cmd_obj)
71 assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) &&
72 "tried to add a CommandObject from a different interpreter");
74 CommandMap::iterator pos;
75 bool success = true;
77 pos = m_subcommand_dict.find(name);
78 if (pos == m_subcommand_dict.end()) {
79 m_subcommand_dict[name] = cmd_obj;
80 } else
81 success = false;
83 return success;
86 bool CommandObjectMultiword::Execute(const char *args_string,
87 CommandReturnObject &result) {
88 Args args(args_string);
89 const size_t argc = args.GetArgumentCount();
90 if (argc == 0) {
91 this->CommandObject::GenerateHelpText(result);
92 return result.Succeeded();
95 auto sub_command = args[0].ref();
96 if (sub_command.empty()) {
97 result.AppendError("Need to specify a non-empty subcommand.");
98 return result.Succeeded();
101 if (sub_command.equals_lower("help")) {
102 this->CommandObject::GenerateHelpText(result);
103 return result.Succeeded();
106 if (m_subcommand_dict.empty()) {
107 result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
108 GetCommandName().str().c_str());
109 result.SetStatus(eReturnStatusFailed);
110 return false;
113 StringList matches;
114 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
115 if (sub_cmd_obj != nullptr) {
116 // Now call CommandObject::Execute to process options in `rest_of_line`.
117 // From there the command-specific version of Execute will be called, with
118 // the processed arguments.
120 args.Shift();
121 sub_cmd_obj->Execute(args_string, result);
122 return result.Succeeded();
125 std::string error_msg;
126 const size_t num_subcmd_matches = matches.GetSize();
127 if (num_subcmd_matches > 0)
128 error_msg.assign("ambiguous command ");
129 else
130 error_msg.assign("invalid command ");
132 error_msg.append("'");
133 error_msg.append(GetCommandName());
134 error_msg.append(" ");
135 error_msg.append(sub_command);
136 error_msg.append("'.");
138 if (num_subcmd_matches > 0) {
139 error_msg.append(" Possible completions:");
140 for (const std::string &match : matches) {
141 error_msg.append("\n\t");
142 error_msg.append(match);
145 error_msg.append("\n");
146 result.AppendRawError(error_msg.c_str());
147 result.SetStatus(eReturnStatusFailed);
148 return false;
151 void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
152 // First time through here, generate the help text for the object and push it
153 // to the return result object as well
155 CommandObject::GenerateHelpText(output_stream);
156 output_stream.PutCString("\nThe following subcommands are supported:\n\n");
158 CommandMap::iterator pos;
159 uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
161 if (max_len)
162 max_len += 4; // Indent the output by 4 spaces.
164 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
165 std::string indented_command(" ");
166 indented_command.append(pos->first);
167 if (pos->second->WantsRawCommandString()) {
168 std::string help_text(pos->second->GetHelp());
169 help_text.append(" Expects 'raw' input (see 'help raw-input'.)");
170 m_interpreter.OutputFormattedHelpText(output_stream,
171 indented_command.c_str(), "--",
172 help_text.c_str(), max_len);
173 } else
174 m_interpreter.OutputFormattedHelpText(output_stream,
175 indented_command.c_str(), "--",
176 pos->second->GetHelp(), max_len);
179 output_stream.PutCString("\nFor more help on any particular subcommand, type "
180 "'help <command> <subcommand>'.\n");
183 void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
184 auto arg0 = request.GetParsedLine()[0].ref();
185 if (request.GetCursorIndex() == 0) {
186 StringList new_matches, descriptions;
187 AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
188 &descriptions);
189 request.AddCompletions(new_matches, descriptions);
191 if (new_matches.GetSize() == 1 &&
192 new_matches.GetStringAtIndex(0) != nullptr &&
193 (arg0 == new_matches.GetStringAtIndex(0))) {
194 StringList temp_matches;
195 CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
196 if (cmd_obj != nullptr) {
197 if (request.GetParsedLine().GetArgumentCount() != 1) {
198 request.GetParsedLine().Shift();
199 request.AppendEmptyArgument();
200 cmd_obj->HandleCompletion(request);
204 return;
207 StringList new_matches;
208 CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);
209 if (sub_command_object == nullptr) {
210 request.AddCompletions(new_matches);
211 return;
214 // Remove the one match that we got from calling GetSubcommandObject.
215 new_matches.DeleteStringAtIndex(0);
216 request.AddCompletions(new_matches);
217 request.ShiftArguments();
218 sub_command_object->HandleCompletion(request);
221 const char *CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
222 uint32_t index) {
223 index++;
224 if (current_command_args.GetArgumentCount() <= index)
225 return nullptr;
226 CommandObject *sub_command_object =
227 GetSubcommandObject(current_command_args[index].ref());
228 if (sub_command_object == nullptr)
229 return nullptr;
230 return sub_command_object->GetRepeatCommand(current_command_args, index);
233 void CommandObjectMultiword::AproposAllSubCommands(llvm::StringRef prefix,
234 llvm::StringRef search_word,
235 StringList &commands_found,
236 StringList &commands_help) {
237 CommandObject::CommandMap::const_iterator pos;
239 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
240 const char *command_name = pos->first.c_str();
241 CommandObject *sub_cmd_obj = pos->second.get();
242 StreamString complete_command_name;
244 complete_command_name << prefix << " " << command_name;
246 if (sub_cmd_obj->HelpTextContainsWord(search_word)) {
247 commands_found.AppendString(complete_command_name.GetString());
248 commands_help.AppendString(sub_cmd_obj->GetHelp());
251 if (sub_cmd_obj->IsMultiwordObject())
252 sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetString(),
253 search_word, commands_found,
254 commands_help);
258 CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
259 const char *name, const char *help,
260 const char *syntax, uint32_t flags)
261 : CommandObject(interpreter, name, help, syntax, flags) {}
263 CommandObjectProxy::~CommandObjectProxy() = default;
265 llvm::StringRef CommandObjectProxy::GetHelpLong() {
266 CommandObject *proxy_command = GetProxyCommandObject();
267 if (proxy_command)
268 return proxy_command->GetHelpLong();
269 return llvm::StringRef();
272 bool CommandObjectProxy::IsRemovable() const {
273 const CommandObject *proxy_command =
274 const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
275 if (proxy_command)
276 return proxy_command->IsRemovable();
277 return false;
280 bool CommandObjectProxy::IsMultiwordObject() {
281 CommandObject *proxy_command = GetProxyCommandObject();
282 if (proxy_command)
283 return proxy_command->IsMultiwordObject();
284 return false;
287 CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
288 CommandObject *proxy_command = GetProxyCommandObject();
289 if (proxy_command)
290 return proxy_command->GetAsMultiwordCommand();
291 return nullptr;
294 void CommandObjectProxy::GenerateHelpText(Stream &result) {
295 CommandObject *proxy_command = GetProxyCommandObject();
296 if (proxy_command)
297 return proxy_command->GenerateHelpText(result);
300 lldb::CommandObjectSP
301 CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
302 StringList *matches) {
303 CommandObject *proxy_command = GetProxyCommandObject();
304 if (proxy_command)
305 return proxy_command->GetSubcommandSP(sub_cmd, matches);
306 return lldb::CommandObjectSP();
309 CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
310 StringList *matches) {
311 CommandObject *proxy_command = GetProxyCommandObject();
312 if (proxy_command)
313 return proxy_command->GetSubcommandObject(sub_cmd, matches);
314 return nullptr;
317 void CommandObjectProxy::AproposAllSubCommands(llvm::StringRef prefix,
318 llvm::StringRef search_word,
319 StringList &commands_found,
320 StringList &commands_help) {
321 CommandObject *proxy_command = GetProxyCommandObject();
322 if (proxy_command)
323 return proxy_command->AproposAllSubCommands(prefix, search_word,
324 commands_found, commands_help);
327 bool CommandObjectProxy::LoadSubCommand(
328 llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
329 CommandObject *proxy_command = GetProxyCommandObject();
330 if (proxy_command)
331 return proxy_command->LoadSubCommand(cmd_name, command_sp);
332 return false;
335 bool CommandObjectProxy::WantsRawCommandString() {
336 CommandObject *proxy_command = GetProxyCommandObject();
337 if (proxy_command)
338 return proxy_command->WantsRawCommandString();
339 return false;
342 bool CommandObjectProxy::WantsCompletion() {
343 CommandObject *proxy_command = GetProxyCommandObject();
344 if (proxy_command)
345 return proxy_command->WantsCompletion();
346 return false;
349 Options *CommandObjectProxy::GetOptions() {
350 CommandObject *proxy_command = GetProxyCommandObject();
351 if (proxy_command)
352 return proxy_command->GetOptions();
353 return nullptr;
356 void CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
357 CommandObject *proxy_command = GetProxyCommandObject();
358 if (proxy_command)
359 proxy_command->HandleCompletion(request);
362 void CommandObjectProxy::HandleArgumentCompletion(
363 CompletionRequest &request, OptionElementVector &opt_element_vector) {
364 CommandObject *proxy_command = GetProxyCommandObject();
365 if (proxy_command)
366 proxy_command->HandleArgumentCompletion(request, opt_element_vector);
369 const char *CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
370 uint32_t index) {
371 CommandObject *proxy_command = GetProxyCommandObject();
372 if (proxy_command)
373 return proxy_command->GetRepeatCommand(current_command_args, index);
374 return nullptr;
377 bool CommandObjectProxy::Execute(const char *args_string,
378 CommandReturnObject &result) {
379 CommandObject *proxy_command = GetProxyCommandObject();
380 if (proxy_command)
381 return proxy_command->Execute(args_string, result);
382 result.AppendError("command is not implemented");
383 result.SetStatus(eReturnStatusFailed);
384 return false;