xref: /freebsd-src/contrib/llvm-project/lldb/source/Commands/CommandObjectMultiword.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
15ffd83dbSDimitry Andric //===-- CommandObjectMultiword.cpp ----------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Interpreter/CommandObjectMultiword.h"
100b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
110b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
120b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
13bdd1243dSDimitry Andric #include <optional>
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric using namespace lldb;
160b57cec5SDimitry Andric using namespace lldb_private;
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric // CommandObjectMultiword
190b57cec5SDimitry Andric 
CommandObjectMultiword(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)200b57cec5SDimitry Andric CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
210b57cec5SDimitry Andric                                                const char *name,
220b57cec5SDimitry Andric                                                const char *help,
230b57cec5SDimitry Andric                                                const char *syntax,
240b57cec5SDimitry Andric                                                uint32_t flags)
250b57cec5SDimitry Andric     : CommandObject(interpreter, name, help, syntax, flags),
260b57cec5SDimitry Andric       m_can_be_removed(false) {}
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric CommandObjectMultiword::~CommandObjectMultiword() = default;
290b57cec5SDimitry Andric 
30349cc55cSDimitry Andric CommandObjectSP
GetSubcommandSPExact(llvm::StringRef sub_cmd)31349cc55cSDimitry Andric CommandObjectMultiword::GetSubcommandSPExact(llvm::StringRef sub_cmd) {
32349cc55cSDimitry Andric   if (m_subcommand_dict.empty())
33349cc55cSDimitry Andric     return {};
34349cc55cSDimitry Andric 
35349cc55cSDimitry Andric   auto pos = m_subcommand_dict.find(std::string(sub_cmd));
36349cc55cSDimitry Andric   if (pos == m_subcommand_dict.end())
37349cc55cSDimitry Andric     return {};
38349cc55cSDimitry Andric 
39349cc55cSDimitry Andric   return pos->second;
40349cc55cSDimitry Andric }
41349cc55cSDimitry Andric 
GetSubcommandSP(llvm::StringRef sub_cmd,StringList * matches)420b57cec5SDimitry Andric CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
430b57cec5SDimitry Andric                                                         StringList *matches) {
44349cc55cSDimitry Andric   if (m_subcommand_dict.empty())
45349cc55cSDimitry Andric     return {};
460b57cec5SDimitry Andric 
47349cc55cSDimitry Andric   CommandObjectSP return_cmd_sp = GetSubcommandSPExact(sub_cmd);
48349cc55cSDimitry Andric   if (return_cmd_sp) {
490b57cec5SDimitry Andric     if (matches)
500b57cec5SDimitry Andric       matches->AppendString(sub_cmd);
51349cc55cSDimitry Andric     return return_cmd_sp;
52349cc55cSDimitry Andric   }
53349cc55cSDimitry Andric 
54349cc55cSDimitry Andric   CommandObject::CommandMap::iterator pos;
55349cc55cSDimitry Andric 
560b57cec5SDimitry Andric   StringList local_matches;
570b57cec5SDimitry Andric   if (matches == nullptr)
580b57cec5SDimitry Andric     matches = &local_matches;
590b57cec5SDimitry Andric   int num_matches =
600b57cec5SDimitry Andric       AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   if (num_matches == 1) {
630b57cec5SDimitry Andric     // Cleaner, but slightly less efficient would be to call back into this
640b57cec5SDimitry Andric     // function, since I now know I have an exact match...
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric     sub_cmd = matches->GetStringAtIndex(0);
675ffd83dbSDimitry Andric     pos = m_subcommand_dict.find(std::string(sub_cmd));
680b57cec5SDimitry Andric     if (pos != m_subcommand_dict.end())
690b57cec5SDimitry Andric       return_cmd_sp = pos->second;
700b57cec5SDimitry Andric   }
71349cc55cSDimitry Andric 
720b57cec5SDimitry Andric   return return_cmd_sp;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric CommandObject *
GetSubcommandObject(llvm::StringRef sub_cmd,StringList * matches)760b57cec5SDimitry Andric CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
770b57cec5SDimitry Andric                                             StringList *matches) {
780b57cec5SDimitry Andric   return GetSubcommandSP(sub_cmd, matches).get();
790b57cec5SDimitry Andric }
800b57cec5SDimitry Andric 
LoadSubCommand(llvm::StringRef name,const CommandObjectSP & cmd_obj_sp)810b57cec5SDimitry Andric bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
82349cc55cSDimitry Andric                                             const CommandObjectSP &cmd_obj_sp) {
83349cc55cSDimitry Andric   if (cmd_obj_sp)
84349cc55cSDimitry Andric     lldbassert((&GetCommandInterpreter() == &cmd_obj_sp->GetCommandInterpreter()) &&
850b57cec5SDimitry Andric            "tried to add a CommandObject from a different interpreter");
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   CommandMap::iterator pos;
880b57cec5SDimitry Andric   bool success = true;
890b57cec5SDimitry Andric 
905ffd83dbSDimitry Andric   pos = m_subcommand_dict.find(std::string(name));
910b57cec5SDimitry Andric   if (pos == m_subcommand_dict.end()) {
92349cc55cSDimitry Andric     m_subcommand_dict[std::string(name)] = cmd_obj_sp;
930b57cec5SDimitry Andric   } else
940b57cec5SDimitry Andric     success = false;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   return success;
970b57cec5SDimitry Andric }
980b57cec5SDimitry Andric 
LoadUserSubcommand(llvm::StringRef name,const CommandObjectSP & cmd_obj_sp,bool can_replace)99349cc55cSDimitry Andric llvm::Error CommandObjectMultiword::LoadUserSubcommand(
100349cc55cSDimitry Andric     llvm::StringRef name, const CommandObjectSP &cmd_obj_sp, bool can_replace) {
101349cc55cSDimitry Andric   Status result;
102349cc55cSDimitry Andric   if (cmd_obj_sp)
103349cc55cSDimitry Andric     lldbassert((&GetCommandInterpreter() == &cmd_obj_sp->GetCommandInterpreter()) &&
104349cc55cSDimitry Andric            "tried to add a CommandObject from a different interpreter");
105349cc55cSDimitry Andric   if (!IsUserCommand()) {
106349cc55cSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),
107349cc55cSDimitry Andric                               "can't add a user subcommand to a builtin container command.");
108349cc55cSDimitry Andric   }
109349cc55cSDimitry Andric   // Make sure this a user command if it isn't already:
110349cc55cSDimitry Andric   cmd_obj_sp->SetIsUserCommand(true);
111349cc55cSDimitry Andric 
112349cc55cSDimitry Andric   std::string str_name(name);
113349cc55cSDimitry Andric 
114349cc55cSDimitry Andric   auto pos = m_subcommand_dict.find(str_name);
115349cc55cSDimitry Andric   if (pos == m_subcommand_dict.end()) {
116349cc55cSDimitry Andric     m_subcommand_dict[str_name] = cmd_obj_sp;
117349cc55cSDimitry Andric     return llvm::Error::success();
118349cc55cSDimitry Andric   }
119349cc55cSDimitry Andric 
120349cc55cSDimitry Andric   const char *error_str = nullptr;
121349cc55cSDimitry Andric   if (!can_replace)
122349cc55cSDimitry Andric     error_str = "sub-command already exists";
123349cc55cSDimitry Andric   if (!(*pos).second->IsUserCommand())
124349cc55cSDimitry Andric     error_str = "can't replace a builtin subcommand";
125349cc55cSDimitry Andric 
126349cc55cSDimitry Andric   if (error_str) {
127349cc55cSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(), error_str);
128349cc55cSDimitry Andric   }
129349cc55cSDimitry Andric   m_subcommand_dict[str_name] = cmd_obj_sp;
130349cc55cSDimitry Andric   return llvm::Error::success();
131349cc55cSDimitry Andric }
132349cc55cSDimitry Andric 
RemoveUserSubcommand(llvm::StringRef cmd_name,bool must_be_multiword)133349cc55cSDimitry Andric llvm::Error CommandObjectMultiword::RemoveUserSubcommand(llvm::StringRef cmd_name,
134349cc55cSDimitry Andric                                                     bool must_be_multiword) {
135349cc55cSDimitry Andric   CommandMap::iterator pos;
136349cc55cSDimitry Andric   std::string str_name(cmd_name);
137349cc55cSDimitry Andric 
138349cc55cSDimitry Andric   pos = m_subcommand_dict.find(str_name);
139349cc55cSDimitry Andric   if (pos == m_subcommand_dict.end()) {
140349cc55cSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' not found.",
141349cc55cSDimitry Andric                                    str_name.c_str());
142349cc55cSDimitry Andric   }
143349cc55cSDimitry Andric   if (!(*pos).second->IsUserCommand()) {
144349cc55cSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' not a user command.",
145349cc55cSDimitry Andric                                    str_name.c_str());
146349cc55cSDimitry Andric   }
147349cc55cSDimitry Andric 
148349cc55cSDimitry Andric   if (must_be_multiword && !(*pos).second->IsMultiwordObject()) {
149349cc55cSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' is not a container command",
150349cc55cSDimitry Andric                                    str_name.c_str());
151349cc55cSDimitry Andric   }
152349cc55cSDimitry Andric   if (!must_be_multiword && (*pos).second->IsMultiwordObject()) {
153349cc55cSDimitry Andric     return llvm::createStringError(llvm::inconvertibleErrorCode(),"subcommand '%s' is not a user command",
154349cc55cSDimitry Andric                                    str_name.c_str());
155349cc55cSDimitry Andric   }
156349cc55cSDimitry Andric 
157349cc55cSDimitry Andric   m_subcommand_dict.erase(pos);
158349cc55cSDimitry Andric 
159349cc55cSDimitry Andric   return llvm::Error::success();
160349cc55cSDimitry Andric }
161349cc55cSDimitry Andric 
Execute(const char * args_string,CommandReturnObject & result)162*5f757f3fSDimitry Andric void CommandObjectMultiword::Execute(const char *args_string,
1630b57cec5SDimitry Andric                                      CommandReturnObject &result) {
1640b57cec5SDimitry Andric   Args args(args_string);
1650b57cec5SDimitry Andric   const size_t argc = args.GetArgumentCount();
1660b57cec5SDimitry Andric   if (argc == 0) {
1670b57cec5SDimitry Andric     this->CommandObject::GenerateHelpText(result);
168*5f757f3fSDimitry Andric     return;
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1719dba64beSDimitry Andric   auto sub_command = args[0].ref();
1729dba64beSDimitry Andric   if (sub_command.empty()) {
1739dba64beSDimitry Andric     result.AppendError("Need to specify a non-empty subcommand.");
174*5f757f3fSDimitry Andric     return;
1759dba64beSDimitry Andric   }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   if (m_subcommand_dict.empty()) {
1780b57cec5SDimitry Andric     result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
1790b57cec5SDimitry Andric                                  GetCommandName().str().c_str());
180*5f757f3fSDimitry Andric     return;
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   StringList matches;
1840b57cec5SDimitry Andric   CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
1850b57cec5SDimitry Andric   if (sub_cmd_obj != nullptr) {
1860b57cec5SDimitry Andric     // Now call CommandObject::Execute to process options in `rest_of_line`.
1870b57cec5SDimitry Andric     // From there the command-specific version of Execute will be called, with
1880b57cec5SDimitry Andric     // the processed arguments.
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     args.Shift();
1910b57cec5SDimitry Andric     sub_cmd_obj->Execute(args_string, result);
192*5f757f3fSDimitry Andric     return;
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   std::string error_msg;
1960b57cec5SDimitry Andric   const size_t num_subcmd_matches = matches.GetSize();
1970b57cec5SDimitry Andric   if (num_subcmd_matches > 0)
1980b57cec5SDimitry Andric     error_msg.assign("ambiguous command ");
1990b57cec5SDimitry Andric   else
2000b57cec5SDimitry Andric     error_msg.assign("invalid command ");
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   error_msg.append("'");
2035ffd83dbSDimitry Andric   error_msg.append(std::string(GetCommandName()));
2040b57cec5SDimitry Andric   error_msg.append(" ");
2055ffd83dbSDimitry Andric   error_msg.append(std::string(sub_command));
2060b57cec5SDimitry Andric   error_msg.append("'.");
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   if (num_subcmd_matches > 0) {
2090b57cec5SDimitry Andric     error_msg.append(" Possible completions:");
2109dba64beSDimitry Andric     for (const std::string &match : matches) {
2110b57cec5SDimitry Andric       error_msg.append("\n\t");
2129dba64beSDimitry Andric       error_msg.append(match);
2130b57cec5SDimitry Andric     }
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric   error_msg.append("\n");
2160b57cec5SDimitry Andric   result.AppendRawError(error_msg.c_str());
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
GenerateHelpText(Stream & output_stream)2190b57cec5SDimitry Andric void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
2200b57cec5SDimitry Andric   // First time through here, generate the help text for the object and push it
2210b57cec5SDimitry Andric   // to the return result object as well
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   CommandObject::GenerateHelpText(output_stream);
2240b57cec5SDimitry Andric   output_stream.PutCString("\nThe following subcommands are supported:\n\n");
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   CommandMap::iterator pos;
2270b57cec5SDimitry Andric   uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   if (max_len)
2300b57cec5SDimitry Andric     max_len += 4; // Indent the output by 4 spaces.
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
2330b57cec5SDimitry Andric     std::string indented_command("    ");
2340b57cec5SDimitry Andric     indented_command.append(pos->first);
2350b57cec5SDimitry Andric     if (pos->second->WantsRawCommandString()) {
2365ffd83dbSDimitry Andric       std::string help_text(std::string(pos->second->GetHelp()));
2370b57cec5SDimitry Andric       help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
2385ffd83dbSDimitry Andric       m_interpreter.OutputFormattedHelpText(output_stream, indented_command,
2395ffd83dbSDimitry Andric                                             "--", help_text, max_len);
2400b57cec5SDimitry Andric     } else
2415ffd83dbSDimitry Andric       m_interpreter.OutputFormattedHelpText(output_stream, indented_command,
2425ffd83dbSDimitry Andric                                             "--", pos->second->GetHelp(),
2435ffd83dbSDimitry Andric                                             max_len);
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   output_stream.PutCString("\nFor more help on any particular subcommand, type "
2470b57cec5SDimitry Andric                            "'help <command> <subcommand>'.\n");
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
HandleCompletion(CompletionRequest & request)2509dba64beSDimitry Andric void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
2519dba64beSDimitry Andric   auto arg0 = request.GetParsedLine()[0].ref();
2520b57cec5SDimitry Andric   if (request.GetCursorIndex() == 0) {
2530b57cec5SDimitry Andric     StringList new_matches, descriptions;
2540b57cec5SDimitry Andric     AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
2550b57cec5SDimitry Andric                                   &descriptions);
2560b57cec5SDimitry Andric     request.AddCompletions(new_matches, descriptions);
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     if (new_matches.GetSize() == 1 &&
2590b57cec5SDimitry Andric         new_matches.GetStringAtIndex(0) != nullptr &&
2600b57cec5SDimitry Andric         (arg0 == new_matches.GetStringAtIndex(0))) {
2610b57cec5SDimitry Andric       StringList temp_matches;
2620b57cec5SDimitry Andric       CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
2630b57cec5SDimitry Andric       if (cmd_obj != nullptr) {
2649dba64beSDimitry Andric         if (request.GetParsedLine().GetArgumentCount() != 1) {
2650b57cec5SDimitry Andric           request.GetParsedLine().Shift();
2669dba64beSDimitry Andric           request.AppendEmptyArgument();
2679dba64beSDimitry Andric           cmd_obj->HandleCompletion(request);
2680b57cec5SDimitry Andric         }
2690b57cec5SDimitry Andric       }
2700b57cec5SDimitry Andric     }
2719dba64beSDimitry Andric     return;
2729dba64beSDimitry Andric   }
2739dba64beSDimitry Andric 
2740b57cec5SDimitry Andric   StringList new_matches;
2750b57cec5SDimitry Andric   CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);
27606c3fb27SDimitry Andric 
27706c3fb27SDimitry Andric   // The subcommand is ambiguous. The completion isn't meaningful.
27806c3fb27SDimitry Andric   if (!sub_command_object)
2799dba64beSDimitry Andric     return;
2809dba64beSDimitry Andric 
2810b57cec5SDimitry Andric   // Remove the one match that we got from calling GetSubcommandObject.
2820b57cec5SDimitry Andric   new_matches.DeleteStringAtIndex(0);
2830b57cec5SDimitry Andric   request.AddCompletions(new_matches);
2849dba64beSDimitry Andric   request.ShiftArguments();
2859dba64beSDimitry Andric   sub_command_object->HandleCompletion(request);
2860b57cec5SDimitry Andric }
2870b57cec5SDimitry Andric 
288bdd1243dSDimitry Andric std::optional<std::string>
GetRepeatCommand(Args & current_command_args,uint32_t index)28981ad6265SDimitry Andric CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
2900b57cec5SDimitry Andric                                          uint32_t index) {
2910b57cec5SDimitry Andric   index++;
2920b57cec5SDimitry Andric   if (current_command_args.GetArgumentCount() <= index)
293bdd1243dSDimitry Andric     return std::nullopt;
2940b57cec5SDimitry Andric   CommandObject *sub_command_object =
2959dba64beSDimitry Andric       GetSubcommandObject(current_command_args[index].ref());
2960b57cec5SDimitry Andric   if (sub_command_object == nullptr)
297bdd1243dSDimitry Andric     return std::nullopt;
2980b57cec5SDimitry Andric   return sub_command_object->GetRepeatCommand(current_command_args, index);
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
CommandObjectProxy(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags)3010b57cec5SDimitry Andric CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
3020b57cec5SDimitry Andric                                        const char *name, const char *help,
3030b57cec5SDimitry Andric                                        const char *syntax, uint32_t flags)
3040b57cec5SDimitry Andric     : CommandObject(interpreter, name, help, syntax, flags) {}
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric CommandObjectProxy::~CommandObjectProxy() = default;
3070b57cec5SDimitry Andric 
GetOptions()308e8d8bef9SDimitry Andric Options *CommandObjectProxy::GetOptions() {
309e8d8bef9SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
310e8d8bef9SDimitry Andric   if (proxy_command)
311e8d8bef9SDimitry Andric     return proxy_command->GetOptions();
312e8d8bef9SDimitry Andric   return CommandObject::GetOptions();
313e8d8bef9SDimitry Andric }
314e8d8bef9SDimitry Andric 
GetHelp()315e8d8bef9SDimitry Andric llvm::StringRef CommandObjectProxy::GetHelp() {
316e8d8bef9SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
317e8d8bef9SDimitry Andric   if (proxy_command)
318e8d8bef9SDimitry Andric     return proxy_command->GetHelp();
319e8d8bef9SDimitry Andric   return CommandObject::GetHelp();
320e8d8bef9SDimitry Andric }
321e8d8bef9SDimitry Andric 
GetSyntax()322e8d8bef9SDimitry Andric llvm::StringRef CommandObjectProxy::GetSyntax() {
323e8d8bef9SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
324e8d8bef9SDimitry Andric   if (proxy_command)
325e8d8bef9SDimitry Andric     return proxy_command->GetSyntax();
326e8d8bef9SDimitry Andric   return CommandObject::GetSyntax();
327e8d8bef9SDimitry Andric }
328e8d8bef9SDimitry Andric 
GetHelpLong()3290b57cec5SDimitry Andric llvm::StringRef CommandObjectProxy::GetHelpLong() {
3300b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3310b57cec5SDimitry Andric   if (proxy_command)
3320b57cec5SDimitry Andric     return proxy_command->GetHelpLong();
333e8d8bef9SDimitry Andric   return CommandObject::GetHelpLong();
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
IsRemovable() const3360b57cec5SDimitry Andric bool CommandObjectProxy::IsRemovable() const {
3370b57cec5SDimitry Andric   const CommandObject *proxy_command =
3380b57cec5SDimitry Andric       const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
3390b57cec5SDimitry Andric   if (proxy_command)
3400b57cec5SDimitry Andric     return proxy_command->IsRemovable();
3410b57cec5SDimitry Andric   return false;
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
IsMultiwordObject()3440b57cec5SDimitry Andric bool CommandObjectProxy::IsMultiwordObject() {
3450b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3460b57cec5SDimitry Andric   if (proxy_command)
3470b57cec5SDimitry Andric     return proxy_command->IsMultiwordObject();
3480b57cec5SDimitry Andric   return false;
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
GetAsMultiwordCommand()3510b57cec5SDimitry Andric CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
3520b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3530b57cec5SDimitry Andric   if (proxy_command)
3540b57cec5SDimitry Andric     return proxy_command->GetAsMultiwordCommand();
3550b57cec5SDimitry Andric   return nullptr;
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric 
GenerateHelpText(Stream & result)3580b57cec5SDimitry Andric void CommandObjectProxy::GenerateHelpText(Stream &result) {
3590b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3600b57cec5SDimitry Andric   if (proxy_command)
361e8d8bef9SDimitry Andric     proxy_command->GenerateHelpText(result);
362e8d8bef9SDimitry Andric   else
363e8d8bef9SDimitry Andric     CommandObject::GenerateHelpText(result);
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric lldb::CommandObjectSP
GetSubcommandSP(llvm::StringRef sub_cmd,StringList * matches)3670b57cec5SDimitry Andric CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
3680b57cec5SDimitry Andric                                     StringList *matches) {
3690b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3700b57cec5SDimitry Andric   if (proxy_command)
3710b57cec5SDimitry Andric     return proxy_command->GetSubcommandSP(sub_cmd, matches);
3720b57cec5SDimitry Andric   return lldb::CommandObjectSP();
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
GetSubcommandObject(llvm::StringRef sub_cmd,StringList * matches)3750b57cec5SDimitry Andric CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
3760b57cec5SDimitry Andric                                                        StringList *matches) {
3770b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3780b57cec5SDimitry Andric   if (proxy_command)
3790b57cec5SDimitry Andric     return proxy_command->GetSubcommandObject(sub_cmd, matches);
3800b57cec5SDimitry Andric   return nullptr;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
LoadSubCommand(llvm::StringRef cmd_name,const lldb::CommandObjectSP & command_sp)3830b57cec5SDimitry Andric bool CommandObjectProxy::LoadSubCommand(
3840b57cec5SDimitry Andric     llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
3850b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3860b57cec5SDimitry Andric   if (proxy_command)
3870b57cec5SDimitry Andric     return proxy_command->LoadSubCommand(cmd_name, command_sp);
3880b57cec5SDimitry Andric   return false;
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
WantsRawCommandString()3910b57cec5SDimitry Andric bool CommandObjectProxy::WantsRawCommandString() {
3920b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
3930b57cec5SDimitry Andric   if (proxy_command)
3940b57cec5SDimitry Andric     return proxy_command->WantsRawCommandString();
3950b57cec5SDimitry Andric   return false;
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric 
WantsCompletion()3980b57cec5SDimitry Andric bool CommandObjectProxy::WantsCompletion() {
3990b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
4000b57cec5SDimitry Andric   if (proxy_command)
4010b57cec5SDimitry Andric     return proxy_command->WantsCompletion();
4020b57cec5SDimitry Andric   return false;
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
HandleCompletion(CompletionRequest & request)4059dba64beSDimitry Andric void CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
4060b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
4070b57cec5SDimitry Andric   if (proxy_command)
4089dba64beSDimitry Andric     proxy_command->HandleCompletion(request);
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)4119dba64beSDimitry Andric void CommandObjectProxy::HandleArgumentCompletion(
4120b57cec5SDimitry Andric     CompletionRequest &request, OptionElementVector &opt_element_vector) {
4130b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
4140b57cec5SDimitry Andric   if (proxy_command)
4159dba64beSDimitry Andric     proxy_command->HandleArgumentCompletion(request, opt_element_vector);
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric 
418bdd1243dSDimitry Andric std::optional<std::string>
GetRepeatCommand(Args & current_command_args,uint32_t index)41981ad6265SDimitry Andric CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
4200b57cec5SDimitry Andric                                      uint32_t index) {
4210b57cec5SDimitry Andric   CommandObject *proxy_command = GetProxyCommandObject();
4220b57cec5SDimitry Andric   if (proxy_command)
4230b57cec5SDimitry Andric     return proxy_command->GetRepeatCommand(current_command_args, index);
424bdd1243dSDimitry Andric   return std::nullopt;
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric 
GetUnsupportedError()427e8d8bef9SDimitry Andric llvm::StringRef CommandObjectProxy::GetUnsupportedError() {
428e8d8bef9SDimitry Andric   return "command is not implemented";
429e8d8bef9SDimitry Andric }
430e8d8bef9SDimitry Andric 
Execute(const char * args_string,CommandReturnObject & result)431*5f757f3fSDimitry Andric void CommandObjectProxy::Execute(const char *args_string,
4320b57cec5SDimitry Andric                                  CommandReturnObject &result) {
433*5f757f3fSDimitry Andric   if (CommandObject *proxy_command = GetProxyCommandObject())
434*5f757f3fSDimitry Andric     proxy_command->Execute(args_string, result);
435*5f757f3fSDimitry Andric   else
436fe6060f1SDimitry Andric     result.AppendError(GetUnsupportedError());
4370b57cec5SDimitry Andric }
438