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