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 m_can_be_removed(false) 37 { 38 } 39 40 CommandObjectMultiword::~CommandObjectMultiword () 41 { 42 } 43 44 CommandObjectSP 45 CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches) 46 { 47 CommandObjectSP return_cmd_sp; 48 CommandObject::CommandMap::iterator pos; 49 50 if (!m_subcommand_dict.empty()) 51 { 52 pos = m_subcommand_dict.find (sub_cmd); 53 if (pos != m_subcommand_dict.end()) { 54 // An exact match; append the sub_cmd to the 'matches' string list. 55 if (matches) 56 matches->AppendString(sub_cmd); 57 return_cmd_sp = pos->second; 58 } 59 else 60 { 61 62 StringList local_matches; 63 if (matches == NULL) 64 matches = &local_matches; 65 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches); 66 67 if (num_matches == 1) 68 { 69 // Cleaner, but slightly less efficient would be to call back into this function, since I now 70 // know I have an exact match... 71 72 sub_cmd = matches->GetStringAtIndex(0); 73 pos = m_subcommand_dict.find(sub_cmd); 74 if (pos != m_subcommand_dict.end()) 75 return_cmd_sp = pos->second; 76 } 77 } 78 } 79 return return_cmd_sp; 80 } 81 82 CommandObject * 83 CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches) 84 { 85 return GetSubcommandSP(sub_cmd, matches).get(); 86 } 87 88 bool 89 CommandObjectMultiword::LoadSubCommand 90 ( 91 const char *name, 92 const CommandObjectSP& cmd_obj 93 ) 94 { 95 CommandMap::iterator pos; 96 bool success = true; 97 98 pos = m_subcommand_dict.find(name); 99 if (pos == m_subcommand_dict.end()) 100 { 101 m_subcommand_dict[name] = cmd_obj; 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 this->CommandObject::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 this->CommandObject::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 const size_t 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 (size_t 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()); 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 (Stream &output_stream) 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 output_stream.PutCString ("The following subcommands are supported:\n\n"); 188 189 CommandMap::iterator pos; 190 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict); 191 192 if (max_len) 193 max_len += 4; // Indent the output by 4 spaces. 194 195 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos) 196 { 197 std::string indented_command (" "); 198 indented_command.append (pos->first); 199 if (pos->second->WantsRawCommandString ()) 200 { 201 std::string help_text (pos->second->GetHelp()); 202 help_text.append (" This command takes 'raw' input (no need to quote stuff)."); 203 m_interpreter.OutputFormattedHelpText (output_stream, 204 indented_command.c_str(), 205 "--", 206 help_text.c_str(), 207 max_len); 208 } 209 else 210 m_interpreter.OutputFormattedHelpText (output_stream, 211 indented_command.c_str(), 212 "--", 213 pos->second->GetHelp(), 214 max_len); 215 } 216 217 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n"); 218 } 219 220 int 221 CommandObjectMultiword::HandleCompletion 222 ( 223 Args &input, 224 int &cursor_index, 225 int &cursor_char_position, 226 int match_start_point, 227 int max_return_elements, 228 bool &word_complete, 229 StringList &matches 230 ) 231 { 232 // Any of the command matches will provide a complete word, otherwise the individual 233 // completers will override this. 234 word_complete = true; 235 236 const char *arg0 = input.GetArgumentAtIndex(0); 237 if (cursor_index == 0) 238 { 239 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, 240 arg0, 241 matches); 242 243 if (matches.GetSize() == 1 244 && matches.GetStringAtIndex(0) != NULL 245 && strcmp (arg0, matches.GetStringAtIndex(0)) == 0) 246 { 247 StringList temp_matches; 248 CommandObject *cmd_obj = GetSubcommandObject (arg0, 249 &temp_matches); 250 if (cmd_obj != NULL) 251 { 252 if (input.GetArgumentCount() == 1) 253 { 254 word_complete = true; 255 } 256 else 257 { 258 matches.DeleteStringAtIndex (0); 259 input.Shift(); 260 cursor_char_position = 0; 261 input.AppendArgument (""); 262 return cmd_obj->HandleCompletion (input, 263 cursor_index, 264 cursor_char_position, 265 match_start_point, 266 max_return_elements, 267 word_complete, 268 matches); 269 } 270 } 271 } 272 return matches.GetSize(); 273 } 274 else 275 { 276 CommandObject *sub_command_object = GetSubcommandObject (arg0, 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 bool 368 CommandObjectProxy::IsRemovable() const 369 { 370 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject(); 371 if (proxy_command) 372 return proxy_command->IsRemovable(); 373 return false; 374 } 375 376 bool 377 CommandObjectProxy::IsMultiwordObject () 378 { 379 CommandObject *proxy_command = GetProxyCommandObject(); 380 if (proxy_command) 381 return proxy_command->IsMultiwordObject(); 382 return false; 383 } 384 385 lldb::CommandObjectSP 386 CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches) 387 { 388 CommandObject *proxy_command = GetProxyCommandObject(); 389 if (proxy_command) 390 return proxy_command->GetSubcommandSP(sub_cmd, matches); 391 return lldb::CommandObjectSP(); 392 } 393 394 CommandObject * 395 CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches) 396 { 397 CommandObject *proxy_command = GetProxyCommandObject(); 398 if (proxy_command) 399 return proxy_command->GetSubcommandObject(sub_cmd, matches); 400 return NULL; 401 } 402 403 void 404 CommandObjectProxy::AproposAllSubCommands (const char *prefix, 405 const char *search_word, 406 StringList &commands_found, 407 StringList &commands_help) 408 { 409 CommandObject *proxy_command = GetProxyCommandObject(); 410 if (proxy_command) 411 return proxy_command->AproposAllSubCommands (prefix, 412 search_word, 413 commands_found, 414 commands_help); 415 } 416 417 bool 418 CommandObjectProxy::LoadSubCommand (const char *cmd_name, 419 const lldb::CommandObjectSP& command_sp) 420 { 421 CommandObject *proxy_command = GetProxyCommandObject(); 422 if (proxy_command) 423 return proxy_command->LoadSubCommand (cmd_name, command_sp); 424 return false; 425 } 426 427 bool 428 CommandObjectProxy::WantsRawCommandString() 429 { 430 CommandObject *proxy_command = GetProxyCommandObject(); 431 if (proxy_command) 432 return proxy_command->WantsRawCommandString(); 433 return false; 434 } 435 436 bool 437 CommandObjectProxy::WantsCompletion() 438 { 439 CommandObject *proxy_command = GetProxyCommandObject(); 440 if (proxy_command) 441 return proxy_command->WantsCompletion(); 442 return false; 443 } 444 445 446 Options * 447 CommandObjectProxy::GetOptions () 448 { 449 CommandObject *proxy_command = GetProxyCommandObject(); 450 if (proxy_command) 451 return proxy_command->GetOptions (); 452 return NULL; 453 } 454 455 456 int 457 CommandObjectProxy::HandleCompletion (Args &input, 458 int &cursor_index, 459 int &cursor_char_position, 460 int match_start_point, 461 int max_return_elements, 462 bool &word_complete, 463 StringList &matches) 464 { 465 CommandObject *proxy_command = GetProxyCommandObject(); 466 if (proxy_command) 467 return proxy_command->HandleCompletion (input, 468 cursor_index, 469 cursor_char_position, 470 match_start_point, 471 max_return_elements, 472 word_complete, 473 matches); 474 matches.Clear(); 475 return 0; 476 } 477 int 478 CommandObjectProxy::HandleArgumentCompletion (Args &input, 479 int &cursor_index, 480 int &cursor_char_position, 481 OptionElementVector &opt_element_vector, 482 int match_start_point, 483 int max_return_elements, 484 bool &word_complete, 485 StringList &matches) 486 { 487 CommandObject *proxy_command = GetProxyCommandObject(); 488 if (proxy_command) 489 return proxy_command->HandleArgumentCompletion (input, 490 cursor_index, 491 cursor_char_position, 492 opt_element_vector, 493 match_start_point, 494 max_return_elements, 495 word_complete, 496 matches); 497 matches.Clear(); 498 return 0; 499 } 500 501 const char * 502 CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args, 503 uint32_t index) 504 { 505 CommandObject *proxy_command = GetProxyCommandObject(); 506 if (proxy_command) 507 return proxy_command->GetRepeatCommand (current_command_args, index); 508 return NULL; 509 } 510 511 bool 512 CommandObjectProxy::Execute (const char *args_string, 513 CommandReturnObject &result) 514 { 515 CommandObject *proxy_command = GetProxyCommandObject(); 516 if (proxy_command) 517 return proxy_command->Execute (args_string, result); 518 result.AppendError ("command is not implemented"); 519 result.SetStatus (eReturnStatusFailed); 520 return false; 521 } 522 523 524