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