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 } 105 else 106 success = false; 107 108 return success; 109} 110 111bool 112CommandObjectMultiword::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 183void 184CommandObjectMultiword::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 222int 223CommandObjectMultiword::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 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 (arg0, 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 298const char * 299CommandObjectMultiword::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 311void 312CommandObjectMultiword::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 343CommandObjectProxy::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 352CommandObjectProxy::~CommandObjectProxy () 353{ 354} 355 356const char * 357CommandObjectProxy::GetHelpLong () 358{ 359 CommandObject *proxy_command = GetProxyCommandObject(); 360 if (proxy_command) 361 return proxy_command->GetHelpLong(); 362 return NULL; 363} 364 365bool 366CommandObjectProxy::IsRemovable() const 367{ 368 const CommandObject *proxy_command = const_cast<CommandObjectProxy *>(this)->GetProxyCommandObject(); 369 if (proxy_command) 370 return proxy_command->IsRemovable(); 371 return false; 372} 373 374bool 375CommandObjectProxy::IsMultiwordObject () 376{ 377 CommandObject *proxy_command = GetProxyCommandObject(); 378 if (proxy_command) 379 return proxy_command->IsMultiwordObject(); 380 return false; 381} 382 383lldb::CommandObjectSP 384CommandObjectProxy::GetSubcommandSP (const char *sub_cmd, StringList *matches) 385{ 386 CommandObject *proxy_command = GetProxyCommandObject(); 387 if (proxy_command) 388 return proxy_command->GetSubcommandSP(sub_cmd, matches); 389 return lldb::CommandObjectSP(); 390} 391 392CommandObject * 393CommandObjectProxy::GetSubcommandObject (const char *sub_cmd, StringList *matches) 394{ 395 CommandObject *proxy_command = GetProxyCommandObject(); 396 if (proxy_command) 397 return proxy_command->GetSubcommandObject(sub_cmd, matches); 398 return NULL; 399} 400 401void 402CommandObjectProxy::AproposAllSubCommands (const char *prefix, 403 const char *search_word, 404 StringList &commands_found, 405 StringList &commands_help) 406{ 407 CommandObject *proxy_command = GetProxyCommandObject(); 408 if (proxy_command) 409 return proxy_command->AproposAllSubCommands (prefix, 410 search_word, 411 commands_found, 412 commands_help); 413} 414 415bool 416CommandObjectProxy::LoadSubCommand (const char *cmd_name, 417 const lldb::CommandObjectSP& command_sp) 418{ 419 CommandObject *proxy_command = GetProxyCommandObject(); 420 if (proxy_command) 421 return proxy_command->LoadSubCommand (cmd_name, command_sp); 422 return false; 423} 424 425bool 426CommandObjectProxy::WantsRawCommandString() 427{ 428 CommandObject *proxy_command = GetProxyCommandObject(); 429 if (proxy_command) 430 return proxy_command->WantsRawCommandString(); 431 return false; 432} 433 434bool 435CommandObjectProxy::WantsCompletion() 436{ 437 CommandObject *proxy_command = GetProxyCommandObject(); 438 if (proxy_command) 439 return proxy_command->WantsCompletion(); 440 return false; 441} 442 443 444Options * 445CommandObjectProxy::GetOptions () 446{ 447 CommandObject *proxy_command = GetProxyCommandObject(); 448 if (proxy_command) 449 return proxy_command->GetOptions (); 450 return NULL; 451} 452 453 454int 455CommandObjectProxy::HandleCompletion (Args &input, 456 int &cursor_index, 457 int &cursor_char_position, 458 int match_start_point, 459 int max_return_elements, 460 bool &word_complete, 461 StringList &matches) 462{ 463 CommandObject *proxy_command = GetProxyCommandObject(); 464 if (proxy_command) 465 return proxy_command->HandleCompletion (input, 466 cursor_index, 467 cursor_char_position, 468 match_start_point, 469 max_return_elements, 470 word_complete, 471 matches); 472 matches.Clear(); 473 return 0; 474} 475int 476CommandObjectProxy::HandleArgumentCompletion (Args &input, 477 int &cursor_index, 478 int &cursor_char_position, 479 OptionElementVector &opt_element_vector, 480 int match_start_point, 481 int max_return_elements, 482 bool &word_complete, 483 StringList &matches) 484{ 485 CommandObject *proxy_command = GetProxyCommandObject(); 486 if (proxy_command) 487 return proxy_command->HandleArgumentCompletion (input, 488 cursor_index, 489 cursor_char_position, 490 opt_element_vector, 491 match_start_point, 492 max_return_elements, 493 word_complete, 494 matches); 495 matches.Clear(); 496 return 0; 497} 498 499const char * 500CommandObjectProxy::GetRepeatCommand (Args ¤t_command_args, 501 uint32_t index) 502{ 503 CommandObject *proxy_command = GetProxyCommandObject(); 504 if (proxy_command) 505 return proxy_command->GetRepeatCommand (current_command_args, index); 506 return NULL; 507} 508 509bool 510CommandObjectProxy::Execute (const char *args_string, 511 CommandReturnObject &result) 512{ 513 CommandObject *proxy_command = GetProxyCommandObject(); 514 if (proxy_command) 515 return proxy_command->Execute (args_string, result); 516 result.AppendError ("command is not implemented"); 517 result.SetStatus (eReturnStatusFailed); 518 return false; 519} 520 521 522