xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- CommandObjectMultiword.cpp ----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f3fbd1c0SDimitry Andric #include "lldb/Interpreter/CommandObjectMultiword.h"
10f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
11f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
1214f1b3e8SDimitry Andric #include "lldb/Interpreter/Options.h"
13e3b55780SDimitry Andric #include <optional>
14f034231aSEd Maste 
15f034231aSEd Maste using namespace lldb;
16f034231aSEd Maste using namespace lldb_private;
17f034231aSEd Maste 
18f034231aSEd Maste // CommandObjectMultiword
19f034231aSEd Maste 
CommandObjectMultiword(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)20f3fbd1c0SDimitry Andric CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
21f034231aSEd Maste                                                const char *name,
22f034231aSEd Maste                                                const char *help,
23f034231aSEd Maste                                                const char *syntax,
2414f1b3e8SDimitry Andric                                                uint32_t flags)
2514f1b3e8SDimitry Andric     : CommandObject(interpreter, name, help, syntax, flags),
2614f1b3e8SDimitry Andric       m_can_be_removed(false) {}
27f034231aSEd Maste 
28f3fbd1c0SDimitry Andric CommandObjectMultiword::~CommandObjectMultiword() = default;
29f034231aSEd Maste 
30c0981da4SDimitry Andric CommandObjectSP
GetSubcommandSPExact(llvm::StringRef sub_cmd)31c0981da4SDimitry Andric CommandObjectMultiword::GetSubcommandSPExact(llvm::StringRef sub_cmd) {
32c0981da4SDimitry Andric   if (m_subcommand_dict.empty())
33c0981da4SDimitry Andric     return {};
34c0981da4SDimitry Andric 
35c0981da4SDimitry Andric   auto pos = m_subcommand_dict.find(std::string(sub_cmd));
36c0981da4SDimitry Andric   if (pos == m_subcommand_dict.end())
37c0981da4SDimitry Andric     return {};
38c0981da4SDimitry Andric 
39c0981da4SDimitry Andric   return pos->second;
40c0981da4SDimitry Andric }
41c0981da4SDimitry Andric 
GetSubcommandSP(llvm::StringRef sub_cmd,StringList * matches)4214f1b3e8SDimitry Andric CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
4314f1b3e8SDimitry Andric                                                         StringList *matches) {
44c0981da4SDimitry Andric   if (m_subcommand_dict.empty())
45c0981da4SDimitry Andric     return {};
46f034231aSEd Maste 
47c0981da4SDimitry Andric   CommandObjectSP return_cmd_sp = GetSubcommandSPExact(sub_cmd);
48c0981da4SDimitry Andric   if (return_cmd_sp) {
49f034231aSEd Maste     if (matches)
50f034231aSEd Maste       matches->AppendString(sub_cmd);
51c0981da4SDimitry Andric     return return_cmd_sp;
52c0981da4SDimitry Andric   }
53c0981da4SDimitry Andric 
54c0981da4SDimitry Andric   CommandObject::CommandMap::iterator pos;
55c0981da4SDimitry Andric 
56f034231aSEd Maste   StringList local_matches;
57f3fbd1c0SDimitry Andric   if (matches == nullptr)
58f034231aSEd Maste     matches = &local_matches;
5914f1b3e8SDimitry Andric   int num_matches =
6014f1b3e8SDimitry Andric       AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);
61f034231aSEd Maste 
6214f1b3e8SDimitry Andric   if (num_matches == 1) {
6314f1b3e8SDimitry Andric     // Cleaner, but slightly less efficient would be to call back into this
64f73363f1SDimitry Andric     // function, since I now know I have an exact match...
65f034231aSEd Maste 
66f034231aSEd Maste     sub_cmd = matches->GetStringAtIndex(0);
67cfca06d7SDimitry Andric     pos = m_subcommand_dict.find(std::string(sub_cmd));
68f034231aSEd Maste     if (pos != m_subcommand_dict.end())
69f034231aSEd Maste       return_cmd_sp = pos->second;
70f034231aSEd Maste   }
71c0981da4SDimitry Andric 
72f034231aSEd Maste   return return_cmd_sp;
73f034231aSEd Maste }
74f034231aSEd Maste 
75f034231aSEd Maste CommandObject *
GetSubcommandObject(llvm::StringRef sub_cmd,StringList * matches)7614f1b3e8SDimitry Andric CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
7714f1b3e8SDimitry Andric                                             StringList *matches) {
78f034231aSEd Maste   return GetSubcommandSP(sub_cmd, matches).get();
79f034231aSEd Maste }
80f034231aSEd Maste 
LoadSubCommand(llvm::StringRef name,const CommandObjectSP & cmd_obj_sp)8114f1b3e8SDimitry Andric bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
82c0981da4SDimitry Andric                                             const CommandObjectSP &cmd_obj_sp) {
83c0981da4SDimitry Andric   if (cmd_obj_sp)
84c0981da4SDimitry Andric     lldbassert((&GetCommandInterpreter() == &cmd_obj_sp->GetCommandInterpreter()) &&
8514f1b3e8SDimitry Andric            "tried to add a CommandObject from a different interpreter");
86f3fbd1c0SDimitry Andric 
87f034231aSEd Maste   CommandMap::iterator pos;
88f034231aSEd Maste   bool success = true;
89f034231aSEd Maste 
90cfca06d7SDimitry Andric   pos = m_subcommand_dict.find(std::string(name));
9114f1b3e8SDimitry Andric   if (pos == m_subcommand_dict.end()) {
92c0981da4SDimitry Andric     m_subcommand_dict[std::string(name)] = cmd_obj_sp;
9314f1b3e8SDimitry Andric   } else
94f034231aSEd Maste     success = false;
95f034231aSEd Maste 
96f034231aSEd Maste   return success;
97f034231aSEd Maste }
98f034231aSEd Maste 
LoadUserSubcommand(llvm::StringRef name,const CommandObjectSP & cmd_obj_sp,bool can_replace)99c0981da4SDimitry Andric llvm::Error CommandObjectMultiword::LoadUserSubcommand(
100c0981da4SDimitry Andric     llvm::StringRef name, const CommandObjectSP &cmd_obj_sp, bool can_replace) {
101c0981da4SDimitry Andric   Status result;
102c0981da4SDimitry Andric   if (cmd_obj_sp)
103c0981da4SDimitry Andric     lldbassert((&GetCommandInterpreter() == &cmd_obj_sp->GetCommandInterpreter()) &&
104c0981da4SDimitry Andric            "tried to add a CommandObject from a different interpreter");
105c0981da4SDimitry Andric   if (!IsUserCommand()) {
106c0981da4SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
107c0981da4SDimitry Andric                               "can't add a user subcommand to a builtin container command.");
108c0981da4SDimitry Andric   }
109c0981da4SDimitry Andric   // Make sure this a user command if it isn't already:
110c0981da4SDimitry Andric   cmd_obj_sp->SetIsUserCommand(true);
111c0981da4SDimitry Andric 
112c0981da4SDimitry Andric   std::string str_name(name);
113c0981da4SDimitry Andric 
114c0981da4SDimitry Andric   auto pos = m_subcommand_dict.find(str_name);
115c0981da4SDimitry Andric   if (pos == m_subcommand_dict.end()) {
116c0981da4SDimitry Andric     m_subcommand_dict[str_name] = cmd_obj_sp;
117c0981da4SDimitry Andric     return llvm::Error::success();
118c0981da4SDimitry Andric   }
119c0981da4SDimitry Andric 
120c0981da4SDimitry Andric   const char *error_str = nullptr;
121c0981da4SDimitry Andric   if (!can_replace)
122c0981da4SDimitry Andric     error_str = "sub-command already exists";
123c0981da4SDimitry Andric   if (!(*pos).second->IsUserCommand())
124c0981da4SDimitry Andric     error_str = "can't replace a builtin subcommand";
125c0981da4SDimitry Andric 
126c0981da4SDimitry Andric   if (error_str) {
127c0981da4SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(), error_str);
128c0981da4SDimitry Andric   }
129c0981da4SDimitry Andric   m_subcommand_dict[str_name] = cmd_obj_sp;
130c0981da4SDimitry Andric   return llvm::Error::success();
131c0981da4SDimitry Andric }
132c0981da4SDimitry Andric 
RemoveUserSubcommand(llvm::StringRef cmd_name,bool must_be_multiword)133c0981da4SDimitry Andric llvm::Error CommandObjectMultiword::RemoveUserSubcommand(llvm::StringRef cmd_name,
134c0981da4SDimitry Andric                                                     bool must_be_multiword) {
135c0981da4SDimitry Andric   CommandMap::iterator pos;
136c0981da4SDimitry Andric   std::string str_name(cmd_name);
137c0981da4SDimitry Andric 
138c0981da4SDimitry Andric   pos = m_subcommand_dict.find(str_name);
139c0981da4SDimitry Andric   if (pos == m_subcommand_dict.end()) {
140c0981da4SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' not found.",
141c0981da4SDimitry Andric                                    str_name.c_str());
142c0981da4SDimitry Andric   }
143c0981da4SDimitry Andric   if (!(*pos).second->IsUserCommand()) {
144c0981da4SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' not a user command.",
145c0981da4SDimitry Andric                                    str_name.c_str());
146c0981da4SDimitry Andric   }
147c0981da4SDimitry Andric 
148c0981da4SDimitry Andric   if (must_be_multiword && !(*pos).second->IsMultiwordObject()) {
149c0981da4SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' is not a container command",
150c0981da4SDimitry Andric                                    str_name.c_str());
151c0981da4SDimitry Andric   }
152c0981da4SDimitry Andric   if (!must_be_multiword && (*pos).second->IsMultiwordObject()) {
153c0981da4SDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' is not a user command",
154c0981da4SDimitry Andric                                    str_name.c_str());
155c0981da4SDimitry Andric   }
156c0981da4SDimitry Andric 
157c0981da4SDimitry Andric   m_subcommand_dict.erase(pos);
158c0981da4SDimitry Andric 
159c0981da4SDimitry Andric   return llvm::Error::success();
160c0981da4SDimitry Andric }
161c0981da4SDimitry Andric 
Execute(const char * args_string,CommandReturnObject & result)162b1c73532SDimitry Andric void CommandObjectMultiword::Execute(const char *args_string,
16314f1b3e8SDimitry Andric                                      CommandReturnObject &result) {
164f034231aSEd Maste   Args args(args_string);
165f034231aSEd Maste   const size_t argc = args.GetArgumentCount();
16614f1b3e8SDimitry Andric   if (argc == 0) {
167f034231aSEd Maste     this->CommandObject::GenerateHelpText(result);
168b1c73532SDimitry Andric     return;
169f034231aSEd Maste   }
170f034231aSEd Maste 
171ead24645SDimitry Andric   auto sub_command = args[0].ref();
172ead24645SDimitry Andric   if (sub_command.empty()) {
173ead24645SDimitry Andric     result.AppendError("Need to specify a non-empty subcommand.");
174b1c73532SDimitry Andric     return;
175ead24645SDimitry Andric   }
17614f1b3e8SDimitry Andric 
17714f1b3e8SDimitry Andric   if (m_subcommand_dict.empty()) {
17814f1b3e8SDimitry Andric     result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
17914f1b3e8SDimitry Andric                                  GetCommandName().str().c_str());
180b1c73532SDimitry Andric     return;
18114f1b3e8SDimitry Andric   }
18214f1b3e8SDimitry Andric 
183f034231aSEd Maste   StringList matches;
184f034231aSEd Maste   CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
18514f1b3e8SDimitry Andric   if (sub_cmd_obj != nullptr) {
18614f1b3e8SDimitry Andric     // Now call CommandObject::Execute to process options in `rest_of_line`.
187f73363f1SDimitry Andric     // From there the command-specific version of Execute will be called, with
188f73363f1SDimitry Andric     // the processed arguments.
189f034231aSEd Maste 
190f034231aSEd Maste     args.Shift();
191f034231aSEd Maste     sub_cmd_obj->Execute(args_string, result);
192b1c73532SDimitry Andric     return;
193f034231aSEd Maste   }
19414f1b3e8SDimitry Andric 
195f034231aSEd Maste   std::string error_msg;
196f034231aSEd Maste   const size_t num_subcmd_matches = matches.GetSize();
197f034231aSEd Maste   if (num_subcmd_matches > 0)
198f034231aSEd Maste     error_msg.assign("ambiguous command ");
199f034231aSEd Maste   else
200f034231aSEd Maste     error_msg.assign("invalid command ");
201f034231aSEd Maste 
202f034231aSEd Maste   error_msg.append("'");
203cfca06d7SDimitry Andric   error_msg.append(std::string(GetCommandName()));
204f034231aSEd Maste   error_msg.append(" ");
205cfca06d7SDimitry Andric   error_msg.append(std::string(sub_command));
2065e95aa85SEd Maste   error_msg.append("'.");
207f034231aSEd Maste 
20814f1b3e8SDimitry Andric   if (num_subcmd_matches > 0) {
209f034231aSEd Maste     error_msg.append(" Possible completions:");
210ead24645SDimitry Andric     for (const std::string &match : matches) {
211f034231aSEd Maste       error_msg.append("\n\t");
212ead24645SDimitry Andric       error_msg.append(match);
213f034231aSEd Maste     }
214f034231aSEd Maste   }
215f034231aSEd Maste   error_msg.append("\n");
216f034231aSEd Maste   result.AppendRawError(error_msg.c_str());
217f034231aSEd Maste }
218f034231aSEd Maste 
GenerateHelpText(Stream & output_stream)21914f1b3e8SDimitry Andric void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
220f73363f1SDimitry Andric   // First time through here, generate the help text for the object and push it
221f73363f1SDimitry Andric   // to the return result object as well
222f034231aSEd Maste 
223f3fbd1c0SDimitry Andric   CommandObject::GenerateHelpText(output_stream);
224f3fbd1c0SDimitry Andric   output_stream.PutCString("\nThe following subcommands are supported:\n\n");
225f034231aSEd Maste 
226f034231aSEd Maste   CommandMap::iterator pos;
227f3fbd1c0SDimitry Andric   uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
228f034231aSEd Maste 
229f034231aSEd Maste   if (max_len)
230f034231aSEd Maste     max_len += 4; // Indent the output by 4 spaces.
231f034231aSEd Maste 
23214f1b3e8SDimitry Andric   for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
233f034231aSEd Maste     std::string indented_command("    ");
234f034231aSEd Maste     indented_command.append(pos->first);
23514f1b3e8SDimitry Andric     if (pos->second->WantsRawCommandString()) {
236cfca06d7SDimitry Andric       std::string help_text(std::string(pos->second->GetHelp()));
237f3fbd1c0SDimitry Andric       help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
238cfca06d7SDimitry Andric       m_interpreter.OutputFormattedHelpText(output_stream, indented_command,
239cfca06d7SDimitry Andric                                             "--", help_text, max_len);
24014f1b3e8SDimitry Andric     } else
241cfca06d7SDimitry Andric       m_interpreter.OutputFormattedHelpText(output_stream, indented_command,
242cfca06d7SDimitry Andric                                             "--", pos->second->GetHelp(),
243cfca06d7SDimitry Andric                                             max_len);
244f034231aSEd Maste   }
245f034231aSEd Maste 
24614f1b3e8SDimitry Andric   output_stream.PutCString("\nFor more help on any particular subcommand, type "
24714f1b3e8SDimitry Andric                            "'help <command> <subcommand>'.\n");
248f034231aSEd Maste }
249f034231aSEd Maste 
HandleCompletion(CompletionRequest & request)250ead24645SDimitry Andric void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
251ead24645SDimitry Andric   auto arg0 = request.GetParsedLine()[0].ref();
252f73363f1SDimitry Andric   if (request.GetCursorIndex() == 0) {
25394994d37SDimitry Andric     StringList new_matches, descriptions;
25494994d37SDimitry Andric     AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
25594994d37SDimitry Andric                                   &descriptions);
25694994d37SDimitry Andric     request.AddCompletions(new_matches, descriptions);
257f034231aSEd Maste 
25839be7ce2SDimitry Andric     if (new_matches.GetSize() == 1 &&
25939be7ce2SDimitry Andric         new_matches.GetStringAtIndex(0) != nullptr &&
26039be7ce2SDimitry Andric         (arg0 == new_matches.GetStringAtIndex(0))) {
261f034231aSEd Maste       StringList temp_matches;
26214f1b3e8SDimitry Andric       CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
26314f1b3e8SDimitry Andric       if (cmd_obj != nullptr) {
264ead24645SDimitry Andric         if (request.GetParsedLine().GetArgumentCount() != 1) {
265f73363f1SDimitry Andric           request.GetParsedLine().Shift();
266ead24645SDimitry Andric           request.AppendEmptyArgument();
267ead24645SDimitry Andric           cmd_obj->HandleCompletion(request);
268f034231aSEd Maste         }
269f034231aSEd Maste       }
2705e95aa85SEd Maste     }
271ead24645SDimitry Andric     return;
272ead24645SDimitry Andric   }
273ead24645SDimitry Andric 
27439be7ce2SDimitry Andric   StringList new_matches;
27539be7ce2SDimitry Andric   CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);
2767fa27ce4SDimitry Andric 
2777fa27ce4SDimitry Andric   // The subcommand is ambiguous. The completion isn't meaningful.
2787fa27ce4SDimitry Andric   if (!sub_command_object)
279ead24645SDimitry Andric     return;
280ead24645SDimitry Andric 
281f034231aSEd Maste   // Remove the one match that we got from calling GetSubcommandObject.
28239be7ce2SDimitry Andric   new_matches.DeleteStringAtIndex(0);
28339be7ce2SDimitry Andric   request.AddCompletions(new_matches);
284ead24645SDimitry Andric   request.ShiftArguments();
285ead24645SDimitry Andric   sub_command_object->HandleCompletion(request);
286f034231aSEd Maste }
287f034231aSEd Maste 
288e3b55780SDimitry Andric std::optional<std::string>
GetRepeatCommand(Args & current_command_args,uint32_t index)289145449b1SDimitry Andric CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
29014f1b3e8SDimitry Andric                                          uint32_t index) {
291f034231aSEd Maste   index++;
292f034231aSEd Maste   if (current_command_args.GetArgumentCount() <= index)
293e3b55780SDimitry Andric     return std::nullopt;
29414f1b3e8SDimitry Andric   CommandObject *sub_command_object =
295ead24645SDimitry Andric       GetSubcommandObject(current_command_args[index].ref());
296f3fbd1c0SDimitry Andric   if (sub_command_object == nullptr)
297e3b55780SDimitry Andric     return std::nullopt;
298f034231aSEd Maste   return sub_command_object->GetRepeatCommand(current_command_args, index);
299f034231aSEd Maste }
300f034231aSEd Maste 
CommandObjectProxy(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)301f034231aSEd Maste CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
30214f1b3e8SDimitry Andric                                        const char *name, const char *help,
30314f1b3e8SDimitry Andric                                        const char *syntax, uint32_t flags)
30414f1b3e8SDimitry Andric     : CommandObject(interpreter, name, help, syntax, flags) {}
305f034231aSEd Maste 
306f3fbd1c0SDimitry Andric CommandObjectProxy::~CommandObjectProxy() = default;
307f034231aSEd Maste 
GetOptions()308b60736ecSDimitry Andric Options *CommandObjectProxy::GetOptions() {
309b60736ecSDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
310b60736ecSDimitry Andric   if (proxy_command)
311b60736ecSDimitry Andric     return proxy_command->GetOptions();
312b60736ecSDimitry Andric   return CommandObject::GetOptions();
313b60736ecSDimitry Andric }
314b60736ecSDimitry Andric 
GetHelp()315b60736ecSDimitry Andric llvm::StringRef CommandObjectProxy::GetHelp() {
316b60736ecSDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
317b60736ecSDimitry Andric   if (proxy_command)
318b60736ecSDimitry Andric     return proxy_command->GetHelp();
319b60736ecSDimitry Andric   return CommandObject::GetHelp();
320b60736ecSDimitry Andric }
321b60736ecSDimitry Andric 
GetSyntax()322b60736ecSDimitry Andric llvm::StringRef CommandObjectProxy::GetSyntax() {
323b60736ecSDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
324b60736ecSDimitry Andric   if (proxy_command)
325b60736ecSDimitry Andric     return proxy_command->GetSyntax();
326b60736ecSDimitry Andric   return CommandObject::GetSyntax();
327b60736ecSDimitry Andric }
328b60736ecSDimitry Andric 
GetHelpLong()32914f1b3e8SDimitry Andric llvm::StringRef CommandObjectProxy::GetHelpLong() {
330f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
331f034231aSEd Maste   if (proxy_command)
332f034231aSEd Maste     return proxy_command->GetHelpLong();
333b60736ecSDimitry Andric   return CommandObject::GetHelpLong();
334f034231aSEd Maste }
335f034231aSEd Maste 
IsRemovable() const33614f1b3e8SDimitry Andric bool CommandObjectProxy::IsRemovable() const {
33714f1b3e8SDimitry Andric   const CommandObject *proxy_command =
33814f1b3e8SDimitry Andric       const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
339f034231aSEd Maste   if (proxy_command)
340f034231aSEd Maste     return proxy_command->IsRemovable();
341f034231aSEd Maste   return false;
342f034231aSEd Maste }
343f034231aSEd Maste 
IsMultiwordObject()34414f1b3e8SDimitry Andric bool CommandObjectProxy::IsMultiwordObject() {
345f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
346f034231aSEd Maste   if (proxy_command)
347f034231aSEd Maste     return proxy_command->IsMultiwordObject();
348f034231aSEd Maste   return false;
349f034231aSEd Maste }
350f034231aSEd Maste 
GetAsMultiwordCommand()35114f1b3e8SDimitry Andric CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
352f3fbd1c0SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
353f3fbd1c0SDimitry Andric   if (proxy_command)
354f3fbd1c0SDimitry Andric     return proxy_command->GetAsMultiwordCommand();
355f3fbd1c0SDimitry Andric   return nullptr;
356f3fbd1c0SDimitry Andric }
357f3fbd1c0SDimitry Andric 
GenerateHelpText(Stream & result)35814f1b3e8SDimitry Andric void CommandObjectProxy::GenerateHelpText(Stream &result) {
359e81d9d49SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
360e81d9d49SDimitry Andric   if (proxy_command)
361b60736ecSDimitry Andric     proxy_command->GenerateHelpText(result);
362b60736ecSDimitry Andric   else
363b60736ecSDimitry Andric     CommandObject::GenerateHelpText(result);
364e81d9d49SDimitry Andric }
365e81d9d49SDimitry Andric 
366f034231aSEd Maste lldb::CommandObjectSP
GetSubcommandSP(llvm::StringRef sub_cmd,StringList * matches)36714f1b3e8SDimitry Andric CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
36814f1b3e8SDimitry Andric                                     StringList *matches) {
369f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
370f034231aSEd Maste   if (proxy_command)
371f034231aSEd Maste     return proxy_command->GetSubcommandSP(sub_cmd, matches);
372f034231aSEd Maste   return lldb::CommandObjectSP();
373f034231aSEd Maste }
374f034231aSEd Maste 
GetSubcommandObject(llvm::StringRef sub_cmd,StringList * matches)37514f1b3e8SDimitry Andric CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
37614f1b3e8SDimitry Andric                                                        StringList *matches) {
377f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
378f034231aSEd Maste   if (proxy_command)
379f034231aSEd Maste     return proxy_command->GetSubcommandObject(sub_cmd, matches);
380f3fbd1c0SDimitry Andric   return nullptr;
381f034231aSEd Maste }
382f034231aSEd Maste 
LoadSubCommand(llvm::StringRef cmd_name,const lldb::CommandObjectSP & command_sp)38314f1b3e8SDimitry Andric bool CommandObjectProxy::LoadSubCommand(
38414f1b3e8SDimitry Andric     llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
385f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
386f034231aSEd Maste   if (proxy_command)
387f034231aSEd Maste     return proxy_command->LoadSubCommand(cmd_name, command_sp);
388f034231aSEd Maste   return false;
389f034231aSEd Maste }
390f034231aSEd Maste 
WantsRawCommandString()39114f1b3e8SDimitry Andric bool CommandObjectProxy::WantsRawCommandString() {
392f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
393f034231aSEd Maste   if (proxy_command)
394f034231aSEd Maste     return proxy_command->WantsRawCommandString();
395f034231aSEd Maste   return false;
396f034231aSEd Maste }
397f034231aSEd Maste 
WantsCompletion()39814f1b3e8SDimitry Andric bool CommandObjectProxy::WantsCompletion() {
399f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
400f034231aSEd Maste   if (proxy_command)
401f034231aSEd Maste     return proxy_command->WantsCompletion();
402f034231aSEd Maste   return false;
403f034231aSEd Maste }
404f034231aSEd Maste 
HandleCompletion(CompletionRequest & request)405ead24645SDimitry Andric void CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
406f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
407f034231aSEd Maste   if (proxy_command)
408ead24645SDimitry Andric     proxy_command->HandleCompletion(request);
409f034231aSEd Maste }
410f3fbd1c0SDimitry Andric 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)411ead24645SDimitry Andric void CommandObjectProxy::HandleArgumentCompletion(
412f73363f1SDimitry Andric     CompletionRequest &request, OptionElementVector &opt_element_vector) {
413f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
414f034231aSEd Maste   if (proxy_command)
415ead24645SDimitry Andric     proxy_command->HandleArgumentCompletion(request, opt_element_vector);
416f034231aSEd Maste }
417f034231aSEd Maste 
418e3b55780SDimitry Andric std::optional<std::string>
GetRepeatCommand(Args & current_command_args,uint32_t index)419145449b1SDimitry Andric CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
42014f1b3e8SDimitry Andric                                      uint32_t index) {
421f034231aSEd Maste   CommandObject *proxy_command = GetProxyCommandObject();
422f034231aSEd Maste   if (proxy_command)
423f034231aSEd Maste     return proxy_command->GetRepeatCommand(current_command_args, index);
424e3b55780SDimitry Andric   return std::nullopt;
425f034231aSEd Maste }
426f034231aSEd Maste 
GetUnsupportedError()427b60736ecSDimitry Andric llvm::StringRef CommandObjectProxy::GetUnsupportedError() {
428b60736ecSDimitry Andric   return "command is not implemented";
429b60736ecSDimitry Andric }
430b60736ecSDimitry Andric 
Execute(const char * args_string,CommandReturnObject & result)431b1c73532SDimitry Andric void CommandObjectProxy::Execute(const char *args_string,
43214f1b3e8SDimitry Andric                                  CommandReturnObject &result) {
433b1c73532SDimitry Andric   if (CommandObject *proxy_command = GetProxyCommandObject())
434b1c73532SDimitry Andric     proxy_command->Execute(args_string, result);
435b1c73532SDimitry Andric   else
436344a3780SDimitry Andric     result.AppendError(GetUnsupportedError());
437f034231aSEd Maste }
438