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 { 39 } 40 41 CommandObjectMultiword::~CommandObjectMultiword () 42 { 43 } 44 45 CommandObjectSP 46 CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches) 47 { 48 CommandObjectSP return_cmd_sp; 49 CommandObject::CommandMap::iterator pos; 50 51 if (!m_subcommand_dict.empty()) 52 { 53 pos = m_subcommand_dict.find (sub_cmd); 54 if (pos != m_subcommand_dict.end()) { 55 // An exact match; append the sub_cmd to the 'matches' string list. 56 if (matches) 57 matches->AppendString(sub_cmd); 58 return_cmd_sp = pos->second; 59 } 60 else 61 { 62 63 StringList local_matches; 64 if (matches == NULL) 65 matches = &local_matches; 66 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches); 67 68 if (num_matches == 1) 69 { 70 // Cleaner, but slightly less efficient would be to call back into this function, since I now 71 // know I have an exact match... 72 73 sub_cmd = matches->GetStringAtIndex(0); 74 pos = m_subcommand_dict.find(sub_cmd); 75 if (pos != m_subcommand_dict.end()) 76 return_cmd_sp = pos->second; 77 } 78 } 79 } 80 return return_cmd_sp; 81 } 82 83 CommandObject * 84 CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches) 85 { 86 return GetSubcommandSP(sub_cmd, matches).get(); 87 } 88 89 bool 90 CommandObjectMultiword::LoadSubCommand 91 ( 92 const char *name, 93 const CommandObjectSP& cmd_obj 94 ) 95 { 96 CommandMap::iterator pos; 97 bool success = true; 98 99 pos = m_subcommand_dict.find(name); 100 if (pos == m_subcommand_dict.end()) 101 { 102 m_subcommand_dict[name] = cmd_obj; 103 m_interpreter.CrossRegisterCommand (name, GetCommandName()); 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 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 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 (CommandReturnObject &result) 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 Stream &output_stream = result.GetOutputStream(); 190 output_stream.PutCString ("The following subcommands are supported:\n\n"); 191 192 CommandMap::iterator pos; 193 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict); 194 195 if (max_len) 196 max_len += 4; // Indent the output by 4 spaces. 197 198 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) 199 { 200 std::string indented_command (" "); 201 indented_command.append (pos->first); 202 if (pos->second->WantsRawCommandString ()) 203 { 204 std::string help_text (pos->second->GetHelp()); 205 help_text.append (" This command takes 'raw' input (no need to quote stuff)."); 206 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(), 207 indented_command.c_str(), 208 "--", 209 help_text.c_str(), 210 max_len); 211 } 212 else 213 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(), 214 indented_command.c_str(), 215 "--", 216 pos->second->GetHelp(), 217 max_len); 218 } 219 220 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n"); 221 222 result.SetStatus (eReturnStatusSuccessFinishNoResult); 223 } 224 225 int 226 CommandObjectMultiword::HandleCompletion 227 ( 228 Args &input, 229 int &cursor_index, 230 int &cursor_char_position, 231 int match_start_point, 232 int max_return_elements, 233 bool &word_complete, 234 StringList &matches 235 ) 236 { 237 // Any of the command matches will provide a complete word, otherwise the individual 238 // completers will override this. 239 word_complete = true; 240 241 if (cursor_index == 0) 242 { 243 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, 244 input.GetArgumentAtIndex(0), 245 matches); 246 247 if (matches.GetSize() == 1 248 && matches.GetStringAtIndex(0) != NULL 249 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 250 { 251 StringList temp_matches; 252 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0), 253 &temp_matches); 254 if (cmd_obj != NULL) 255 { 256 matches.DeleteStringAtIndex (0); 257 input.Shift(); 258 cursor_char_position = 0; 259 input.AppendArgument (""); 260 return cmd_obj->HandleCompletion (input, 261 cursor_index, 262 cursor_char_position, 263 match_start_point, 264 max_return_elements, 265 word_complete, 266 matches); 267 } 268 else 269 return matches.GetSize(); 270 } 271 else 272 return matches.GetSize(); 273 } 274 else 275 { 276 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0), 277 &matches); 278 if (sub_command_object == NULL) 279 { 280 return matches.GetSize(); 281 } 282 else 283 { 284 // Remove the one match that we got from calling GetSubcommandObject. 285 matches.DeleteStringAtIndex(0); 286 input.Shift(); 287 cursor_index--; 288 return sub_command_object->HandleCompletion (input, 289 cursor_index, 290 cursor_char_position, 291 match_start_point, 292 max_return_elements, 293 word_complete, 294 matches); 295 } 296 297 } 298 } 299 300 const char * 301 CommandObjectMultiword::GetRepeatCommand (Args ¤t_command_args, uint32_t index) 302 { 303 index++; 304 if (current_command_args.GetArgumentCount() <= index) 305 return NULL; 306 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index)); 307 if (sub_command_object == NULL) 308 return NULL; 309 return sub_command_object->GetRepeatCommand(current_command_args, index); 310 } 311 312 313 void 314 CommandObjectMultiword::AproposAllSubCommands (const char *prefix, 315 const char *search_word, 316 StringList &commands_found, 317 StringList &commands_help) 318 { 319 CommandObject::CommandMap::const_iterator pos; 320 321 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) 322 { 323 const char * command_name = pos->first.c_str(); 324 CommandObject *sub_cmd_obj = pos->second.get(); 325 StreamString complete_command_name; 326 327 complete_command_name.Printf ("%s %s", prefix, command_name); 328 329 if (sub_cmd_obj->HelpTextContainsWord (search_word)) 330 { 331 commands_found.AppendString (complete_command_name.GetData()); 332 commands_help.AppendString (sub_cmd_obj->GetHelp()); 333 } 334 335 if (sub_cmd_obj->IsMultiwordObject()) 336 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(), 337 search_word, 338 commands_found, 339 commands_help); 340 } 341 } 342 343 344 345 CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter, 346 const char *name, 347 const char *help, 348 const char *syntax, 349 uint32_t flags) : 350 CommandObject (interpreter, name, help, syntax, flags) 351 { 352 } 353 354 CommandObjectProxy::~CommandObjectProxy () 355 { 356 } 357 358 const char * 359 CommandObjectProxy::GetHelpLong () 360 { 361 CommandObject *proxy_command = GetProxyCommandObject(); 362 if (proxy_command) 363 return proxy_command->GetHelpLong(); 364 return NULL; 365 } 366 367 void 368 CommandObjectProxy::AddObject (const char *obj_name) 369 { 370 CommandObject *proxy_command = GetProxyCommandObject(); 371 if (proxy_command) 372 return proxy_command->AddObject (obj_name); 373 } 374 375 bool 376 CommandObjectProxy::IsCrossRefObject () 377 { 378 CommandObject *proxy_command = GetProxyCommandObject(); 379 if (proxy_command) 380 return proxy_command->IsCrossRefObject(); 381 return false; 382 } 383 384 bool 385 CommandObjectProxy::IsRemovable() const 386 { 387 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject(); 388 if (proxy_command) 389 return proxy_command->IsRemovable(); 390 return false; 391 } 392 393 bool 394 CommandObjectProxy::IsMultiwordObject () 395 { 396 CommandObject *proxy_command = GetProxyCommandObject(); 397 if (proxy_command) 398 return proxy_command->IsMultiwordObject(); 399 return false; 400 } 401 402 lldb::CommandObjectSP 403 CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches) 404 { 405 CommandObject *proxy_command = GetProxyCommandObject(); 406 if (proxy_command) 407 return proxy_command->GetSubcommandSP(sub_cmd, matches); 408 return lldb::CommandObjectSP(); 409 } 410 411 CommandObject * 412 CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches) 413 { 414 CommandObject *proxy_command = GetProxyCommandObject(); 415 if (proxy_command) 416 return proxy_command->GetSubcommandObject(sub_cmd, matches); 417 return NULL; 418 } 419 420 void 421 CommandObjectProxy::AproposAllSubCommands (const char *prefix, 422 const char *search_word, 423 StringList &commands_found, 424 StringList &commands_help) 425 { 426 CommandObject *proxy_command = GetProxyCommandObject(); 427 if (proxy_command) 428 return proxy_command->AproposAllSubCommands (prefix, 429 search_word, 430 commands_found, 431 commands_help); 432 } 433 434 bool 435 CommandObjectProxy::LoadSubCommand (const char *cmd_name, 436 const lldb::CommandObjectSP& command_sp) 437 { 438 CommandObject *proxy_command = GetProxyCommandObject(); 439 if (proxy_command) 440 return proxy_command->LoadSubCommand (cmd_name, command_sp); 441 return false; 442 } 443 444 bool 445 CommandObjectProxy::WantsRawCommandString() 446 { 447 CommandObject *proxy_command = GetProxyCommandObject(); 448 if (proxy_command) 449 return proxy_command->WantsRawCommandString(); 450 return false; 451 } 452 453 bool 454 CommandObjectProxy::WantsCompletion() 455 { 456 CommandObject *proxy_command = GetProxyCommandObject(); 457 if (proxy_command) 458 return proxy_command->WantsCompletion(); 459 return false; 460 } 461 462 463 Options * 464 CommandObjectProxy::GetOptions () 465 { 466 CommandObject *proxy_command = GetProxyCommandObject(); 467 if (proxy_command) 468 return proxy_command->GetOptions (); 469 return NULL; 470 } 471 472 473 int 474 CommandObjectProxy::HandleCompletion (Args &input, 475 int &cursor_index, 476 int &cursor_char_position, 477 int match_start_point, 478 int max_return_elements, 479 bool &word_complete, 480 StringList &matches) 481 { 482 CommandObject *proxy_command = GetProxyCommandObject(); 483 if (proxy_command) 484 return proxy_command->HandleCompletion (input, 485 cursor_index, 486 cursor_char_position, 487 match_start_point, 488 max_return_elements, 489 word_complete, 490 matches); 491 matches.Clear(); 492 return 0; 493 } 494 int 495 CommandObjectProxy::HandleArgumentCompletion (Args &input, 496 int &cursor_index, 497 int &cursor_char_position, 498 OptionElementVector &opt_element_vector, 499 int match_start_point, 500 int max_return_elements, 501 bool &word_complete, 502 StringList &matches) 503 { 504 CommandObject *proxy_command = GetProxyCommandObject(); 505 if (proxy_command) 506 return proxy_command->HandleArgumentCompletion (input, 507 cursor_index, 508 cursor_char_position, 509 opt_element_vector, 510 match_start_point, 511 max_return_elements, 512 word_complete, 513 matches); 514 matches.Clear(); 515 return 0; 516 } 517 518 const char * 519 CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args, 520 uint32_t index) 521 { 522 CommandObject *proxy_command = GetProxyCommandObject(); 523 if (proxy_command) 524 return proxy_command->GetRepeatCommand (current_command_args, index); 525 return NULL; 526 } 527 528 bool 529 CommandObjectProxy::Execute (const char *args_string, 530 CommandReturnObject &result) 531 { 532 CommandObject *proxy_command = GetProxyCommandObject(); 533 if (proxy_command) 534 return proxy_command->Execute (args_string, result); 535 result.AppendError ("command is not implemented"); 536 result.SetStatus (eReturnStatusFailed); 537 return false; 538 } 539 540 541