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