CommandInterpreter.cpp revision c1ad82eb979ee856b86aec6e2acb7bddf75f7c4f
1//===-- CommandInterpreter.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 <string> 11 12#include <getopt.h> 13#include <stdlib.h> 14 15#include "../Commands/CommandObjectApropos.h" 16#include "../Commands/CommandObjectArgs.h" 17#include "../Commands/CommandObjectBreakpoint.h" 18//#include "../Commands/CommandObjectCall.h" 19#include "../Commands/CommandObjectDisassemble.h" 20#include "../Commands/CommandObjectExpression.h" 21#include "../Commands/CommandObjectFile.h" 22#include "../Commands/CommandObjectFrame.h" 23#include "../Commands/CommandObjectHelp.h" 24#include "../Commands/CommandObjectImage.h" 25#include "../Commands/CommandObjectLog.h" 26#include "../Commands/CommandObjectMemory.h" 27#include "../Commands/CommandObjectProcess.h" 28#include "../Commands/CommandObjectQuit.h" 29#include "lldb/Interpreter/CommandObjectRegexCommand.h" 30#include "../Commands/CommandObjectRegister.h" 31#include "CommandObjectScript.h" 32#include "../Commands/CommandObjectSettings.h" 33#include "../Commands/CommandObjectSource.h" 34#include "../Commands/CommandObjectCommands.h" 35#include "../Commands/CommandObjectSyntax.h" 36#include "../Commands/CommandObjectTarget.h" 37#include "../Commands/CommandObjectThread.h" 38 39#include "lldb/Interpreter/Args.h" 40#include "lldb/Core/Debugger.h" 41#include "lldb/Core/Stream.h" 42#include "lldb/Core/Timer.h" 43#include "lldb/Target/Process.h" 44#include "lldb/Target/Thread.h" 45#include "lldb/Target/TargetList.h" 46 47#include "lldb/Interpreter/CommandReturnObject.h" 48#include "lldb/Interpreter/CommandInterpreter.h" 49 50using namespace lldb; 51using namespace lldb_private; 52 53CommandInterpreter::CommandInterpreter 54( 55 Debugger &debugger, 56 ScriptLanguage script_language, 57 bool synchronous_execution 58) : 59 Broadcaster ("CommandInterpreter"), 60 m_debugger (debugger), 61 m_synchronous_execution (synchronous_execution) 62{ 63 const char *dbg_name = debugger.GetInstanceName().AsCString(); 64 std::string lang_name = ScriptInterpreter::LanguageToString (script_language); 65 StreamString var_name; 66 var_name.Printf ("[%s].script-lang", dbg_name); 67 debugger.GetSettingsController()->SetVariable (var_name.GetData(), lang_name.c_str(), lldb::eVarSetOperationAssign, false); 68} 69 70void 71CommandInterpreter::Initialize () 72{ 73 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 74 75 CommandReturnObject result; 76 77 LoadCommandDictionary (); 78 79 // Set up some initial aliases. 80 result.Clear(); HandleCommand ("command alias q quit", false, result); 81 result.Clear(); HandleCommand ("command alias run process launch", false, result); 82 result.Clear(); HandleCommand ("command alias r process launch", false, result); 83 result.Clear(); HandleCommand ("command alias c process continue", false, result); 84 result.Clear(); HandleCommand ("command alias continue process continue", false, result); 85 result.Clear(); HandleCommand ("command alias expr expression", false, result); 86 result.Clear(); HandleCommand ("command alias exit quit", false, result); 87 result.Clear(); HandleCommand ("command alias b breakpoint", false, result); 88 result.Clear(); HandleCommand ("command alias bt thread backtrace", false, result); 89 result.Clear(); HandleCommand ("command alias si thread step-inst", false, result); 90 result.Clear(); HandleCommand ("command alias step thread step-in", false, result); 91 result.Clear(); HandleCommand ("command alias s thread step-in", false, result); 92 result.Clear(); HandleCommand ("command alias next thread step-over", false, result); 93 result.Clear(); HandleCommand ("command alias n thread step-over", false, result); 94 result.Clear(); HandleCommand ("command alias finish thread step-out", false, result); 95 result.Clear(); HandleCommand ("command alias x memory read", false, result); 96 result.Clear(); HandleCommand ("command alias l source list", false, result); 97 result.Clear(); HandleCommand ("command alias list source list", false, result); 98} 99 100const char * 101CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) 102{ 103 // This function has not yet been implemented. 104 105 // Look for any embedded script command 106 // If found, 107 // get interpreter object from the command dictionary, 108 // call execute_one_command on it, 109 // get the results as a string, 110 // substitute that string for current stuff. 111 112 return arg; 113} 114 115 116void 117CommandInterpreter::LoadCommandDictionary () 118{ 119 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 120 121 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT *** 122 // 123 // Command objects that are used as cross reference objects (i.e. they inherit from CommandObjectCrossref) 124 // *MUST* be created and put into the command dictionary *BEFORE* any multi-word commands (which may use 125 // the cross-referencing stuff) are created!!! 126 // 127 // **** IMPORTANT **** IMPORTANT *** IMPORTANT *** **** IMPORTANT **** IMPORTANT *** IMPORTANT *** 128 129 130 // Command objects that inherit from CommandObjectCrossref must be created before other command objects 131 // are created. This is so that when another command is created that needs to go into a crossref object, 132 // the crossref object exists and is ready to take the cross reference. Put the cross referencing command 133 // objects into the CommandDictionary now, so they are ready for use when the other commands get created. 134 135 // Non-CommandObjectCrossref commands can now be created. 136 137 lldb::ScriptLanguage script_language; 138 lldb::SettableVariableType var_type = lldb::eSetVarTypeString; 139 StringList value; 140 const char *dbg_name = GetDebugger().GetInstanceName().AsCString(); 141 StreamString var_name; 142 var_name.Printf ("[%s].script-lang", dbg_name); 143 value = Debugger::GetSettingsController()->GetVariable (var_name.GetData(), var_type); 144 bool success; 145 script_language = Args::StringToScriptLanguage (value.GetStringAtIndex(0), lldb::eScriptLanguageDefault, &success); 146 147 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos ()); 148 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); 149 //m_command_dict["call"] = CommandObjectSP (new CommandObjectCall ()); 150 m_command_dict["commands"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); 151 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble ()); 152 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression ()); 153 m_command_dict["file"] = CommandObjectSP (new CommandObjectFile ()); 154 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); 155 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp ()); 156 m_command_dict["image"] = CommandObjectSP (new CommandObjectImage (*this)); 157 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); 158 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); 159 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); 160 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit ()); 161 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); 162 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (script_language)); 163 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); 164 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); 165 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); 166 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); 167 168 std::auto_ptr<CommandObjectRegexCommand> 169 break_regex_cmd_ap(new CommandObjectRegexCommand ("regexp-break", 170 "Set a breakpoint using a regular expression to specify the location.", 171 "regexp-break [<file>:<line>]\nregexp-break [<address>]\nregexp-break <...>", 2)); 172 if (break_regex_cmd_ap.get()) 173 { 174 if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") && 175 break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") && 176 break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") && 177 break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list") && 178 break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") && 179 break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'")) 180 { 181 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); 182 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; 183 } 184 } 185} 186 187int 188CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, 189 StringList &matches) 190{ 191 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); 192 193 if (include_aliases) 194 { 195 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); 196 } 197 198 return matches.GetSize(); 199} 200 201CommandObjectSP 202CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) 203{ 204 CommandObject::CommandMap::iterator pos; 205 CommandObjectSP ret_val; 206 207 std::string cmd(cmd_cstr); 208 209 if (HasCommands()) 210 { 211 pos = m_command_dict.find(cmd); 212 if (pos != m_command_dict.end()) 213 ret_val = pos->second; 214 } 215 216 if (include_aliases && HasAliases()) 217 { 218 pos = m_alias_dict.find(cmd); 219 if (pos != m_alias_dict.end()) 220 ret_val = pos->second; 221 } 222 223 if (HasUserCommands()) 224 { 225 pos = m_user_dict.find(cmd); 226 if (pos != m_user_dict.end()) 227 ret_val = pos->second; 228 } 229 230 if (!exact && ret_val == NULL) 231 { 232 // We will only get into here if we didn't find any exact matches. 233 234 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; 235 236 StringList local_matches; 237 if (matches == NULL) 238 matches = &local_matches; 239 240 unsigned int num_cmd_matches = 0; 241 unsigned int num_alias_matches = 0; 242 unsigned int num_user_matches = 0; 243 244 // Look through the command dictionaries one by one, and if we get only one match from any of 245 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. 246 247 if (HasCommands()) 248 { 249 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); 250 } 251 252 if (num_cmd_matches == 1) 253 { 254 cmd.assign(matches->GetStringAtIndex(0)); 255 pos = m_command_dict.find(cmd); 256 if (pos != m_command_dict.end()) 257 real_match_sp = pos->second; 258 } 259 260 if (include_aliases && HasAliases()) 261 { 262 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); 263 264 } 265 266 if (num_alias_matches == 1) 267 { 268 cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); 269 pos = m_alias_dict.find(cmd); 270 if (pos != m_alias_dict.end()) 271 alias_match_sp = pos->second; 272 } 273 274 if (HasUserCommands()) 275 { 276 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); 277 } 278 279 if (num_user_matches == 1) 280 { 281 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); 282 283 pos = m_user_dict.find (cmd); 284 if (pos != m_user_dict.end()) 285 user_match_sp = pos->second; 286 } 287 288 // If we got exactly one match, return that, otherwise return the match list. 289 290 if (num_user_matches + num_cmd_matches + num_alias_matches == 1) 291 { 292 if (num_cmd_matches) 293 return real_match_sp; 294 else if (num_alias_matches) 295 return alias_match_sp; 296 else 297 return user_match_sp; 298 } 299 } 300 else if (matches && ret_val != NULL) 301 { 302 matches->AppendString (cmd_cstr); 303 } 304 305 306 return ret_val; 307} 308 309CommandObjectSP 310CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) 311{ 312 return GetCommandSP(cmd_cstr, include_aliases, true, NULL); 313} 314 315CommandObject * 316CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) 317{ 318 return GetCommandSPExact (cmd_cstr, include_aliases).get(); 319} 320 321CommandObject * 322CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) 323{ 324 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); 325 326 // If we didn't find an exact match to the command string in the commands, look in 327 // the aliases. 328 329 if (command_obj == NULL) 330 { 331 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); 332 } 333 334 // Finally, if there wasn't an exact match among the aliases, look for an inexact match 335 // in both the commands and the aliases. 336 337 if (command_obj == NULL) 338 command_obj = GetCommandSP(cmd_cstr, true, false, matches).get(); 339 340 return command_obj; 341} 342 343bool 344CommandInterpreter::CommandExists (const char *cmd) 345{ 346 return m_command_dict.find(cmd) != m_command_dict.end(); 347} 348 349bool 350CommandInterpreter::AliasExists (const char *cmd) 351{ 352 return m_alias_dict.find(cmd) != m_alias_dict.end(); 353} 354 355bool 356CommandInterpreter::UserCommandExists (const char *cmd) 357{ 358 return m_user_dict.find(cmd) != m_user_dict.end(); 359} 360 361void 362CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp) 363{ 364 command_obj_sp->SetIsAlias (true); 365 m_alias_dict[alias_name] = command_obj_sp; 366} 367 368bool 369CommandInterpreter::RemoveAlias (const char *alias_name) 370{ 371 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name); 372 if (pos != m_alias_dict.end()) 373 { 374 m_alias_dict.erase(pos); 375 return true; 376 } 377 return false; 378} 379bool 380CommandInterpreter::RemoveUser (const char *alias_name) 381{ 382 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); 383 if (pos != m_user_dict.end()) 384 { 385 m_user_dict.erase(pos); 386 return true; 387 } 388 return false; 389} 390 391void 392CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string) 393{ 394 help_string.Printf ("'%s", command_name); 395 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 396 397 if (option_arg_vector_sp != NULL) 398 { 399 OptionArgVector *options = option_arg_vector_sp.get(); 400 for (int i = 0; i < options->size(); ++i) 401 { 402 OptionArgPair cur_option = (*options)[i]; 403 std::string opt = cur_option.first; 404 std::string value = cur_option.second; 405 if (opt.compare("<argument>") == 0) 406 { 407 help_string.Printf (" %s", value.c_str()); 408 } 409 else 410 { 411 help_string.Printf (" %s", opt.c_str()); 412 if ((value.compare ("<no-argument>") != 0) 413 && (value.compare ("<need-argument") != 0)) 414 { 415 help_string.Printf (" %s", value.c_str()); 416 } 417 } 418 } 419 } 420 421 help_string.Printf ("'"); 422} 423 424size_t 425CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict) 426{ 427 CommandObject::CommandMap::const_iterator pos; 428 CommandObject::CommandMap::const_iterator end = dict.end(); 429 size_t max_len = 0; 430 431 for (pos = dict.begin(); pos != end; ++pos) 432 { 433 size_t len = pos->first.size(); 434 if (max_len < len) 435 max_len = len; 436 } 437 return max_len; 438} 439 440void 441CommandInterpreter::GetHelp (CommandReturnObject &result) 442{ 443 CommandObject::CommandMap::const_iterator pos; 444 result.AppendMessage("The following is a list of built-in, permanent debugger commands:"); 445 result.AppendMessage(""); 446 uint32_t max_len = FindLongestCommandWord (m_command_dict); 447 448 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 449 { 450 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 451 max_len); 452 } 453 result.AppendMessage(""); 454 455 if (m_alias_dict.size() > 0) 456 { 457 result.AppendMessage("The following is a list of your current command abbreviations (see 'commands alias' for more info):"); 458 result.AppendMessage(""); 459 max_len = FindLongestCommandWord (m_alias_dict); 460 461 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos) 462 { 463 StreamString sstr; 464 StreamString translation_and_help; 465 std::string entry_name = pos->first; 466 std::string second_entry = pos->second.get()->GetCommandName(); 467 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr); 468 469 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp()); 470 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 471 translation_and_help.GetData(), max_len); 472 } 473 result.AppendMessage(""); 474 } 475 476 if (m_user_dict.size() > 0) 477 { 478 result.AppendMessage ("The following is a list of your current user-defined commands:"); 479 result.AppendMessage(""); 480 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 481 { 482 result.AppendMessageWithFormat ("%s -- %s\n", pos->first.c_str(), pos->second->GetHelp()); 483 } 484 result.AppendMessage(""); 485 } 486 487 result.AppendMessage("For more information on any particular command, try 'help <command-name>'."); 488} 489 490bool 491CommandInterpreter::HandleCommand 492( 493 const char *command_line, 494 bool add_to_history, 495 CommandReturnObject &result, 496 ExecutionContext *override_context 497) 498{ 499 // FIXME: there should probably be a mutex to make sure only one thread can 500 // run the interpreter at a time. 501 502 // TODO: this should be a logging channel in lldb. 503// if (DebugSelf()) 504// { 505// result.AppendMessageWithFormat ("Processing command: %s\n", command_line); 506// } 507 508 m_debugger.UpdateExecutionContext (override_context); 509 510 if (command_line == NULL || command_line[0] == '\0') 511 { 512 if (m_command_history.empty()) 513 { 514 result.AppendError ("empty command"); 515 result.SetStatus(eReturnStatusFailed); 516 return false; 517 } 518 else 519 { 520 command_line = m_repeat_command.c_str(); 521 if (m_repeat_command.empty()) 522 { 523 result.AppendErrorWithFormat("No auto repeat.\n"); 524 result.SetStatus (eReturnStatusFailed); 525 return false; 526 } 527 } 528 add_to_history = false; 529 } 530 531 Args command_args(command_line); 532 533 if (command_args.GetArgumentCount() > 0) 534 { 535 const char *command_cstr = command_args.GetArgumentAtIndex(0); 536 if (command_cstr) 537 { 538 539 // We're looking up the command object here. So first find an exact match to the 540 // command in the commands. 541 CommandObject *command_obj = GetCommandObject(command_cstr); 542 543 if (command_obj != NULL) 544 { 545 if (command_obj->IsAlias()) 546 { 547 BuildAliasCommandArgs (command_obj, command_cstr, command_args, result); 548 if (!result.Succeeded()) 549 return false; 550 } 551 552 if (add_to_history) 553 { 554 const char *repeat_command = command_obj->GetRepeatCommand(command_args, 0); 555 if (repeat_command != NULL) 556 m_repeat_command.assign(repeat_command); 557 else 558 m_repeat_command.assign(command_line); 559 560 m_command_history.push_back (command_line); 561 } 562 563 564 if (command_obj->WantsRawCommandString()) 565 { 566 const char *stripped_command = ::strstr (command_line, command_cstr); 567 if (stripped_command) 568 { 569 stripped_command += strlen(command_cstr); 570 while (isspace(*stripped_command)) 571 ++stripped_command; 572 command_obj->ExecuteRawCommandString (*this, stripped_command, result); 573 } 574 } 575 else 576 { 577 // Remove the command from the args. 578 command_args.Shift(); 579 command_obj->ExecuteWithOptions (*this, command_args, result); 580 } 581 } 582 else 583 { 584 // We didn't find the first command object, so complete the first argument. 585 StringList matches; 586 int num_matches; 587 int cursor_index = 0; 588 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); 589 bool word_complete; 590 num_matches = HandleCompletionMatches (command_args, 591 cursor_index, 592 cursor_char_position, 593 0, 594 -1, 595 word_complete, 596 matches); 597 598 if (num_matches > 0) 599 { 600 std::string error_msg; 601 error_msg.assign ("ambiguous command '"); 602 error_msg.append(command_cstr); 603 error_msg.append ("'."); 604 605 error_msg.append (" Possible completions:"); 606 for (int i = 0; i < num_matches; i++) 607 { 608 error_msg.append ("\n\t"); 609 error_msg.append (matches.GetStringAtIndex (i)); 610 } 611 error_msg.append ("\n"); 612 result.AppendRawError (error_msg.c_str(), error_msg.size()); 613 } 614 else 615 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_cstr); 616 617 result.SetStatus (eReturnStatusFailed); 618 } 619 } 620 } 621 return result.Succeeded(); 622} 623 624int 625CommandInterpreter::HandleCompletionMatches (Args &parsed_line, 626 int &cursor_index, 627 int &cursor_char_position, 628 int match_start_point, 629 int max_return_elements, 630 bool &word_complete, 631 StringList &matches) 632{ 633 int num_command_matches = 0; 634 bool look_for_subcommand = false; 635 636 // For any of the command completions a unique match will be a complete word. 637 word_complete = true; 638 639 if (cursor_index == -1) 640 { 641 // We got nothing on the command line, so return the list of commands 642 bool include_aliases = true; 643 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches); 644 } 645 else if (cursor_index == 0) 646 { 647 // The cursor is in the first argument, so just do a lookup in the dictionary. 648 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches); 649 num_command_matches = matches.GetSize(); 650 651 if (num_command_matches == 1 652 && cmd_obj && cmd_obj->IsMultiwordObject() 653 && matches.GetStringAtIndex(0) != NULL 654 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 655 { 656 look_for_subcommand = true; 657 num_command_matches = 0; 658 matches.DeleteStringAtIndex(0); 659 parsed_line.AppendArgument (""); 660 cursor_index++; 661 cursor_char_position = 0; 662 } 663 } 664 665 if (cursor_index > 0 || look_for_subcommand) 666 { 667 // We are completing further on into a commands arguments, so find the command and tell it 668 // to complete the command. 669 // First see if there is a matching initial command: 670 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); 671 if (command_object == NULL) 672 { 673 return 0; 674 } 675 else 676 { 677 parsed_line.Shift(); 678 cursor_index--; 679 num_command_matches = command_object->HandleCompletion (*this, 680 parsed_line, 681 cursor_index, 682 cursor_char_position, 683 match_start_point, 684 max_return_elements, 685 word_complete, 686 matches); 687 } 688 } 689 690 return num_command_matches; 691 692} 693 694int 695CommandInterpreter::HandleCompletion (const char *current_line, 696 const char *cursor, 697 const char *last_char, 698 int match_start_point, 699 int max_return_elements, 700 StringList &matches) 701{ 702 // We parse the argument up to the cursor, so the last argument in parsed_line is 703 // the one containing the cursor, and the cursor is after the last character. 704 705 Args parsed_line(current_line, last_char - current_line); 706 Args partial_parsed_line(current_line, cursor - current_line); 707 708 int num_args = partial_parsed_line.GetArgumentCount(); 709 int cursor_index = partial_parsed_line.GetArgumentCount() - 1; 710 int cursor_char_position; 711 712 if (cursor_index == -1) 713 cursor_char_position = 0; 714 else 715 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index)); 716 717 int num_command_matches; 718 719 matches.Clear(); 720 721 // Only max_return_elements == -1 is supported at present: 722 assert (max_return_elements == -1); 723 bool word_complete; 724 num_command_matches = HandleCompletionMatches (parsed_line, 725 cursor_index, 726 cursor_char_position, 727 match_start_point, 728 max_return_elements, 729 word_complete, 730 matches); 731 732 if (num_command_matches <= 0) 733 return num_command_matches; 734 735 if (num_args == 0) 736 { 737 // If we got an empty string, insert nothing. 738 matches.InsertStringAtIndex(0, ""); 739 } 740 else 741 { 742 // Now figure out if there is a common substring, and if so put that in element 0, otherwise 743 // put an empty string in element 0. 744 std::string command_partial_str; 745 if (cursor_index >= 0) 746 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position); 747 748 std::string common_prefix; 749 matches.LongestCommonPrefix (common_prefix); 750 int partial_name_len = command_partial_str.size(); 751 752 // If we matched a unique single command, add a space... 753 // Only do this if the completer told us this was a complete word, however... 754 if (num_command_matches == 1 && word_complete) 755 { 756 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); 757 if (quote_char != '\0') 758 common_prefix.push_back(quote_char); 759 760 common_prefix.push_back(' '); 761 } 762 common_prefix.erase (0, partial_name_len); 763 matches.InsertStringAtIndex(0, common_prefix.c_str()); 764 } 765 return num_command_matches; 766} 767 768 769CommandInterpreter::~CommandInterpreter () 770{ 771} 772 773const char * 774CommandInterpreter::GetPrompt () 775{ 776 lldb::SettableVariableType var_type; 777 const char *instance_name = GetDebugger().GetInstanceName().AsCString(); 778 StreamString var_name; 779 var_name.Printf ("[%s].prompt", instance_name); 780 return Debugger::GetSettingsController()->GetVariable (var_name.GetData(), var_type).GetStringAtIndex(0); 781} 782 783void 784CommandInterpreter::SetPrompt (const char *new_prompt) 785{ 786 const char *instance_name = GetDebugger().GetInstanceName().AsCString(); 787 StreamString name_str; 788 name_str.Printf ("[%s].prompt", instance_name); 789 Debugger::GetSettingsController()->SetVariable (name_str.GetData(), new_prompt, lldb::eVarSetOperationAssign, false); 790} 791 792void 793CommandInterpreter::CrossRegisterCommand (const char * dest_cmd, const char * object_type) 794{ 795 CommandObjectSP cmd_obj_sp = GetCommandSPExact (dest_cmd, true); 796 797 if (cmd_obj_sp != NULL) 798 { 799 CommandObject *cmd_obj = cmd_obj_sp.get(); 800 if (cmd_obj->IsCrossRefObject ()) 801 cmd_obj->AddObject (object_type); 802 } 803} 804 805OptionArgVectorSP 806CommandInterpreter::GetAliasOptions (const char *alias_name) 807{ 808 OptionArgMap::iterator pos; 809 OptionArgVectorSP ret_val; 810 811 std::string alias (alias_name); 812 813 if (HasAliasOptions()) 814 { 815 pos = m_alias_options.find (alias); 816 if (pos != m_alias_options.end()) 817 ret_val = pos->second; 818 } 819 820 return ret_val; 821} 822 823void 824CommandInterpreter::RemoveAliasOptions (const char *alias_name) 825{ 826 OptionArgMap::iterator pos = m_alias_options.find(alias_name); 827 if (pos != m_alias_options.end()) 828 { 829 m_alias_options.erase (pos); 830 } 831} 832 833void 834CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp) 835{ 836 m_alias_options[alias_name] = option_arg_vector_sp; 837} 838 839bool 840CommandInterpreter::HasCommands () 841{ 842 return (!m_command_dict.empty()); 843} 844 845bool 846CommandInterpreter::HasAliases () 847{ 848 return (!m_alias_dict.empty()); 849} 850 851bool 852CommandInterpreter::HasUserCommands () 853{ 854 return (!m_user_dict.empty()); 855} 856 857bool 858CommandInterpreter::HasAliasOptions () 859{ 860 return (!m_alias_options.empty()); 861} 862 863void 864CommandInterpreter::BuildAliasCommandArgs 865( 866 CommandObject *alias_cmd_obj, 867 const char *alias_name, 868 Args &cmd_args, 869 CommandReturnObject &result 870) 871{ 872 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 873 874 if (option_arg_vector_sp.get()) 875 { 876 // Make sure that the alias name is the 0th element in cmd_args 877 std::string alias_name_str = alias_name; 878 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) 879 cmd_args.Unshift (alias_name); 880 881 Args new_args (alias_cmd_obj->GetCommandName()); 882 if (new_args.GetArgumentCount() == 2) 883 new_args.Shift(); 884 885 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 886 int old_size = cmd_args.GetArgumentCount(); 887 int *used = (int *) malloc ((old_size + 1) * sizeof (int)); 888 889 memset (used, 0, (old_size + 1) * sizeof (int)); 890 used[0] = 1; 891 892 for (int i = 0; i < option_arg_vector->size(); ++i) 893 { 894 OptionArgPair option_pair = (*option_arg_vector)[i]; 895 std::string option = option_pair.first; 896 std::string value = option_pair.second; 897 if (option.compare ("<argument>") == 0) 898 new_args.AppendArgument (value.c_str()); 899 else 900 { 901 new_args.AppendArgument (option.c_str()); 902 if (value.compare ("<no-argument>") != 0) 903 { 904 int index = GetOptionArgumentPosition (value.c_str()); 905 if (index == 0) 906 // value was NOT a positional argument; must be a real value 907 new_args.AppendArgument (value.c_str()); 908 else if (index >= cmd_args.GetArgumentCount()) 909 { 910 result.AppendErrorWithFormat 911 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 912 index); 913 result.SetStatus (eReturnStatusFailed); 914 return; 915 } 916 else 917 { 918 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); 919 used[index] = 1; 920 } 921 } 922 } 923 } 924 925 for (int j = 0; j < cmd_args.GetArgumentCount(); ++j) 926 { 927 if (!used[j]) 928 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); 929 } 930 931 cmd_args.Clear(); 932 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); 933 } 934 else 935 { 936 result.SetStatus (eReturnStatusSuccessFinishNoResult); 937 // This alias was not created with any options; nothing further needs to be done. 938 return; 939 } 940 941 result.SetStatus (eReturnStatusSuccessFinishNoResult); 942 return; 943} 944 945 946int 947CommandInterpreter::GetOptionArgumentPosition (const char *in_string) 948{ 949 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position 950 // of zero. 951 952 char *cptr = (char *) in_string; 953 954 // Does it start with '%' 955 if (cptr[0] == '%') 956 { 957 ++cptr; 958 959 // Is the rest of it entirely digits? 960 if (isdigit (cptr[0])) 961 { 962 const char *start = cptr; 963 while (isdigit (cptr[0])) 964 ++cptr; 965 966 // We've gotten to the end of the digits; are we at the end of the string? 967 if (cptr[0] == '\0') 968 position = atoi (start); 969 } 970 } 971 972 return position; 973} 974 975void 976CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) 977{ 978 const char *init_file_path = in_cwd ? "./.lldbinit" : "~/.lldbinit"; 979 FileSpec init_file (init_file_path); 980 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting 981 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details). 982 983 if (init_file.Exists()) 984 { 985 char path[PATH_MAX]; 986 init_file.GetPath(path, sizeof(path)); 987 StreamString source_command; 988 source_command.Printf ("command source '%s'", path); 989 HandleCommand (source_command.GetData(), false, result); 990 } 991 else 992 { 993 // nothing to be done if the file doesn't exist 994 result.SetStatus(eReturnStatusSuccessFinishNoResult); 995 } 996} 997 998ScriptInterpreter * 999CommandInterpreter::GetScriptInterpreter () 1000{ 1001 CommandObject::CommandMap::iterator pos; 1002 1003 pos = m_command_dict.find ("script"); 1004 if (pos != m_command_dict.end()) 1005 { 1006 CommandObject *script_cmd_obj = pos->second.get(); 1007 return ((CommandObjectScript *) script_cmd_obj)->GetInterpreter (*this); 1008 } 1009 return NULL; 1010} 1011 1012 1013 1014bool 1015CommandInterpreter::GetSynchronous () 1016{ 1017 return m_synchronous_execution; 1018} 1019 1020void 1021CommandInterpreter::SetSynchronous (bool value) 1022{ 1023 static bool value_set_once = false; 1024 if (!value_set_once) 1025 { 1026 value_set_once = true; 1027 m_synchronous_execution = value; 1028 } 1029} 1030 1031void 1032CommandInterpreter::OutputFormattedHelpText (Stream &strm, 1033 const char *word_text, 1034 const char *separator, 1035 const char *help_text, 1036 uint32_t max_word_len) 1037{ 1038 lldb::SettableVariableType var_type; 1039 const char *width_value = 1040 Debugger::GetSettingsController()->GetVariable ("term-width", var_type).GetStringAtIndex(0); 1041 int max_columns = atoi (width_value); 1042 // Sanity check max_columns, to cope with emacs shell mode with TERM=dumb 1043 // (0 rows; 0 columns;). 1044 if (max_columns <= 0) max_columns = 80; 1045 1046 int indent_size = max_word_len + strlen (separator) + 2; 1047 1048 strm.IndentMore (indent_size); 1049 1050 int len = indent_size + strlen (help_text) + 1; 1051 char *text = (char *) malloc (len); 1052 sprintf (text, "%-*s %s %s", max_word_len, word_text, separator, help_text); 1053 if (text[len - 1] == '\n') 1054 text[--len] = '\0'; 1055 1056 if (len < max_columns) 1057 { 1058 // Output it as a single line. 1059 strm.Printf ("%s", text); 1060 } 1061 else 1062 { 1063 // We need to break it up into multiple lines. 1064 bool first_line = true; 1065 int text_width; 1066 int start = 0; 1067 int end = start; 1068 int final_end = strlen (text); 1069 int sub_len; 1070 1071 while (end < final_end) 1072 { 1073 if (first_line) 1074 text_width = max_columns - 1; 1075 else 1076 text_width = max_columns - indent_size - 1; 1077 1078 // Don't start the 'text' on a space, since we're already outputting the indentation. 1079 if (!first_line) 1080 { 1081 while ((start < final_end) && (text[start] == ' ')) 1082 start++; 1083 } 1084 1085 end = start + text_width; 1086 if (end > final_end) 1087 end = final_end; 1088 else 1089 { 1090 // If we're not at the end of the text, make sure we break the line on white space. 1091 while (end > start 1092 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 1093 end--; 1094 } 1095 1096 sub_len = end - start; 1097 if (start != 0) 1098 strm.EOL(); 1099 if (!first_line) 1100 strm.Indent(); 1101 else 1102 first_line = false; 1103 assert (start <= final_end); 1104 assert (start + sub_len <= final_end); 1105 if (sub_len > 0) 1106 strm.Write (text + start, sub_len); 1107 start = end + 1; 1108 } 1109 } 1110 strm.EOL(); 1111 strm.IndentLess(indent_size); 1112 free (text); 1113} 1114 1115void 1116CommandInterpreter::AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word, 1117 StringList &commands_found, StringList &commands_help) 1118{ 1119 CommandObject::CommandMap::const_iterator pos; 1120 CommandObject::CommandMap sub_cmd_dict = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict; 1121 CommandObject *sub_cmd_obj; 1122 1123 for (pos = sub_cmd_dict.begin(); pos != sub_cmd_dict.end(); ++pos) 1124 { 1125 const char * command_name = pos->first.c_str(); 1126 sub_cmd_obj = pos->second.get(); 1127 StreamString complete_command_name; 1128 1129 complete_command_name.Printf ("%s %s", prefix, command_name); 1130 1131 if (sub_cmd_obj->HelpTextContainsWord (search_word)) 1132 { 1133 commands_found.AppendString (complete_command_name.GetData()); 1134 commands_help.AppendString (sub_cmd_obj->GetHelp()); 1135 } 1136 1137 if (sub_cmd_obj->IsMultiwordObject()) 1138 AproposAllSubCommands (sub_cmd_obj, complete_command_name.GetData(), search_word, commands_found, 1139 commands_help); 1140 } 1141 1142} 1143 1144void 1145CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found, 1146 StringList &commands_help) 1147{ 1148 CommandObject::CommandMap::const_iterator pos; 1149 1150 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 1151 { 1152 const char *command_name = pos->first.c_str(); 1153 CommandObject *cmd_obj = pos->second.get(); 1154 1155 if (cmd_obj->HelpTextContainsWord (search_word)) 1156 { 1157 commands_found.AppendString (command_name); 1158 commands_help.AppendString (cmd_obj->GetHelp()); 1159 } 1160 1161 if (cmd_obj->IsMultiwordObject()) 1162 AproposAllSubCommands (cmd_obj, command_name, search_word, commands_found, commands_help); 1163 1164 } 1165} 1166