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