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 ¤t_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 ¤t_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