CommandObjectMultiword.cpp revision 004ccb3fcca8c8004cb6cdb1f383b02e792a0452
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/lldb-python.h"
11
12#include "lldb/Interpreter/CommandObjectMultiword.h"
13// C Includes
14// C++ Includes
15// Other libraries and framework includes
16// Project includes
17#include "lldb/Core/Debugger.h"
18#include "lldb/Interpreter/CommandInterpreter.h"
19#include "lldb/Interpreter/Options.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
25//-------------------------------------------------------------------------
26// CommandObjectMultiword
27//-------------------------------------------------------------------------
28
29CommandObjectMultiword::CommandObjectMultiword
30(
31    CommandInterpreter &interpreter,
32    const char *name,
33    const char *help,
34    const char *syntax,
35    uint32_t flags
36) :
37    CommandObject (interpreter, name, help, syntax, flags),
38    m_can_be_removed(false)
39{
40}
41
42CommandObjectMultiword::~CommandObjectMultiword ()
43{
44}
45
46CommandObjectSP
47CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
48{
49    CommandObjectSP return_cmd_sp;
50    CommandObject::CommandMap::iterator pos;
51
52    if (!m_subcommand_dict.empty())
53    {
54        pos = m_subcommand_dict.find (sub_cmd);
55        if (pos != m_subcommand_dict.end()) {
56            // An exact match; append the sub_cmd to the 'matches' string list.
57            if (matches)
58                matches->AppendString(sub_cmd);
59            return_cmd_sp = pos->second;
60        }
61        else
62        {
63
64            StringList local_matches;
65            if (matches == NULL)
66                matches = &local_matches;
67            int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
68
69            if (num_matches == 1)
70            {
71                // Cleaner, but slightly less efficient would be to call back into this function, since I now
72                // know I have an exact match...
73
74                sub_cmd = matches->GetStringAtIndex(0);
75                pos = m_subcommand_dict.find(sub_cmd);
76                if (pos != m_subcommand_dict.end())
77                    return_cmd_sp = pos->second;
78            }
79        }
80    }
81    return return_cmd_sp;
82}
83
84CommandObject *
85CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
86{
87    return GetSubcommandSP(sub_cmd, matches).get();
88}
89
90bool
91CommandObjectMultiword::LoadSubCommand
92(
93    const char *name,
94    const CommandObjectSP& cmd_obj
95)
96{
97    CommandMap::iterator pos;
98    bool success = true;
99
100    pos = m_subcommand_dict.find(name);
101    if (pos == m_subcommand_dict.end())
102    {
103        m_subcommand_dict[name] = cmd_obj;
104        m_interpreter.CrossRegisterCommand (name, GetCommandName());
105    }
106    else
107        success = false;
108
109    return success;
110}
111
112bool
113CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
114{
115    Args args (args_string);
116    const size_t argc = args.GetArgumentCount();
117    if (argc == 0)
118    {
119        GenerateHelpText (result);
120    }
121    else
122    {
123        const char *sub_command = args.GetArgumentAtIndex (0);
124
125        if (sub_command)
126        {
127            if (::strcasecmp (sub_command, "help") == 0)
128            {
129                GenerateHelpText (result);
130            }
131            else if (!m_subcommand_dict.empty())
132            {
133                StringList matches;
134                CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
135                if (sub_cmd_obj != NULL)
136                {
137                    // Now call CommandObject::Execute to process and options in 'rest_of_line'.  From there
138                    // the command-specific version of Execute will be called, with the processed arguments.
139
140                    args.Shift();
141
142                    sub_cmd_obj->Execute (args_string, result);
143                }
144                else
145                {
146                    std::string error_msg;
147                    const size_t num_subcmd_matches = matches.GetSize();
148                    if (num_subcmd_matches > 0)
149                        error_msg.assign ("ambiguous command ");
150                    else
151                        error_msg.assign ("invalid command ");
152
153                    error_msg.append ("'");
154                    error_msg.append (GetCommandName());
155                    error_msg.append (" ");
156                    error_msg.append (sub_command);
157                    error_msg.append ("'");
158
159                    if (num_subcmd_matches > 0)
160                    {
161                        error_msg.append (" Possible completions:");
162                        for (size_t i = 0; i < num_subcmd_matches; i++)
163                        {
164                            error_msg.append ("\n\t");
165                            error_msg.append (matches.GetStringAtIndex (i));
166                        }
167                    }
168                    error_msg.append ("\n");
169                    result.AppendRawError (error_msg.c_str());
170                    result.SetStatus (eReturnStatusFailed);
171                }
172            }
173            else
174            {
175                result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
176                result.SetStatus (eReturnStatusFailed);
177            }
178        }
179    }
180
181    return result.Succeeded();
182}
183
184void
185CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
186{
187    // First time through here, generate the help text for the object and
188    // push it to the return result object as well
189
190    Stream &output_stream = result.GetOutputStream();
191    output_stream.PutCString ("The following subcommands are supported:\n\n");
192
193    CommandMap::iterator pos;
194    uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
195
196    if (max_len)
197        max_len += 4; // Indent the output by 4 spaces.
198
199    for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
200    {
201        std::string indented_command ("    ");
202        indented_command.append (pos->first);
203        if (pos->second->WantsRawCommandString ())
204        {
205            std::string help_text (pos->second->GetHelp());
206            help_text.append ("  This command takes 'raw' input (no need to quote stuff).");
207            m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
208                                                   indented_command.c_str(),
209                                                   "--",
210                                                   help_text.c_str(),
211                                                   max_len);
212        }
213        else
214            m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
215                                                   indented_command.c_str(),
216                                                   "--",
217                                                   pos->second->GetHelp(),
218                                                   max_len);
219    }
220
221    output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
222
223    result.SetStatus (eReturnStatusSuccessFinishNoResult);
224}
225
226int
227CommandObjectMultiword::HandleCompletion
228(
229    Args &input,
230    int &cursor_index,
231    int &cursor_char_position,
232    int match_start_point,
233    int max_return_elements,
234    bool &word_complete,
235    StringList &matches
236)
237{
238    // Any of the command matches will provide a complete word, otherwise the individual
239    // completers will override this.
240    word_complete = true;
241
242    if (cursor_index == 0)
243    {
244        CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
245                                                      input.GetArgumentAtIndex(0),
246                                                      matches);
247
248        if (matches.GetSize() == 1
249            && matches.GetStringAtIndex(0) != NULL
250            && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
251        {
252            StringList temp_matches;
253            CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
254                                                          &temp_matches);
255            if (cmd_obj != NULL)
256            {
257                matches.DeleteStringAtIndex (0);
258                input.Shift();
259                cursor_char_position = 0;
260                input.AppendArgument ("");
261                return cmd_obj->HandleCompletion (input,
262                                                  cursor_index,
263                                                  cursor_char_position,
264                                                  match_start_point,
265                                                  max_return_elements,
266                                                  word_complete,
267                                                  matches);
268            }
269            else
270                return matches.GetSize();
271        }
272        else
273            return matches.GetSize();
274    }
275    else
276    {
277        CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
278                                                                 &matches);
279        if (sub_command_object == NULL)
280        {
281            return matches.GetSize();
282        }
283        else
284        {
285            // Remove the one match that we got from calling GetSubcommandObject.
286            matches.DeleteStringAtIndex(0);
287            input.Shift();
288            cursor_index--;
289            return sub_command_object->HandleCompletion (input,
290                                                         cursor_index,
291                                                         cursor_char_position,
292                                                         match_start_point,
293                                                         max_return_elements,
294                                                         word_complete,
295                                                         matches);
296        }
297
298    }
299}
300
301const char *
302CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
303{
304    index++;
305    if (current_command_args.GetArgumentCount() <= index)
306        return NULL;
307    CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
308    if (sub_command_object == NULL)
309        return NULL;
310    return sub_command_object->GetRepeatCommand(current_command_args, index);
311}
312
313
314void
315CommandObjectMultiword::AproposAllSubCommands (const char *prefix,
316                                               const char *search_word,
317                                               StringList &commands_found,
318                                               StringList &commands_help)
319{
320    CommandObject::CommandMap::const_iterator pos;
321
322    for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
323    {
324        const char * command_name = pos->first.c_str();
325        CommandObject *sub_cmd_obj = pos->second.get();
326        StreamString complete_command_name;
327
328        complete_command_name.Printf ("%s %s", prefix, command_name);
329
330        if (sub_cmd_obj->HelpTextContainsWord (search_word))
331        {
332            commands_found.AppendString (complete_command_name.GetData());
333            commands_help.AppendString (sub_cmd_obj->GetHelp());
334        }
335
336        if (sub_cmd_obj->IsMultiwordObject())
337            sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(),
338                                                search_word,
339                                                commands_found,
340                                                commands_help);
341    }
342}
343
344
345
346CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter,
347                                        const char *name,
348                                        const char *help,
349                                        const char *syntax,
350                                        uint32_t flags) :
351    CommandObject (interpreter, name, help, syntax, flags)
352{
353}
354
355CommandObjectProxy::~CommandObjectProxy ()
356{
357}
358
359const char *
360CommandObjectProxy::GetHelpLong ()
361{
362    CommandObject *proxy_command = GetProxyCommandObject();
363    if (proxy_command)
364        return proxy_command->GetHelpLong();
365    return NULL;
366}
367
368void
369CommandObjectProxy::AddObject (const char *obj_name)
370{
371    CommandObject *proxy_command = GetProxyCommandObject();
372    if (proxy_command)
373        return proxy_command->AddObject (obj_name);
374}
375
376bool
377CommandObjectProxy::IsCrossRefObject ()
378{
379    CommandObject *proxy_command = GetProxyCommandObject();
380    if (proxy_command)
381        return proxy_command->IsCrossRefObject();
382    return false;
383}
384
385bool
386CommandObjectProxy::IsRemovable() const
387{
388    const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject();
389    if (proxy_command)
390        return proxy_command->IsRemovable();
391    return false;
392}
393
394bool
395CommandObjectProxy::IsMultiwordObject ()
396{
397    CommandObject *proxy_command = GetProxyCommandObject();
398    if (proxy_command)
399        return proxy_command->IsMultiwordObject();
400    return false;
401}
402
403lldb::CommandObjectSP
404CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches)
405{
406    CommandObject *proxy_command = GetProxyCommandObject();
407    if (proxy_command)
408        return proxy_command->GetSubcommandSP(sub_cmd, matches);
409    return lldb::CommandObjectSP();
410}
411
412CommandObject *
413CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches)
414{
415    CommandObject *proxy_command = GetProxyCommandObject();
416    if (proxy_command)
417        return proxy_command->GetSubcommandObject(sub_cmd, matches);
418    return NULL;
419}
420
421void
422CommandObjectProxy::AproposAllSubCommands (const char *prefix,
423                                           const char *search_word,
424                                           StringList &commands_found,
425                                           StringList &commands_help)
426{
427    CommandObject *proxy_command = GetProxyCommandObject();
428    if (proxy_command)
429        return proxy_command->AproposAllSubCommands (prefix,
430                                                     search_word,
431                                                     commands_found,
432                                                     commands_help);
433}
434
435bool
436CommandObjectProxy::LoadSubCommand (const char *cmd_name,
437                                    const lldb::CommandObjectSP& command_sp)
438{
439    CommandObject *proxy_command = GetProxyCommandObject();
440    if (proxy_command)
441        return proxy_command->LoadSubCommand (cmd_name, command_sp);
442    return false;
443}
444
445bool
446CommandObjectProxy::WantsRawCommandString()
447{
448    CommandObject *proxy_command = GetProxyCommandObject();
449    if (proxy_command)
450        return proxy_command->WantsRawCommandString();
451    return false;
452}
453
454bool
455CommandObjectProxy::WantsCompletion()
456{
457    CommandObject *proxy_command = GetProxyCommandObject();
458    if (proxy_command)
459        return proxy_command->WantsCompletion();
460    return false;
461}
462
463
464Options *
465CommandObjectProxy::GetOptions ()
466{
467    CommandObject *proxy_command = GetProxyCommandObject();
468    if (proxy_command)
469        return proxy_command->GetOptions ();
470    return NULL;
471}
472
473
474int
475CommandObjectProxy::HandleCompletion (Args &input,
476                                      int &cursor_index,
477                                      int &cursor_char_position,
478                                      int match_start_point,
479                                      int max_return_elements,
480                                      bool &word_complete,
481                                      StringList &matches)
482{
483    CommandObject *proxy_command = GetProxyCommandObject();
484    if (proxy_command)
485        return proxy_command->HandleCompletion (input,
486                                                cursor_index,
487                                                cursor_char_position,
488                                                match_start_point,
489                                                max_return_elements,
490                                                word_complete,
491                                                matches);
492    matches.Clear();
493    return 0;
494}
495int
496CommandObjectProxy::HandleArgumentCompletion (Args &input,
497                                              int &cursor_index,
498                                              int &cursor_char_position,
499                                              OptionElementVector &opt_element_vector,
500                                              int match_start_point,
501                                              int max_return_elements,
502                                              bool &word_complete,
503                                              StringList &matches)
504{
505    CommandObject *proxy_command = GetProxyCommandObject();
506    if (proxy_command)
507        return proxy_command->HandleArgumentCompletion (input,
508                                                        cursor_index,
509                                                        cursor_char_position,
510                                                        opt_element_vector,
511                                                        match_start_point,
512                                                        max_return_elements,
513                                                        word_complete,
514                                                        matches);
515    matches.Clear();
516    return 0;
517}
518
519const char *
520CommandObjectProxy::GetRepeatCommand (Args &current_command_args,
521                                      uint32_t index)
522{
523    CommandObject *proxy_command = GetProxyCommandObject();
524    if (proxy_command)
525        return proxy_command->GetRepeatCommand (current_command_args, index);
526    return NULL;
527}
528
529bool
530CommandObjectProxy::Execute (const char *args_string,
531                             CommandReturnObject &result)
532{
533    CommandObject *proxy_command = GetProxyCommandObject();
534    if (proxy_command)
535        return proxy_command->Execute (args_string, result);
536    result.AppendError ("command is not implemented");
537    result.SetStatus (eReturnStatusFailed);
538    return false;
539}
540
541
542