]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Commands/CommandObjectMultiword.cpp
Merge upstream r4302 to support multiple concurrently valid anchors.
[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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/Interpreter/CommandObjectMultiword.h"
15 #include "lldb/Core/Debugger.h"
16 #include "lldb/Interpreter/CommandInterpreter.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/Options.h"
19
20 using namespace lldb;
21 using namespace lldb_private;
22
23 //-------------------------------------------------------------------------
24 // CommandObjectMultiword
25 //-------------------------------------------------------------------------
26
27 CommandObjectMultiword::CommandObjectMultiword(CommandInterpreter &interpreter,
28                                                const char *name,
29                                                const char *help,
30                                                const char *syntax,
31                                                uint32_t flags)
32     : CommandObject(interpreter, name, help, syntax, flags),
33       m_can_be_removed(false) {}
34
35 CommandObjectMultiword::~CommandObjectMultiword() = default;
36
37 CommandObjectSP CommandObjectMultiword::GetSubcommandSP(llvm::StringRef sub_cmd,
38                                                         StringList *matches) {
39   CommandObjectSP return_cmd_sp;
40   CommandObject::CommandMap::iterator pos;
41
42   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);
55
56       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...
60
61         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       }
66     }
67   }
68   return return_cmd_sp;
69 }
70
71 CommandObject *
72 CommandObjectMultiword::GetSubcommandObject(llvm::StringRef sub_cmd,
73                                             StringList *matches) {
74   return GetSubcommandSP(sub_cmd, matches).get();
75 }
76
77 bool CommandObjectMultiword::LoadSubCommand(llvm::StringRef name,
78                                             const CommandObjectSP &cmd_obj) {
79   if (cmd_obj)
80     assert((&GetCommandInterpreter() == &cmd_obj->GetCommandInterpreter()) &&
81            "tried to add a CommandObject from a different interpreter");
82
83   CommandMap::iterator pos;
84   bool success = true;
85
86   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;
93 }
94
95 bool 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);
101     return result.Succeeded();
102   }
103
104   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;
156 }
157
158 void 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
161
162   CommandObject::GenerateHelpText(output_stream);
163   output_stream.PutCString("\nThe following subcommands are supported:\n\n");
164
165   CommandMap::iterator pos;
166   uint32_t max_len = FindLongestCommandWord(m_subcommand_dict);
167
168   if (max_len)
169     max_len += 4; // Indent the output by 4 spaces.
170
171   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
190 int 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
197   // individual completers will override this.
198   word_complete = true;
199
200   auto arg0 = input[0].ref;
201   if (cursor_index == 0) {
202     AddNamesMatchingPartialString(m_subcommand_dict, arg0, matches);
203
204     if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != nullptr &&
205         (arg0 == matches.GetStringAtIndex(0))) {
206       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;
215           input.AppendArgument(llvm::StringRef());
216           return cmd_obj->HandleCompletion(
217               input, cursor_index, cursor_char_position, match_start_point,
218               max_return_elements, word_complete, matches);
219         }
220       }
221     }
222     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   }
237 }
238
239 const 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 =
245       GetSubcommandObject(current_command_args[index].ref);
246   if (sub_command_object == nullptr)
247     return nullptr;
248   return sub_command_object->GetRepeatCommand(current_command_args, index);
249 }
250
251 void CommandObjectMultiword::AproposAllSubCommands(llvm::StringRef prefix,
252                                                    llvm::StringRef search_word,
253                                                    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
262     complete_command_name << prefix << " " << command_name;
263
264     if (sub_cmd_obj->HelpTextContainsWord(search_word)) {
265       commands_found.AppendString(complete_command_name.GetString());
266       commands_help.AppendString(sub_cmd_obj->GetHelp());
267     }
268
269     if (sub_cmd_obj->IsMultiwordObject())
270       sub_cmd_obj->AproposAllSubCommands(complete_command_name.GetString(),
271                                          search_word, commands_found,
272                                          commands_help);
273   }
274 }
275
276 CommandObjectProxy::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
281 CommandObjectProxy::~CommandObjectProxy() = default;
282
283 llvm::StringRef CommandObjectProxy::GetHelpLong() {
284   CommandObject *proxy_command = GetProxyCommandObject();
285   if (proxy_command)
286     return proxy_command->GetHelpLong();
287   return llvm::StringRef();
288 }
289
290 bool 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
298 bool CommandObjectProxy::IsMultiwordObject() {
299   CommandObject *proxy_command = GetProxyCommandObject();
300   if (proxy_command)
301     return proxy_command->IsMultiwordObject();
302   return false;
303 }
304
305 CommandObjectMultiword *CommandObjectProxy::GetAsMultiwordCommand() {
306   CommandObject *proxy_command = GetProxyCommandObject();
307   if (proxy_command)
308     return proxy_command->GetAsMultiwordCommand();
309   return nullptr;
310 }
311
312 void CommandObjectProxy::GenerateHelpText(Stream &result) {
313   CommandObject *proxy_command = GetProxyCommandObject();
314   if (proxy_command)
315     return proxy_command->GenerateHelpText(result);
316 }
317
318 lldb::CommandObjectSP
319 CommandObjectProxy::GetSubcommandSP(llvm::StringRef sub_cmd,
320                                     StringList *matches) {
321   CommandObject *proxy_command = GetProxyCommandObject();
322   if (proxy_command)
323     return proxy_command->GetSubcommandSP(sub_cmd, matches);
324   return lldb::CommandObjectSP();
325 }
326
327 CommandObject *CommandObjectProxy::GetSubcommandObject(llvm::StringRef sub_cmd,
328                                                        StringList *matches) {
329   CommandObject *proxy_command = GetProxyCommandObject();
330   if (proxy_command)
331     return proxy_command->GetSubcommandObject(sub_cmd, matches);
332   return nullptr;
333 }
334
335 void CommandObjectProxy::AproposAllSubCommands(llvm::StringRef prefix,
336                                                llvm::StringRef search_word,
337                                                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
345 bool CommandObjectProxy::LoadSubCommand(
346     llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_sp) {
347   CommandObject *proxy_command = GetProxyCommandObject();
348   if (proxy_command)
349     return proxy_command->LoadSubCommand(cmd_name, command_sp);
350   return false;
351 }
352
353 bool CommandObjectProxy::WantsRawCommandString() {
354   CommandObject *proxy_command = GetProxyCommandObject();
355   if (proxy_command)
356     return proxy_command->WantsRawCommandString();
357   return false;
358 }
359
360 bool CommandObjectProxy::WantsCompletion() {
361   CommandObject *proxy_command = GetProxyCommandObject();
362   if (proxy_command)
363     return proxy_command->WantsCompletion();
364   return false;
365 }
366
367 Options *CommandObjectProxy::GetOptions() {
368   CommandObject *proxy_command = GetProxyCommandObject();
369   if (proxy_command)
370     return proxy_command->GetOptions();
371   return nullptr;
372 }
373
374 int CommandObjectProxy::HandleCompletion(Args &input, int &cursor_index,
375                                          int &cursor_char_position,
376                                          int match_start_point,
377                                          int max_return_elements,
378                                          bool &word_complete,
379                                          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;
387 }
388
389 int 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;
400 }
401
402 const 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;
408 }
409
410 bool 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;
418 }