]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Commands / CommandObjectMultiword.cpp
1 //===-- 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
10 #include "lldb/Interpreter/CommandObjectMultiword.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Interpreter/CommandInterpreter.h"
13 #include "lldb/Interpreter/CommandReturnObject.h"
14 #include "lldb/Interpreter/Options.h"
15
16 using namespace lldb;
17 using namespace lldb_private;
18
19 //-------------------------------------------------------------------------
20 // CommandObjectMultiword
21 //-------------------------------------------------------------------------
22
23 CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
24                                                const char *name,
25                                                const char *help,
26                                                const char *syntax,
27                                                uint32_t flags)
28     : CommandObject(interpreter, name, help, syntax, flags),
29       m_can_be_removed(false) {}
30
31 CommandObjectMultiword::~CommandObjectMultiword() = default;
32
33 CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
34                                                         StringList *matches) {
35   CommandObjectSP return_cmd_sp;
36   CommandObject::CommandMap::iterator pos;
37
38   if (!m_subcommand_dict.empty()) {
39     pos = m_subcommand_dict.find(sub_cmd);
40     if (pos != m_subcommand_dict.end()) {
41       // An exact match; append the sub_cmd to the 'matches' string list.
42       if (matches)
43         matches->AppendString(sub_cmd);
44       return_cmd_sp = pos->second;
45     } else {
46       StringList local_matches;
47       if (matches == nullptr)
48         matches = &local_matches;
49       int num_matches =
50           AddNamesMatchingPartialString(m_subcommand_dict, sub_cmd, *matches);
51
52       if (num_matches == 1) {
53         // Cleaner, but slightly less efficient would be to call back into this
54         // function, since I now know I have an exact match...
55
56         sub_cmd = matches->GetStringAtIndex(0);
57         pos = m_subcommand_dict.find(sub_cmd);
58         if (pos != m_subcommand_dict.end())
59           return_cmd_sp = pos->second;
60       }
61     }
62   }
63   return return_cmd_sp;
64 }
65
66 CommandObject *
67 CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
68                                             StringList *matches) {
69   return GetSubcommandSP(sub_cmd, matches).get();
70 }
71
72 bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
73                                             const CommandObjectSP &cmd_obj) {
74   if (cmd_obj)
75     assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) &&
76            "tried to add a CommandObject from a different interpreter");
77
78   CommandMap::iterator pos;
79   bool success = true;
80
81   pos = m_subcommand_dict.find(name);
82   if (pos == m_subcommand_dict.end()) {
83     m_subcommand_dict[name] = cmd_obj;
84   } else
85     success = false;
86
87   return success;
88 }
89
90 bool CommandObjectMultiword::Execute(const char *args_string,
91                                      CommandReturnObject &result) {
92   Args args(args_string);
93   const size_t argc = args.GetArgumentCount();
94   if (argc == 0) {
95     this->CommandObject::GenerateHelpText(result);
96     return result.Succeeded();
97   }
98
99   auto sub_command = args[0].ref;
100   if (sub_command.empty())
101     return result.Succeeded();
102
103   if (sub_command.equals_lower("help")) {
104     this->CommandObject::GenerateHelpText(result);
105     return result.Succeeded();
106   }
107
108   if (m_subcommand_dict.empty()) {
109     result.AppendErrorWithFormat("'%s' does not have any subcommands.\n",
110                                  GetCommandName().str().c_str());
111     result.SetStatus(eReturnStatusFailed);
112     return false;
113   }
114
115   StringList matches;
116   CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
117   if (sub_cmd_obj != nullptr) {
118     // Now call CommandObject::Execute to process options in `rest_of_line`.
119     // From there the command-specific version of Execute will be called, with
120     // the processed arguments.
121
122     args.Shift();
123     sub_cmd_obj->Execute(args_string, result);
124     return result.Succeeded();
125   }
126
127   std::string error_msg;
128   const size_t num_subcmd_matches = matches.GetSize();
129   if (num_subcmd_matches > 0)
130     error_msg.assign("ambiguous command ");
131   else
132     error_msg.assign("invalid command ");
133
134   error_msg.append("'");
135   error_msg.append(GetCommandName());
136   error_msg.append(" ");
137   error_msg.append(sub_command);
138   error_msg.append("'.");
139
140   if (num_subcmd_matches > 0) {
141     error_msg.append(" Possible completions:");
142     for (size_t i = 0; i < matches.GetSize(); i++) {
143       error_msg.append("\n\t");
144       error_msg.append(matches.GetStringAtIndex(i));
145     }
146   }
147   error_msg.append("\n");
148   result.AppendRawError(error_msg.c_str());
149   result.SetStatus(eReturnStatusFailed);
150   return false;
151 }
152
153 void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) {
154   // First time through here, generate the help text for the object and push it
155   // to the return result object as well
156
157   CommandObject::GenerateHelpText(output_stream);
158   output_stream.PutCString("\nThe following subcommands are supported:\n\n");
159
160   CommandMap::iterator pos;
161   uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
162
163   if (max_len)
164     max_len += 4; // Indent the output by 4 spaces.
165
166   for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
167     std::string indented_command("    ");
168     indented_command.append(pos->first);
169     if (pos->second->WantsRawCommandString()) {
170       std::string help_text(pos->second->GetHelp());
171       help_text.append("  Expects 'raw' input (see 'help raw-input'.)");
172       m_interpreter.OutputFormattedHelpText(output_stream,
173                                             indented_command.c_str(), "--",
174                                             help_text.c_str(), max_len);
175     } else
176       m_interpreter.OutputFormattedHelpText(output_stream,
177                                             indented_command.c_str(), "--",
178                                             pos->second->GetHelp(), max_len);
179   }
180
181   output_stream.PutCString("\nFor more help on any particular subcommand, type "
182                            "'help <command> <subcommand>'.\n");
183 }
184
185 int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
186   // Any of the command matches will provide a complete word, otherwise the
187   // individual completers will override this.
188   request.SetWordComplete(true);
189
190   auto arg0 = request.GetParsedLine()[0].ref;
191   if (request.GetCursorIndex() == 0) {
192     StringList new_matches, descriptions;
193     AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
194                                   &descriptions);
195     request.AddCompletions(new_matches, descriptions);
196
197     if (new_matches.GetSize() == 1 &&
198         new_matches.GetStringAtIndex(0) != nullptr &&
199         (arg0 == new_matches.GetStringAtIndex(0))) {
200       StringList temp_matches;
201       CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
202       if (cmd_obj != nullptr) {
203         if (request.GetParsedLine().GetArgumentCount() == 1) {
204           request.SetWordComplete(true);
205         } else {
206           request.GetParsedLine().Shift();
207           request.SetCursorCharPosition(0);
208           request.GetParsedLine().AppendArgument(llvm::StringRef());
209           return cmd_obj->HandleCompletion(request);
210         }
211       }
212     }
213     return new_matches.GetSize();
214   } else {
215     StringList new_matches;
216     CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches);
217     if (sub_command_object == nullptr) {
218       request.AddCompletions(new_matches);
219       return request.GetNumberOfMatches();
220     } else {
221       // Remove the one match that we got from calling GetSubcommandObject.
222       new_matches.DeleteStringAtIndex(0);
223       request.AddCompletions(new_matches);
224       request.GetParsedLine().Shift();
225       request.SetCursorIndex(request.GetCursorIndex() - 1);
226       return sub_command_object->HandleCompletion(request);
227     }
228   }
229 }
230
231 const char *CommandObjectMultiword::GetRepeatCommand(Args &current_command_args,
232                                                      uint32_t index) {
233   index++;
234   if (current_command_args.GetArgumentCount() <= index)
235     return nullptr;
236   CommandObject *sub_command_object =
237       GetSubcommandObject(current_command_args[index].ref);
238   if (sub_command_object == nullptr)
239     return nullptr;
240   return sub_command_object->GetRepeatCommand(current_command_args, index);
241 }
242
243 void CommandObjectMultiword::AproposAllSubCommands(llvm::StringRef prefix,
244                                                    llvm::StringRef search_word,
245                                                    StringList &commands_found,
246                                                    StringList &commands_help) {
247   CommandObject::CommandMap::const_iterator pos;
248
249   for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) {
250     const char *command_name = pos->first.c_str();
251     CommandObject *sub_cmd_obj = pos->second.get();
252     StreamString complete_command_name;
253
254     complete_command_name << prefix << " " << command_name;
255
256     if (sub_cmd_obj->HelpTextContainsWord(search_word)) {
257       commands_found.AppendString(complete_command_name.GetString());
258       commands_help.AppendString(sub_cmd_obj->GetHelp());
259     }
260
261     if (sub_cmd_obj->IsMultiwordObject())
262       sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetString(),
263                                          search_word, commands_found,
264                                          commands_help);
265   }
266 }
267
268 CommandObjectProxy::CommandObjectProxy(CommandInterpreter &interpreter,
269                                        const char *name, const char *help,
270                                        const char *syntax, uint32_t flags)
271     : CommandObject(interpreter, name, help, syntax, flags) {}
272
273 CommandObjectProxy::~CommandObjectProxy() = default;
274
275 llvm::StringRef CommandObjectProxy::GetHelpLong() {
276   CommandObject *proxy_command = GetProxyCommandObject();
277   if (proxy_command)
278     return proxy_command->GetHelpLong();
279   return llvm::StringRef();
280 }
281
282 bool CommandObjectProxy::IsRemovable() const {
283   const CommandObject *proxy_command =
284       const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
285   if (proxy_command)
286     return proxy_command->IsRemovable();
287   return false;
288 }
289
290 bool CommandObjectProxy::IsMultiwordObject() {
291   CommandObject *proxy_command = GetProxyCommandObject();
292   if (proxy_command)
293     return proxy_command->IsMultiwordObject();
294   return false;
295 }
296
297 CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
298   CommandObject *proxy_command = GetProxyCommandObject();
299   if (proxy_command)
300     return proxy_command->GetAsMultiwordCommand();
301   return nullptr;
302 }
303
304 void CommandObjectProxy::GenerateHelpText(Stream &result) {
305   CommandObject *proxy_command = GetProxyCommandObject();
306   if (proxy_command)
307     return proxy_command->GenerateHelpText(result);
308 }
309
310 lldb::CommandObjectSP
311 CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
312                                     StringList *matches) {
313   CommandObject *proxy_command = GetProxyCommandObject();
314   if (proxy_command)
315     return proxy_command->GetSubcommandSP(sub_cmd, matches);
316   return lldb::CommandObjectSP();
317 }
318
319 CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
320                                                        StringList *matches) {
321   CommandObject *proxy_command = GetProxyCommandObject();
322   if (proxy_command)
323     return proxy_command->GetSubcommandObject(sub_cmd, matches);
324   return nullptr;
325 }
326
327 void CommandObjectProxy::AproposAllSubCommands(llvm::StringRef prefix,
328                                                llvm::StringRef search_word,
329                                                StringList &commands_found,
330                                                StringList &commands_help) {
331   CommandObject *proxy_command = GetProxyCommandObject();
332   if (proxy_command)
333     return proxy_command->AproposAllSubCommands(prefix, search_word,
334                                                 commands_found, commands_help);
335 }
336
337 bool CommandObjectProxy::LoadSubCommand(
338     llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
339   CommandObject *proxy_command = GetProxyCommandObject();
340   if (proxy_command)
341     return proxy_command->LoadSubCommand(cmd_name, command_sp);
342   return false;
343 }
344
345 bool CommandObjectProxy::WantsRawCommandString() {
346   CommandObject *proxy_command = GetProxyCommandObject();
347   if (proxy_command)
348     return proxy_command->WantsRawCommandString();
349   return false;
350 }
351
352 bool CommandObjectProxy::WantsCompletion() {
353   CommandObject *proxy_command = GetProxyCommandObject();
354   if (proxy_command)
355     return proxy_command->WantsCompletion();
356   return false;
357 }
358
359 Options *CommandObjectProxy::GetOptions() {
360   CommandObject *proxy_command = GetProxyCommandObject();
361   if (proxy_command)
362     return proxy_command->GetOptions();
363   return nullptr;
364 }
365
366 int CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
367   CommandObject *proxy_command = GetProxyCommandObject();
368   if (proxy_command)
369     return proxy_command->HandleCompletion(request);
370   return 0;
371 }
372
373 int CommandObjectProxy::HandleArgumentCompletion(
374     CompletionRequest &request, OptionElementVector &opt_element_vector) {
375   CommandObject *proxy_command = GetProxyCommandObject();
376   if (proxy_command)
377     return proxy_command->HandleArgumentCompletion(request, opt_element_vector);
378   return 0;
379 }
380
381 const char *CommandObjectProxy::GetRepeatCommand(Args &current_command_args,
382                                                  uint32_t index) {
383   CommandObject *proxy_command = GetProxyCommandObject();
384   if (proxy_command)
385     return proxy_command->GetRepeatCommand(current_command_args, index);
386   return nullptr;
387 }
388
389 bool CommandObjectProxy::Execute(const char *args_string,
390                                  CommandReturnObject &result) {
391   CommandObject *proxy_command = GetProxyCommandObject();
392   if (proxy_command)
393     return proxy_command->Execute(args_string, result);
394   result.AppendError("command is not implemented");
395   result.SetStatus(eReturnStatusFailed);
396   return false;
397 }