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 const char *arg0 = input.GetArgumentAtIndex(0); 239 if (cursor_index == 0) 240 { 241 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, 242 arg0, 243 matches); 244 245 if (matches.GetSize() == 1 246 && matches.GetStringAtIndex(0) != NULL 247 && strcmp (arg0, matches.GetStringAtIndex(0)) == 0) 248 { 249 StringList temp_matches; 250 CommandObject *cmd_obj = GetSubcommandObject (arg0, 251 &temp_matches); 252 if (cmd_obj != NULL) 253 { 254 if (input.GetArgumentCount() == 1) 255 { 256 word_complete = true; 257 } 258 else 259 { 260 matches.DeleteStringAtIndex (0); 261 input.Shift(); 262 cursor_char_position = 0; 263 input.AppendArgument (""); 264 return cmd_obj->HandleCompletion (input, 265 cursor_index, 266 cursor_char_position, 267 match_start_point, 268 max_return_elements, 269 word_complete, 270 matches); 271 } 272 } 273 } 274 return matches.GetSize(); 275 } 276 else 277 { 278 CommandObject *sub_command_object = GetSubcommandObject (arg0, 279 &matches); 280 if (sub_command_object == NULL) 281 { 282 return matches.GetSize(); 283 } 284 else 285 { 286 // Remove the one match that we got from calling GetSubcommandObject. 287 matches.DeleteStringAtIndex(0); 288 input.Shift(); 289 cursor_index--; 290 return sub_command_object->HandleCompletion (input, 291 cursor_index, 292 cursor_char_position, 293 match_start_point, 294 max_return_elements, 295 word_complete, 296 matches); 297 } 298 299 } 300 } 301 302 const char * 303 CommandObjectMultiword::GetRepeatCommand (Args ¤t_command_args, uint32_t index) 304 { 305 index++; 306 if (current_command_args.GetArgumentCount() <= index) 307 return NULL; 308 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index)); 309 if (sub_command_object == NULL) 310 return NULL; 311 return sub_command_object->GetRepeatCommand(current_command_args, index); 312 } 313 314 315 void 316 CommandObjectMultiword::AproposAllSubCommands (const char *prefix, 317 const char *search_word, 318 StringList &commands_found, 319 StringList &commands_help) 320 { 321 CommandObject::CommandMap::const_iterator pos; 322 323 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) 324 { 325 const char * command_name = pos->first.c_str(); 326 CommandObject *sub_cmd_obj = pos->second.get(); 327 StreamString complete_command_name; 328 329 complete_command_name.Printf ("%s %s", prefix, command_name); 330 331 if (sub_cmd_obj->HelpTextContainsWord (search_word)) 332 { 333 commands_found.AppendString (complete_command_name.GetData()); 334 commands_help.AppendString (sub_cmd_obj->GetHelp()); 335 } 336 337 if (sub_cmd_obj->IsMultiwordObject()) 338 sub_cmd_obj->AproposAllSubCommands (complete_command_name.GetData(), 339 search_word, 340 commands_found, 341 commands_help); 342 } 343 } 344 345 346 347 CommandObjectProxy::CommandObjectProxy (CommandInterpreter &interpreter, 348 const char *name, 349 const char *help, 350 const char *syntax, 351 uint32_t flags) : 352 CommandObject (interpreter, name, help, syntax, flags) 353 { 354 } 355 356 CommandObjectProxy::~CommandObjectProxy () 357 { 358 } 359 360 const char * 361 CommandObjectProxy::GetHelpLong () 362 { 363 CommandObject *proxy_command = GetProxyCommandObject(); 364 if (proxy_command) 365 return proxy_command->GetHelpLong(); 366 return NULL; 367 } 368 369 bool 370 CommandObjectProxy::IsRemovable() const 371 { 372 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject(); 373 if (proxy_command) 374 return proxy_command->IsRemovable(); 375 return false; 376 } 377 378 bool 379 CommandObjectProxy::IsMultiwordObject () 380 { 381 CommandObject *proxy_command = GetProxyCommandObject(); 382 if (proxy_command) 383 return proxy_command->IsMultiwordObject(); 384 return false; 385 } 386 387 lldb::CommandObjectSP 388 CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches) 389 { 390 CommandObject *proxy_command = GetProxyCommandObject(); 391 if (proxy_command) 392 return proxy_command->GetSubcommandSP(sub_cmd, matches); 393 return lldb::CommandObjectSP(); 394 } 395 396 CommandObject * 397 CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches) 398 { 399 CommandObject *proxy_command = GetProxyCommandObject(); 400 if (proxy_command) 401 return proxy_command->GetSubcommandObject(sub_cmd, matches); 402 return NULL; 403 } 404 405 void 406 CommandObjectProxy::AproposAllSubCommands (const char *prefix, 407 const char *search_word, 408 StringList &commands_found, 409 StringList &commands_help) 410 { 411 CommandObject *proxy_command = GetProxyCommandObject(); 412 if (proxy_command) 413 return proxy_command->AproposAllSubCommands (prefix, 414 search_word, 415 commands_found, 416 commands_help); 417 } 418 419 bool 420 CommandObjectProxy::LoadSubCommand (const char *cmd_name, 421 const lldb::CommandObjectSP& command_sp) 422 { 423 CommandObject *proxy_command = GetProxyCommandObject(); 424 if (proxy_command) 425 return proxy_command->LoadSubCommand (cmd_name, command_sp); 426 return false; 427 } 428 429 bool 430 CommandObjectProxy::WantsRawCommandString() 431 { 432 CommandObject *proxy_command = GetProxyCommandObject(); 433 if (proxy_command) 434 return proxy_command->WantsRawCommandString(); 435 return false; 436 } 437 438 bool 439 CommandObjectProxy::WantsCompletion() 440 { 441 CommandObject *proxy_command = GetProxyCommandObject(); 442 if (proxy_command) 443 return proxy_command->WantsCompletion(); 444 return false; 445 } 446 447 448 Options * 449 CommandObjectProxy::GetOptions () 450 { 451 CommandObject *proxy_command = GetProxyCommandObject(); 452 if (proxy_command) 453 return proxy_command->GetOptions (); 454 return NULL; 455 } 456 457 458 int 459 CommandObjectProxy::HandleCompletion (Args &input, 460 int &cursor_index, 461 int &cursor_char_position, 462 int match_start_point, 463 int max_return_elements, 464 bool &word_complete, 465 StringList &matches) 466 { 467 CommandObject *proxy_command = GetProxyCommandObject(); 468 if (proxy_command) 469 return proxy_command->HandleCompletion (input, 470 cursor_index, 471 cursor_char_position, 472 match_start_point, 473 max_return_elements, 474 word_complete, 475 matches); 476 matches.Clear(); 477 return 0; 478 } 479 int 480 CommandObjectProxy::HandleArgumentCompletion (Args &input, 481 int &cursor_index, 482 int &cursor_char_position, 483 OptionElementVector &opt_element_vector, 484 int match_start_point, 485 int max_return_elements, 486 bool &word_complete, 487 StringList &matches) 488 { 489 CommandObject *proxy_command = GetProxyCommandObject(); 490 if (proxy_command) 491 return proxy_command->HandleArgumentCompletion (input, 492 cursor_index, 493 cursor_char_position, 494 opt_element_vector, 495 match_start_point, 496 max_return_elements, 497 word_complete, 498 matches); 499 matches.Clear(); 500 return 0; 501 } 502 503 const char * 504 CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args, 505 uint32_t index) 506 { 507 CommandObject *proxy_command = GetProxyCommandObject(); 508 if (proxy_command) 509 return proxy_command->GetRepeatCommand (current_command_args, index); 510 return NULL; 511 } 512 513 bool 514 CommandObjectProxy::Execute (const char *args_string, 515 CommandReturnObject &result) 516 { 517 CommandObject *proxy_command = GetProxyCommandObject(); 518 if (proxy_command) 519 return proxy_command->Execute (args_string, result); 520 result.AppendError ("command is not implemented"); 521 result.SetStatus (eReturnStatusFailed); 522 return false; 523 } 524 525 526