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 #include <vector> 12 #include <stdlib.h> 13 14 #include "CommandObjectScript.h" 15 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 16 17 #include "../Commands/CommandObjectApropos.h" 18 #include "../Commands/CommandObjectArgs.h" 19 #include "../Commands/CommandObjectBreakpoint.h" 20 #include "../Commands/CommandObjectBugreport.h" 21 #include "../Commands/CommandObjectDisassemble.h" 22 #include "../Commands/CommandObjectExpression.h" 23 #include "../Commands/CommandObjectFrame.h" 24 #include "../Commands/CommandObjectGUI.h" 25 #include "../Commands/CommandObjectHelp.h" 26 #include "../Commands/CommandObjectLog.h" 27 #include "../Commands/CommandObjectMemory.h" 28 #include "../Commands/CommandObjectPlatform.h" 29 #include "../Commands/CommandObjectPlugin.h" 30 #include "../Commands/CommandObjectProcess.h" 31 #include "../Commands/CommandObjectQuit.h" 32 #include "../Commands/CommandObjectRegister.h" 33 #include "../Commands/CommandObjectSettings.h" 34 #include "../Commands/CommandObjectSource.h" 35 #include "../Commands/CommandObjectCommands.h" 36 #include "../Commands/CommandObjectSyntax.h" 37 #include "../Commands/CommandObjectTarget.h" 38 #include "../Commands/CommandObjectThread.h" 39 #include "../Commands/CommandObjectType.h" 40 #include "../Commands/CommandObjectVersion.h" 41 #include "../Commands/CommandObjectWatchpoint.h" 42 #include "../Commands/CommandObjectLanguage.h" 43 44 #include "lldb/Core/Debugger.h" 45 #include "lldb/Core/Log.h" 46 #include "lldb/Core/PluginManager.h" 47 #include "lldb/Core/State.h" 48 #include "lldb/Core/Stream.h" 49 #include "lldb/Core/StreamFile.h" 50 #include "lldb/Core/Timer.h" 51 52 #ifndef LLDB_DISABLE_LIBEDIT 53 #include "lldb/Host/Editline.h" 54 #endif 55 #include "lldb/Host/Host.h" 56 #include "lldb/Host/HostInfo.h" 57 58 #include "lldb/Interpreter/Args.h" 59 #include "lldb/Interpreter/CommandCompletions.h" 60 #include "lldb/Interpreter/CommandInterpreter.h" 61 #include "lldb/Interpreter/CommandReturnObject.h" 62 #include "lldb/Interpreter/Options.h" 63 #include "lldb/Interpreter/OptionValueProperties.h" 64 #include "lldb/Interpreter/Property.h" 65 66 67 #include "lldb/Target/Process.h" 68 #include "lldb/Target/Thread.h" 69 #include "lldb/Target/TargetList.h" 70 71 #include "lldb/Utility/CleanUp.h" 72 73 #include "llvm/ADT/SmallString.h" 74 #include "llvm/ADT/STLExtras.h" 75 #include "llvm/Support/Path.h" 76 77 using namespace lldb; 78 using namespace lldb_private; 79 80 static const char *k_white_space = " \t\v"; 81 82 static PropertyDefinition 83 g_properties[] = 84 { 85 { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, 86 { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, 87 { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, 88 { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." }, 89 { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr } 90 }; 91 92 enum 93 { 94 ePropertyExpandRegexAliases = 0, 95 ePropertyPromptOnQuit = 1, 96 ePropertyStopCmdSourceOnError = 2, 97 eSpaceReplPrompts = 3 98 }; 99 100 ConstString & 101 CommandInterpreter::GetStaticBroadcasterClass () 102 { 103 static ConstString class_name ("lldb.commandInterpreter"); 104 return class_name; 105 } 106 107 CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution) 108 : Broadcaster(&debugger, CommandInterpreter::GetStaticBroadcasterClass().AsCString()), 109 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), 110 IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), 111 m_debugger(debugger), 112 m_synchronous_execution(synchronous_execution), 113 m_skip_lldbinit_files(false), 114 m_skip_app_init_files(false), 115 m_script_interpreter_sp(), 116 m_command_io_handler_sp(), 117 m_comment_char('#'), 118 m_batch_command_mode(false), 119 m_truncation_warning(eNoTruncation), 120 m_command_source_depth(0), 121 m_num_errors(0), 122 m_quit_requested(false), 123 m_stopped_for_crash(false) 124 { 125 debugger.SetScriptLanguage (script_language); 126 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); 127 SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); 128 SetEventName (eBroadcastBitQuitCommandReceived, "quit"); 129 CheckInWithManager (); 130 m_collection_sp->Initialize (g_properties); 131 } 132 133 bool 134 CommandInterpreter::GetExpandRegexAliases () const 135 { 136 const uint32_t idx = ePropertyExpandRegexAliases; 137 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 138 } 139 140 bool 141 CommandInterpreter::GetPromptOnQuit () const 142 { 143 const uint32_t idx = ePropertyPromptOnQuit; 144 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 145 } 146 147 void 148 CommandInterpreter::SetPromptOnQuit (bool b) 149 { 150 const uint32_t idx = ePropertyPromptOnQuit; 151 m_collection_sp->SetPropertyAtIndexAsBoolean (nullptr, idx, b); 152 } 153 154 void 155 CommandInterpreter::ResolveCommand(const char *command_line, CommandReturnObject &result) 156 { 157 std::string command = command_line; 158 if (ResolveCommandImpl(command, result) != nullptr) { 159 result.AppendMessageWithFormat("%s", command.c_str()); 160 result.SetStatus(eReturnStatusSuccessFinishResult); 161 } 162 } 163 164 165 bool 166 CommandInterpreter::GetStopCmdSourceOnError () const 167 { 168 const uint32_t idx = ePropertyStopCmdSourceOnError; 169 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 170 } 171 172 bool 173 CommandInterpreter::GetSpaceReplPrompts () const 174 { 175 const uint32_t idx = eSpaceReplPrompts; 176 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 177 } 178 179 void 180 CommandInterpreter::Initialize () 181 { 182 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 183 184 CommandReturnObject result; 185 186 LoadCommandDictionary (); 187 188 // Set up some initial aliases. 189 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false); 190 if (cmd_obj_sp) 191 { 192 AddAlias ("q", cmd_obj_sp); 193 AddAlias ("exit", cmd_obj_sp); 194 } 195 196 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false); 197 if (cmd_obj_sp) 198 { 199 AddAlias ("attach", cmd_obj_sp); 200 } 201 202 cmd_obj_sp = GetCommandSPExact ("process detach",false); 203 if (cmd_obj_sp) 204 { 205 AddAlias ("detach", cmd_obj_sp); 206 } 207 208 cmd_obj_sp = GetCommandSPExact ("process continue", false); 209 if (cmd_obj_sp) 210 { 211 AddAlias ("c", cmd_obj_sp); 212 AddAlias ("continue", cmd_obj_sp); 213 } 214 215 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false); 216 if (cmd_obj_sp) 217 AddAlias ("b", cmd_obj_sp); 218 219 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false); 220 if (cmd_obj_sp) 221 AddAlias ("tbreak", cmd_obj_sp); 222 223 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false); 224 if (cmd_obj_sp) 225 { 226 AddAlias ("stepi", cmd_obj_sp); 227 AddAlias ("si", cmd_obj_sp); 228 } 229 230 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false); 231 if (cmd_obj_sp) 232 { 233 AddAlias ("nexti", cmd_obj_sp); 234 AddAlias ("ni", cmd_obj_sp); 235 } 236 237 cmd_obj_sp = GetCommandSPExact ("thread step-in", false); 238 if (cmd_obj_sp) 239 { 240 AddAlias ("s", cmd_obj_sp); 241 AddAlias ("step", cmd_obj_sp); 242 } 243 244 cmd_obj_sp = GetCommandSPExact ("thread step-over", false); 245 if (cmd_obj_sp) 246 { 247 AddAlias ("n", cmd_obj_sp); 248 AddAlias ("next", cmd_obj_sp); 249 } 250 251 cmd_obj_sp = GetCommandSPExact ("thread step-out", false); 252 if (cmd_obj_sp) 253 { 254 AddAlias ("finish", cmd_obj_sp); 255 } 256 257 cmd_obj_sp = GetCommandSPExact ("frame select", false); 258 if (cmd_obj_sp) 259 { 260 AddAlias ("f", cmd_obj_sp); 261 } 262 263 cmd_obj_sp = GetCommandSPExact ("thread select", false); 264 if (cmd_obj_sp) 265 { 266 AddAlias ("t", cmd_obj_sp); 267 } 268 269 cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false); 270 if (cmd_obj_sp) 271 { 272 AddAlias ("j", cmd_obj_sp); 273 AddAlias ("jump", cmd_obj_sp); 274 } 275 276 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false); 277 if (cmd_obj_sp) 278 { 279 AddAlias ("l", cmd_obj_sp); 280 AddAlias ("list", cmd_obj_sp); 281 } 282 283 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false); 284 if (cmd_obj_sp) 285 { 286 AddAlias ("env", cmd_obj_sp); 287 } 288 289 cmd_obj_sp = GetCommandSPExact ("memory read", false); 290 if (cmd_obj_sp) 291 AddAlias ("x", cmd_obj_sp); 292 293 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false); 294 if (cmd_obj_sp) 295 AddAlias ("up", cmd_obj_sp); 296 297 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false); 298 if (cmd_obj_sp) 299 AddAlias ("down", cmd_obj_sp); 300 301 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false); 302 if (cmd_obj_sp) 303 AddAlias ("display", cmd_obj_sp); 304 305 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 306 if (cmd_obj_sp) 307 AddAlias ("dis", cmd_obj_sp); 308 309 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 310 if (cmd_obj_sp) 311 AddAlias ("di", cmd_obj_sp); 312 313 314 315 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false); 316 if (cmd_obj_sp) 317 AddAlias ("undisplay", cmd_obj_sp); 318 319 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false); 320 if (cmd_obj_sp) 321 AddAlias ("bt", cmd_obj_sp); 322 323 cmd_obj_sp = GetCommandSPExact ("target create", false); 324 if (cmd_obj_sp) 325 AddAlias ("file", cmd_obj_sp); 326 327 cmd_obj_sp = GetCommandSPExact ("target modules", false); 328 if (cmd_obj_sp) 329 AddAlias ("image", cmd_obj_sp); 330 331 332 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector); 333 334 cmd_obj_sp = GetCommandSPExact ("expression", false); 335 if (cmd_obj_sp) 336 { 337 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 338 AddAlias ("p", cmd_obj_sp); 339 AddAlias ("print", cmd_obj_sp); 340 AddAlias ("call", cmd_obj_sp); 341 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp); 342 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp); 343 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp); 344 345 alias_arguments_vector_sp.reset (new OptionArgVector); 346 ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp); 347 AddAlias ("po", cmd_obj_sp); 348 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp); 349 } 350 351 cmd_obj_sp = GetCommandSPExact ("process kill", false); 352 if (cmd_obj_sp) 353 { 354 AddAlias ("kill", cmd_obj_sp); 355 } 356 357 cmd_obj_sp = GetCommandSPExact ("process launch", false); 358 if (cmd_obj_sp) 359 { 360 alias_arguments_vector_sp.reset (new OptionArgVector); 361 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) 362 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 363 #else 364 #if defined(__APPLE__) 365 std::string shell_option; 366 shell_option.append("--shell-expand-args"); 367 shell_option.append(" true"); 368 shell_option.append(" --"); 369 ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); 370 #else 371 std::string shell_option; 372 shell_option.append("--shell="); 373 shell_option.append(HostInfo::GetDefaultShell().GetPath()); 374 shell_option.append(" --"); 375 ProcessAliasOptionsArgs (cmd_obj_sp, shell_option.c_str(), alias_arguments_vector_sp); 376 #endif 377 #endif 378 AddAlias ("r", cmd_obj_sp); 379 AddAlias ("run", cmd_obj_sp); 380 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp); 381 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp); 382 } 383 384 cmd_obj_sp = GetCommandSPExact ("target symbols add", false); 385 if (cmd_obj_sp) 386 { 387 AddAlias ("add-dsym", cmd_obj_sp); 388 } 389 390 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false); 391 if (cmd_obj_sp) 392 { 393 alias_arguments_vector_sp.reset (new OptionArgVector); 394 ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp); 395 AddAlias ("rbreak", cmd_obj_sp); 396 AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp); 397 } 398 } 399 400 void 401 CommandInterpreter::Clear() 402 { 403 m_command_io_handler_sp.reset(); 404 405 if (m_script_interpreter_sp) 406 m_script_interpreter_sp->Clear(); 407 } 408 409 const char * 410 CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) 411 { 412 // This function has not yet been implemented. 413 414 // Look for any embedded script command 415 // If found, 416 // get interpreter object from the command dictionary, 417 // call execute_one_command on it, 418 // get the results as a string, 419 // substitute that string for current stuff. 420 421 return arg; 422 } 423 424 425 void 426 CommandInterpreter::LoadCommandDictionary () 427 { 428 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 429 430 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); 431 432 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); 433 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); 434 m_command_dict["bugreport"] = CommandObjectSP (new CommandObjectMultiwordBugreport (*this)); 435 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); 436 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); 437 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this)); 438 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); 439 m_command_dict["gui"] = CommandObjectSP (new CommandObjectGUI (*this)); 440 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this)); 441 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); 442 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); 443 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this)); 444 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this)); 445 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); 446 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this)); 447 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); 448 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language)); 449 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); 450 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); 451 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); 452 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); 453 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this)); 454 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this)); 455 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); 456 m_command_dict["language"] = CommandObjectSP (new CommandObjectLanguage(*this)); 457 458 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, 459 {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, 460 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, 461 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, 462 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, 463 {"^(-.*)$", "breakpoint set %1"}, 464 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"}, 465 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, 466 {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}}; 467 468 size_t num_regexes = llvm::array_lengthof(break_regexes); 469 470 std::unique_ptr<CommandObjectRegexCommand> 471 break_regex_cmd_ap(new CommandObjectRegexCommand (*this, 472 "_regexp-break", 473 "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.\n", 474 "\n_regexp-break <filename>:<linenum> # _regexp-break main.c:12 // Break on line 12 of main.c\n" 475 "_regexp-break <linenum> # _regexp-break 12 // Break on line 12 of current file\n" 476 "_regexp-break <address> # _regexp-break 0x1234000 // Break on address 0x1234000\n" 477 "_regexp-break <name> # _regexp-break main // Break in 'main' after the prologue\n" 478 "_regexp-break &<name> # _regexp-break &main // Break on the first instruction in 'main'\n" 479 "_regexp-break <module>`<name> # _regexp-break libc.so`malloc // Break in 'malloc' only in the 'libc.so' shared library\n" 480 "_regexp-break /<source-regex>/ # _regexp-break /break here/ // Break on all lines that match the regular expression 'break here' in the current file.\n", 481 2, 482 CommandCompletions::eSymbolCompletion | 483 CommandCompletions::eSourceFileCompletion, 484 false)); 485 486 if (break_regex_cmd_ap.get()) 487 { 488 bool success = true; 489 for (size_t i = 0; i < num_regexes; i++) 490 { 491 success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]); 492 if (!success) 493 break; 494 } 495 success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 496 497 if (success) 498 { 499 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); 500 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; 501 } 502 } 503 504 std::unique_ptr<CommandObjectRegexCommand> 505 tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this, 506 "_regexp-tbreak", 507 "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 508 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 509 2, 510 CommandCompletions::eSymbolCompletion | 511 CommandCompletions::eSourceFileCompletion, 512 false)); 513 514 if (tbreak_regex_cmd_ap.get()) 515 { 516 bool success = true; 517 for (size_t i = 0; i < num_regexes; i++) 518 { 519 // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer. 520 char buffer[1024]; 521 int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); 522 assert (num_printed < 1024); 523 UNUSED_IF_ASSERT_DISABLED(num_printed); 524 success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); 525 if (!success) 526 break; 527 } 528 success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 529 530 if (success) 531 { 532 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); 533 m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp; 534 } 535 } 536 537 std::unique_ptr<CommandObjectRegexCommand> 538 attach_regex_cmd_ap(new CommandObjectRegexCommand (*this, 539 "_regexp-attach", 540 "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", 541 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", 542 2, 543 0, 544 false)); 545 if (attach_regex_cmd_ap.get()) 546 { 547 if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && 548 attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach' 549 attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") && 550 attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) 551 { 552 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); 553 m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp; 554 } 555 } 556 557 std::unique_ptr<CommandObjectRegexCommand> 558 down_regex_cmd_ap(new CommandObjectRegexCommand (*this, 559 "_regexp-down", 560 "Go down \"n\" frames in the stack (1 frame by default).", 561 "_regexp-down [n]", 562 2, 563 0, 564 false)); 565 if (down_regex_cmd_ap.get()) 566 { 567 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && 568 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1")) 569 { 570 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); 571 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp; 572 } 573 } 574 575 std::unique_ptr<CommandObjectRegexCommand> 576 up_regex_cmd_ap(new CommandObjectRegexCommand (*this, 577 "_regexp-up", 578 "Go up \"n\" frames in the stack (1 frame by default).", 579 "_regexp-up [n]", 580 2, 581 0, 582 false)); 583 if (up_regex_cmd_ap.get()) 584 { 585 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && 586 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) 587 { 588 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); 589 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp; 590 } 591 } 592 593 std::unique_ptr<CommandObjectRegexCommand> 594 display_regex_cmd_ap(new CommandObjectRegexCommand (*this, 595 "_regexp-display", 596 "Add an expression evaluation stop-hook.", 597 "_regexp-display expression", 598 2, 599 0, 600 false)); 601 if (display_regex_cmd_ap.get()) 602 { 603 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) 604 { 605 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); 606 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp; 607 } 608 } 609 610 std::unique_ptr<CommandObjectRegexCommand> 611 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, 612 "_regexp-undisplay", 613 "Remove an expression evaluation stop-hook.", 614 "_regexp-undisplay stop-hook-number", 615 2, 616 0, 617 false)); 618 if (undisplay_regex_cmd_ap.get()) 619 { 620 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) 621 { 622 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); 623 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp; 624 } 625 } 626 627 std::unique_ptr<CommandObjectRegexCommand> 628 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, 629 "gdb-remote", 630 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", 631 "gdb-remote [<hostname>:]<portnum>", 632 2, 633 0, 634 false)); 635 if (connect_gdb_remote_cmd_ap.get()) 636 { 637 if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && 638 connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) 639 { 640 CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); 641 m_command_dict[command_sp->GetCommandName ()] = command_sp; 642 } 643 } 644 645 std::unique_ptr<CommandObjectRegexCommand> 646 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, 647 "kdp-remote", 648 "Connect to a remote KDP server. udp port 41139 is the default port number.", 649 "kdp-remote <hostname>[:<portnum>]", 650 2, 651 0, 652 false)); 653 if (connect_kdp_remote_cmd_ap.get()) 654 { 655 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && 656 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) 657 { 658 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); 659 m_command_dict[command_sp->GetCommandName ()] = command_sp; 660 } 661 } 662 663 std::unique_ptr<CommandObjectRegexCommand> 664 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, 665 "_regexp-bt", 666 "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", 667 "bt [<digit>|all]", 668 2, 669 0, 670 false)); 671 if (bt_regex_cmd_ap.get()) 672 { 673 // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace 674 // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and 675 // so now "bt 3" is the preferred form, in line with gdb. 676 if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") && 677 bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") && 678 bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && 679 bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) 680 { 681 CommandObjectSP command_sp(bt_regex_cmd_ap.release()); 682 m_command_dict[command_sp->GetCommandName ()] = command_sp; 683 } 684 } 685 686 std::unique_ptr<CommandObjectRegexCommand> 687 list_regex_cmd_ap(new CommandObjectRegexCommand (*this, 688 "_regexp-list", 689 "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", 690 "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]", 691 2, 692 CommandCompletions::eSourceFileCompletion, 693 false)); 694 if (list_regex_cmd_ap.get()) 695 { 696 if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && 697 list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") && 698 list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") && 699 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") && 700 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") && 701 list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") && 702 list_regex_cmd_ap->AddRegexCommand("^$", "source list")) 703 { 704 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); 705 m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp; 706 } 707 } 708 709 std::unique_ptr<CommandObjectRegexCommand> 710 env_regex_cmd_ap(new CommandObjectRegexCommand (*this, 711 "_regexp-env", 712 "Implements a shortcut to viewing and setting environment variables.", 713 "_regexp-env\n_regexp-env FOO=BAR", 714 2, 715 0, 716 false)); 717 if (env_regex_cmd_ap.get()) 718 { 719 if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && 720 env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1")) 721 { 722 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); 723 m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp; 724 } 725 } 726 727 std::unique_ptr<CommandObjectRegexCommand> 728 jump_regex_cmd_ap(new CommandObjectRegexCommand (*this, 729 "_regexp-jump", 730 "Sets the program counter to a new address.", 731 "_regexp-jump [<line>]\n" 732 "_regexp-jump [<+-lineoffset>]\n" 733 "_regexp-jump [<file>:<line>]\n" 734 "_regexp-jump [*<addr>]\n", 735 2, 736 0, 737 false)); 738 if (jump_regex_cmd_ap.get()) 739 { 740 if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") && 741 jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") && 742 jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") && 743 jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1")) 744 { 745 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release()); 746 m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp; 747 } 748 } 749 750 } 751 752 int 753 CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, 754 StringList &matches) 755 { 756 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); 757 758 if (include_aliases) 759 { 760 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); 761 } 762 763 return matches.GetSize(); 764 } 765 766 CommandObjectSP 767 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) 768 { 769 CommandObject::CommandMap::iterator pos; 770 CommandObjectSP command_sp; 771 772 std::string cmd(cmd_cstr); 773 774 if (HasCommands()) 775 { 776 pos = m_command_dict.find(cmd); 777 if (pos != m_command_dict.end()) 778 command_sp = pos->second; 779 } 780 781 if (include_aliases && HasAliases()) 782 { 783 pos = m_alias_dict.find(cmd); 784 if (pos != m_alias_dict.end()) 785 command_sp = pos->second; 786 } 787 788 if (HasUserCommands()) 789 { 790 pos = m_user_dict.find(cmd); 791 if (pos != m_user_dict.end()) 792 command_sp = pos->second; 793 } 794 795 if (!exact && !command_sp) 796 { 797 // We will only get into here if we didn't find any exact matches. 798 799 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; 800 801 StringList local_matches; 802 if (matches == nullptr) 803 matches = &local_matches; 804 805 unsigned int num_cmd_matches = 0; 806 unsigned int num_alias_matches = 0; 807 unsigned int num_user_matches = 0; 808 809 // Look through the command dictionaries one by one, and if we get only one match from any of 810 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. 811 812 if (HasCommands()) 813 { 814 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); 815 } 816 817 if (num_cmd_matches == 1) 818 { 819 cmd.assign(matches->GetStringAtIndex(0)); 820 pos = m_command_dict.find(cmd); 821 if (pos != m_command_dict.end()) 822 real_match_sp = pos->second; 823 } 824 825 if (include_aliases && HasAliases()) 826 { 827 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); 828 829 } 830 831 if (num_alias_matches == 1) 832 { 833 cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); 834 pos = m_alias_dict.find(cmd); 835 if (pos != m_alias_dict.end()) 836 alias_match_sp = pos->second; 837 } 838 839 if (HasUserCommands()) 840 { 841 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); 842 } 843 844 if (num_user_matches == 1) 845 { 846 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); 847 848 pos = m_user_dict.find (cmd); 849 if (pos != m_user_dict.end()) 850 user_match_sp = pos->second; 851 } 852 853 // If we got exactly one match, return that, otherwise return the match list. 854 855 if (num_user_matches + num_cmd_matches + num_alias_matches == 1) 856 { 857 if (num_cmd_matches) 858 return real_match_sp; 859 else if (num_alias_matches) 860 return alias_match_sp; 861 else 862 return user_match_sp; 863 } 864 } 865 else if (matches && command_sp) 866 { 867 matches->AppendString (cmd_cstr); 868 } 869 870 871 return command_sp; 872 } 873 874 bool 875 CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) 876 { 877 if (name && name[0]) 878 { 879 std::string name_sstr(name); 880 bool found = (m_command_dict.find (name_sstr) != m_command_dict.end()); 881 if (found && !can_replace) 882 return false; 883 if (found && m_command_dict[name_sstr]->IsRemovable() == false) 884 return false; 885 m_command_dict[name_sstr] = cmd_sp; 886 return true; 887 } 888 return false; 889 } 890 891 bool 892 CommandInterpreter::AddUserCommand (std::string name, 893 const lldb::CommandObjectSP &cmd_sp, 894 bool can_replace) 895 { 896 if (!name.empty()) 897 { 898 899 const char* name_cstr = name.c_str(); 900 901 // do not allow replacement of internal commands 902 if (CommandExists(name_cstr)) 903 { 904 if (can_replace == false) 905 return false; 906 if (m_command_dict[name]->IsRemovable() == false) 907 return false; 908 } 909 910 if (UserCommandExists(name_cstr)) 911 { 912 if (can_replace == false) 913 return false; 914 if (m_user_dict[name]->IsRemovable() == false) 915 return false; 916 } 917 918 m_user_dict[name] = cmd_sp; 919 return true; 920 } 921 return false; 922 } 923 924 CommandObjectSP 925 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) 926 { 927 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command. 928 CommandObjectSP ret_val; // Possibly empty return value. 929 930 if (cmd_cstr == nullptr) 931 return ret_val; 932 933 if (cmd_words.GetArgumentCount() == 1) 934 return GetCommandSP(cmd_cstr, include_aliases, true, nullptr); 935 else 936 { 937 // We have a multi-word command (seemingly), so we need to do more work. 938 // First, get the cmd_obj_sp for the first word in the command. 939 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr); 940 if (cmd_obj_sp.get() != nullptr) 941 { 942 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a 943 // command name), and find the appropriate sub-command SP for each command word.... 944 size_t end = cmd_words.GetArgumentCount(); 945 for (size_t j= 1; j < end; ++j) 946 { 947 if (cmd_obj_sp->IsMultiwordObject()) 948 { 949 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); 950 if (cmd_obj_sp.get() == nullptr) 951 // The sub-command name was invalid. Fail and return the empty 'ret_val'. 952 return ret_val; 953 } 954 else 955 // We have more words in the command name, but we don't have a multiword object. Fail and return 956 // empty 'ret_val'. 957 return ret_val; 958 } 959 // We successfully looped through all the command words and got valid command objects for them. Assign the 960 // last object retrieved to 'ret_val'. 961 ret_val = cmd_obj_sp; 962 } 963 } 964 return ret_val; 965 } 966 967 CommandObject * 968 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) 969 { 970 return GetCommandSPExact (cmd_cstr, include_aliases).get(); 971 } 972 973 CommandObject * 974 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) 975 { 976 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); 977 978 // If we didn't find an exact match to the command string in the commands, look in 979 // the aliases. 980 981 if (command_obj) 982 return command_obj; 983 984 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); 985 986 if (command_obj) 987 return command_obj; 988 989 // If there wasn't an exact match then look for an inexact one in just the commands 990 command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get(); 991 992 // Finally, if there wasn't an inexact match among the commands, look for an inexact 993 // match in both the commands and aliases. 994 995 if (command_obj) 996 { 997 if (matches) 998 matches->AppendString(command_obj->GetCommandName()); 999 return command_obj; 1000 } 1001 1002 return GetCommandSP(cmd_cstr, true, false, matches).get(); 1003 } 1004 1005 bool 1006 CommandInterpreter::CommandExists (const char *cmd) 1007 { 1008 return m_command_dict.find(cmd) != m_command_dict.end(); 1009 } 1010 1011 bool 1012 CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, 1013 const char *options_args, 1014 OptionArgVectorSP &option_arg_vector_sp) 1015 { 1016 bool success = true; 1017 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 1018 1019 if (!options_args || (strlen (options_args) < 1)) 1020 return true; 1021 1022 std::string options_string (options_args); 1023 Args args (options_args); 1024 CommandReturnObject result; 1025 // Check to see if the command being aliased can take any command options. 1026 Options *options = cmd_obj_sp->GetOptions (); 1027 if (options) 1028 { 1029 // See if any options were specified as part of the alias; if so, handle them appropriately. 1030 options->NotifyOptionParsingStarting (); 1031 args.Unshift ("dummy_arg"); 1032 args.ParseAliasOptions (*options, result, option_arg_vector, options_string); 1033 args.Shift (); 1034 if (result.Succeeded()) 1035 options->VerifyPartialOptions (result); 1036 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 1037 { 1038 result.AppendError ("Unable to create requested alias.\n"); 1039 return false; 1040 } 1041 } 1042 1043 if (!options_string.empty()) 1044 { 1045 if (cmd_obj_sp->WantsRawCommandString ()) 1046 option_arg_vector->push_back (OptionArgPair ("<argument>", 1047 OptionArgValue (-1, 1048 options_string))); 1049 else 1050 { 1051 const size_t argc = args.GetArgumentCount(); 1052 for (size_t i = 0; i < argc; ++i) 1053 if (strcmp (args.GetArgumentAtIndex (i), "") != 0) 1054 option_arg_vector->push_back 1055 (OptionArgPair ("<argument>", 1056 OptionArgValue (-1, 1057 std::string (args.GetArgumentAtIndex (i))))); 1058 } 1059 } 1060 1061 return success; 1062 } 1063 1064 bool 1065 CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name) 1066 { 1067 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); 1068 if (exact_match) 1069 { 1070 full_name.assign(cmd); 1071 return exact_match; 1072 } 1073 else 1074 { 1075 StringList matches; 1076 size_t num_alias_matches; 1077 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches); 1078 if (num_alias_matches == 1) 1079 { 1080 // Make sure this isn't shadowing a command in the regular command space: 1081 StringList regular_matches; 1082 const bool include_aliases = false; 1083 const bool exact = false; 1084 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches)); 1085 if (cmd_obj_sp || regular_matches.GetSize() > 0) 1086 return false; 1087 else 1088 { 1089 full_name.assign (matches.GetStringAtIndex(0)); 1090 return true; 1091 } 1092 } 1093 else 1094 return false; 1095 } 1096 } 1097 1098 bool 1099 CommandInterpreter::AliasExists (const char *cmd) 1100 { 1101 return m_alias_dict.find(cmd) != m_alias_dict.end(); 1102 } 1103 1104 bool 1105 CommandInterpreter::UserCommandExists (const char *cmd) 1106 { 1107 return m_user_dict.find(cmd) != m_user_dict.end(); 1108 } 1109 1110 void 1111 CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp) 1112 { 1113 command_obj_sp->SetIsAlias (true); 1114 m_alias_dict[alias_name] = command_obj_sp; 1115 } 1116 1117 bool 1118 CommandInterpreter::RemoveAlias (const char *alias_name) 1119 { 1120 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name); 1121 if (pos != m_alias_dict.end()) 1122 { 1123 m_alias_dict.erase(pos); 1124 return true; 1125 } 1126 return false; 1127 } 1128 1129 bool 1130 CommandInterpreter::RemoveCommand (const char *cmd) 1131 { 1132 auto pos = m_command_dict.find(cmd); 1133 if (pos != m_command_dict.end()) 1134 { 1135 if (pos->second->IsRemovable()) 1136 { 1137 // Only regular expression objects or python commands are removable 1138 m_command_dict.erase(pos); 1139 return true; 1140 } 1141 } 1142 return false; 1143 } 1144 bool 1145 CommandInterpreter::RemoveUser (const char *alias_name) 1146 { 1147 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); 1148 if (pos != m_user_dict.end()) 1149 { 1150 m_user_dict.erase(pos); 1151 return true; 1152 } 1153 return false; 1154 } 1155 1156 void 1157 CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string) 1158 { 1159 help_string.Printf ("'%s", command_name); 1160 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1161 1162 if (option_arg_vector_sp) 1163 { 1164 OptionArgVector *options = option_arg_vector_sp.get(); 1165 for (size_t i = 0; i < options->size(); ++i) 1166 { 1167 OptionArgPair cur_option = (*options)[i]; 1168 std::string opt = cur_option.first; 1169 OptionArgValue value_pair = cur_option.second; 1170 std::string value = value_pair.second; 1171 if (opt.compare("<argument>") == 0) 1172 { 1173 help_string.Printf (" %s", value.c_str()); 1174 } 1175 else 1176 { 1177 help_string.Printf (" %s", opt.c_str()); 1178 if ((value.compare ("<no-argument>") != 0) 1179 && (value.compare ("<need-argument") != 0)) 1180 { 1181 help_string.Printf (" %s", value.c_str()); 1182 } 1183 } 1184 } 1185 } 1186 1187 help_string.Printf ("'"); 1188 } 1189 1190 size_t 1191 CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict) 1192 { 1193 CommandObject::CommandMap::const_iterator pos; 1194 CommandObject::CommandMap::const_iterator end = dict.end(); 1195 size_t max_len = 0; 1196 1197 for (pos = dict.begin(); pos != end; ++pos) 1198 { 1199 size_t len = pos->first.size(); 1200 if (max_len < len) 1201 max_len = len; 1202 } 1203 return max_len; 1204 } 1205 1206 void 1207 CommandInterpreter::GetHelp (CommandReturnObject &result, 1208 uint32_t cmd_types) 1209 { 1210 const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue(); 1211 if (help_prologue != NULL) 1212 { 1213 OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue); 1214 } 1215 1216 CommandObject::CommandMap::const_iterator pos; 1217 size_t max_len = FindLongestCommandWord (m_command_dict); 1218 1219 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) 1220 { 1221 result.AppendMessage("Debugger commands:"); 1222 result.AppendMessage(""); 1223 1224 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 1225 { 1226 if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0)) 1227 continue; 1228 1229 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1230 max_len); 1231 } 1232 result.AppendMessage(""); 1233 1234 } 1235 1236 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) 1237 { 1238 result.AppendMessageWithFormat("Current command abbreviations " 1239 "(type '%shelp command alias' for more info):\n", 1240 GetCommandPrefix()); 1241 result.AppendMessage(""); 1242 max_len = FindLongestCommandWord (m_alias_dict); 1243 1244 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos) 1245 { 1246 StreamString sstr; 1247 StreamString translation_and_help; 1248 std::string entry_name = pos->first; 1249 std::string second_entry = pos->second.get()->GetCommandName(); 1250 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr); 1251 1252 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp()); 1253 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 1254 translation_and_help.GetData(), max_len); 1255 } 1256 result.AppendMessage(""); 1257 } 1258 1259 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) 1260 { 1261 result.AppendMessage ("Current user-defined commands:"); 1262 result.AppendMessage(""); 1263 max_len = FindLongestCommandWord (m_user_dict); 1264 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 1265 { 1266 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1267 max_len); 1268 } 1269 result.AppendMessage(""); 1270 } 1271 1272 result.AppendMessageWithFormat("For more information on any command, type '%shelp <command-name>'.\n", 1273 GetCommandPrefix()); 1274 } 1275 1276 CommandObject * 1277 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) 1278 { 1279 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will 1280 // eventually be invoked by the given command line. 1281 1282 CommandObject *cmd_obj = nullptr; 1283 size_t start = command_string.find_first_not_of (k_white_space); 1284 size_t end = 0; 1285 bool done = false; 1286 while (!done) 1287 { 1288 if (start != std::string::npos) 1289 { 1290 // Get the next word from command_string. 1291 end = command_string.find_first_of (k_white_space, start); 1292 if (end == std::string::npos) 1293 end = command_string.size(); 1294 std::string cmd_word = command_string.substr (start, end - start); 1295 1296 if (cmd_obj == nullptr) 1297 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid 1298 // command or alias. 1299 cmd_obj = GetCommandObject (cmd_word.c_str()); 1300 else if (cmd_obj->IsMultiwordObject ()) 1301 { 1302 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object. 1303 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str()); 1304 if (sub_cmd_obj) 1305 cmd_obj = sub_cmd_obj; 1306 else // cmd_word was not a valid sub-command word, so we are done 1307 done = true; 1308 } 1309 else 1310 // We have a cmd_obj and it is not a multi-word object, so we are done. 1311 done = true; 1312 1313 // If we didn't find a valid command object, or our command object is not a multi-word object, or 1314 // we are at the end of the command_string, then we are done. Otherwise, find the start of the 1315 // next word. 1316 1317 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) 1318 done = true; 1319 else 1320 start = command_string.find_first_not_of (k_white_space, end); 1321 } 1322 else 1323 // Unable to find any more words. 1324 done = true; 1325 } 1326 1327 if (end == command_string.size()) 1328 command_string.clear(); 1329 else 1330 command_string = command_string.substr(end); 1331 1332 return cmd_obj; 1333 } 1334 1335 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; 1336 static void 1337 StripLeadingSpaces (std::string &s) 1338 { 1339 if (!s.empty()) 1340 { 1341 size_t pos = s.find_first_not_of (k_white_space); 1342 if (pos == std::string::npos) 1343 s.clear(); 1344 else if (pos == 0) 1345 return; 1346 s.erase (0, pos); 1347 } 1348 } 1349 1350 static size_t 1351 FindArgumentTerminator (const std::string &s) 1352 { 1353 const size_t s_len = s.size(); 1354 size_t offset = 0; 1355 while (offset < s_len) 1356 { 1357 size_t pos = s.find ("--", offset); 1358 if (pos == std::string::npos) 1359 break; 1360 if (pos > 0) 1361 { 1362 if (isspace(s[pos-1])) 1363 { 1364 // Check if the string ends "\s--" (where \s is a space character) 1365 // or if we have "\s--\s". 1366 if ((pos + 2 >= s_len) || isspace(s[pos+2])) 1367 { 1368 return pos; 1369 } 1370 } 1371 } 1372 offset = pos + 2; 1373 } 1374 return std::string::npos; 1375 } 1376 1377 static bool 1378 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char) 1379 { 1380 command.clear(); 1381 suffix.clear(); 1382 StripLeadingSpaces (command_string); 1383 1384 bool result = false; 1385 quote_char = '\0'; 1386 1387 if (!command_string.empty()) 1388 { 1389 const char first_char = command_string[0]; 1390 if (first_char == '\'' || first_char == '"') 1391 { 1392 quote_char = first_char; 1393 const size_t end_quote_pos = command_string.find (quote_char, 1); 1394 if (end_quote_pos == std::string::npos) 1395 { 1396 command.swap (command_string); 1397 command_string.erase (); 1398 } 1399 else 1400 { 1401 command.assign (command_string, 1, end_quote_pos - 1); 1402 if (end_quote_pos + 1 < command_string.size()) 1403 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1)); 1404 else 1405 command_string.erase (); 1406 } 1407 } 1408 else 1409 { 1410 const size_t first_space_pos = command_string.find_first_of (k_white_space); 1411 if (first_space_pos == std::string::npos) 1412 { 1413 command.swap (command_string); 1414 command_string.erase(); 1415 } 1416 else 1417 { 1418 command.assign (command_string, 0, first_space_pos); 1419 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos)); 1420 } 1421 } 1422 result = true; 1423 } 1424 1425 1426 if (!command.empty()) 1427 { 1428 // actual commands can't start with '-' or '_' 1429 if (command[0] != '-' && command[0] != '_') 1430 { 1431 size_t pos = command.find_first_not_of(k_valid_command_chars); 1432 if (pos > 0 && pos != std::string::npos) 1433 { 1434 suffix.assign (command.begin() + pos, command.end()); 1435 command.erase (pos); 1436 } 1437 } 1438 } 1439 1440 return result; 1441 } 1442 1443 CommandObject * 1444 CommandInterpreter::BuildAliasResult (const char *alias_name, 1445 std::string &raw_input_string, 1446 std::string &alias_result, 1447 CommandReturnObject &result) 1448 { 1449 CommandObject *alias_cmd_obj = nullptr; 1450 Args cmd_args (raw_input_string); 1451 alias_cmd_obj = GetCommandObject (alias_name); 1452 StreamString result_str; 1453 1454 if (alias_cmd_obj) 1455 { 1456 std::string alias_name_str = alias_name; 1457 if ((cmd_args.GetArgumentCount() == 0) 1458 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) 1459 cmd_args.Unshift (alias_name); 1460 1461 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); 1462 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1463 1464 if (option_arg_vector_sp.get()) 1465 { 1466 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 1467 1468 for (size_t i = 0; i < option_arg_vector->size(); ++i) 1469 { 1470 OptionArgPair option_pair = (*option_arg_vector)[i]; 1471 OptionArgValue value_pair = option_pair.second; 1472 int value_type = value_pair.first; 1473 std::string option = option_pair.first; 1474 std::string value = value_pair.second; 1475 if (option.compare ("<argument>") == 0) 1476 result_str.Printf (" %s", value.c_str()); 1477 else 1478 { 1479 result_str.Printf (" %s", option.c_str()); 1480 if (value_type != OptionParser::eNoArgument) 1481 { 1482 if (value_type != OptionParser::eOptionalArgument) 1483 result_str.Printf (" "); 1484 int index = GetOptionArgumentPosition (value.c_str()); 1485 if (index == 0) 1486 result_str.Printf ("%s", value.c_str()); 1487 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) 1488 { 1489 1490 result.AppendErrorWithFormat 1491 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 1492 index); 1493 result.SetStatus (eReturnStatusFailed); 1494 return nullptr; 1495 } 1496 else 1497 { 1498 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 1499 if (strpos != std::string::npos) 1500 raw_input_string = raw_input_string.erase (strpos, 1501 strlen (cmd_args.GetArgumentAtIndex (index))); 1502 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index)); 1503 } 1504 } 1505 } 1506 } 1507 } 1508 1509 alias_result = result_str.GetData(); 1510 } 1511 return alias_cmd_obj; 1512 } 1513 1514 Error 1515 CommandInterpreter::PreprocessCommand (std::string &command) 1516 { 1517 // The command preprocessor needs to do things to the command 1518 // line before any parsing of arguments or anything else is done. 1519 // The only current stuff that gets preprocessed is anything enclosed 1520 // in backtick ('`') characters is evaluated as an expression and 1521 // the result of the expression must be a scalar that can be substituted 1522 // into the command. An example would be: 1523 // (lldb) memory read `$rsp + 20` 1524 Error error; // Error for any expressions that might not evaluate 1525 size_t start_backtick; 1526 size_t pos = 0; 1527 while ((start_backtick = command.find ('`', pos)) != std::string::npos) 1528 { 1529 if (start_backtick > 0 && command[start_backtick-1] == '\\') 1530 { 1531 // The backtick was preceded by a '\' character, remove the slash 1532 // and don't treat the backtick as the start of an expression 1533 command.erase(start_backtick-1, 1); 1534 // No need to add one to start_backtick since we just deleted a char 1535 pos = start_backtick; 1536 } 1537 else 1538 { 1539 const size_t expr_content_start = start_backtick + 1; 1540 const size_t end_backtick = command.find ('`', expr_content_start); 1541 if (end_backtick == std::string::npos) 1542 return error; 1543 else if (end_backtick == expr_content_start) 1544 { 1545 // Empty expression (two backticks in a row) 1546 command.erase (start_backtick, 2); 1547 } 1548 else 1549 { 1550 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start); 1551 1552 ExecutionContext exe_ctx(GetExecutionContext()); 1553 Target *target = exe_ctx.GetTargetPtr(); 1554 // Get a dummy target to allow for calculator mode while processing backticks. 1555 // This also helps break the infinite loop caused when target is null. 1556 if (!target) 1557 target = m_debugger.GetDummyTarget(); 1558 if (target) 1559 { 1560 ValueObjectSP expr_result_valobj_sp; 1561 1562 EvaluateExpressionOptions options; 1563 options.SetCoerceToId(false); 1564 options.SetUnwindOnError(true); 1565 options.SetIgnoreBreakpoints(true); 1566 options.SetKeepInMemory(false); 1567 options.SetTryAllThreads(true); 1568 options.SetTimeoutUsec(0); 1569 1570 ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1571 exe_ctx.GetFramePtr(), 1572 expr_result_valobj_sp, 1573 options); 1574 1575 if (expr_result == eExpressionCompleted) 1576 { 1577 Scalar scalar; 1578 if (expr_result_valobj_sp) 1579 expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true); 1580 if (expr_result_valobj_sp->ResolveValue (scalar)) 1581 { 1582 command.erase (start_backtick, end_backtick - start_backtick + 1); 1583 StreamString value_strm; 1584 const bool show_type = false; 1585 scalar.GetValue (&value_strm, show_type); 1586 size_t value_string_size = value_strm.GetSize(); 1587 if (value_string_size) 1588 { 1589 command.insert (start_backtick, value_strm.GetData(), value_string_size); 1590 pos = start_backtick + value_string_size; 1591 continue; 1592 } 1593 else 1594 { 1595 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1596 } 1597 } 1598 else 1599 { 1600 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1601 } 1602 } 1603 else 1604 { 1605 if (expr_result_valobj_sp) 1606 error = expr_result_valobj_sp->GetError(); 1607 if (error.Success()) 1608 { 1609 1610 switch (expr_result) 1611 { 1612 case eExpressionSetupError: 1613 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str()); 1614 break; 1615 case eExpressionParseError: 1616 error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str()); 1617 break; 1618 case eExpressionResultUnavailable: 1619 error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str()); 1620 case eExpressionCompleted: 1621 break; 1622 case eExpressionDiscarded: 1623 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str()); 1624 break; 1625 case eExpressionInterrupted: 1626 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str()); 1627 break; 1628 case eExpressionHitBreakpoint: 1629 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str()); 1630 break; 1631 case eExpressionTimedOut: 1632 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str()); 1633 break; 1634 case eExpressionStoppedForDebug: 1635 error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str()); 1636 break; 1637 } 1638 } 1639 } 1640 } 1641 } 1642 if (error.Fail()) 1643 break; 1644 } 1645 } 1646 return error; 1647 } 1648 1649 1650 bool 1651 CommandInterpreter::HandleCommand (const char *command_line, 1652 LazyBool lazy_add_to_history, 1653 CommandReturnObject &result, 1654 ExecutionContext *override_context, 1655 bool repeat_on_empty_command, 1656 bool no_context_switching) 1657 1658 { 1659 1660 std::string command_string (command_line); 1661 std::string original_command_string (command_line); 1662 1663 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); 1664 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); 1665 1666 // Make a scoped cleanup object that will clear the crash description string 1667 // on exit of this function. 1668 lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription); 1669 1670 if (log) 1671 log->Printf ("Processing command: %s", command_line); 1672 1673 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line); 1674 1675 if (!no_context_switching) 1676 UpdateExecutionContext (override_context); 1677 1678 bool add_to_history; 1679 if (lazy_add_to_history == eLazyBoolCalculate) 1680 add_to_history = (m_command_source_depth == 0); 1681 else 1682 add_to_history = (lazy_add_to_history == eLazyBoolYes); 1683 1684 bool empty_command = false; 1685 bool comment_command = false; 1686 if (command_string.empty()) 1687 empty_command = true; 1688 else 1689 { 1690 const char *k_space_characters = "\t\n\v\f\r "; 1691 1692 size_t non_space = command_string.find_first_not_of (k_space_characters); 1693 // Check for empty line or comment line (lines whose first 1694 // non-space character is the comment character for this interpreter) 1695 if (non_space == std::string::npos) 1696 empty_command = true; 1697 else if (command_string[non_space] == m_comment_char) 1698 comment_command = true; 1699 else if (command_string[non_space] == CommandHistory::g_repeat_char) 1700 { 1701 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space); 1702 if (history_string == nullptr) 1703 { 1704 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); 1705 result.SetStatus(eReturnStatusFailed); 1706 return false; 1707 } 1708 add_to_history = false; 1709 command_string = history_string; 1710 original_command_string = history_string; 1711 } 1712 } 1713 1714 if (empty_command) 1715 { 1716 if (repeat_on_empty_command) 1717 { 1718 if (m_command_history.IsEmpty()) 1719 { 1720 result.AppendError ("empty command"); 1721 result.SetStatus(eReturnStatusFailed); 1722 return false; 1723 } 1724 else 1725 { 1726 command_line = m_repeat_command.c_str(); 1727 command_string = command_line; 1728 original_command_string = command_line; 1729 if (m_repeat_command.empty()) 1730 { 1731 result.AppendErrorWithFormat("No auto repeat.\n"); 1732 result.SetStatus (eReturnStatusFailed); 1733 return false; 1734 } 1735 } 1736 add_to_history = false; 1737 } 1738 else 1739 { 1740 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1741 return true; 1742 } 1743 } 1744 else if (comment_command) 1745 { 1746 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1747 return true; 1748 } 1749 1750 1751 Error error (PreprocessCommand (command_string)); 1752 1753 if (error.Fail()) 1754 { 1755 result.AppendError (error.AsCString()); 1756 result.SetStatus(eReturnStatusFailed); 1757 return false; 1758 } 1759 1760 // Phase 1. 1761 1762 // Before we do ANY kind of argument processing, we need to figure out what 1763 // the real/final command object is for the specified command. This gets 1764 // complicated by the fact that the user could have specified an alias, and, 1765 // in translating the alias, there may also be command options and/or even 1766 // data (including raw text strings) that need to be found and inserted into 1767 // the command line as part of the translation. So this first step is plain 1768 // look-up and replacement, resulting in: 1769 // 1. the command object whose Execute method will actually be called 1770 // 2. a revised command string, with all substitutions and replacements 1771 // taken care of 1772 // From 1 above, we can determine whether the Execute function wants raw 1773 // input or not. 1774 1775 CommandObject *cmd_obj = ResolveCommandImpl(command_string, result); 1776 1777 // Although the user may have abbreviated the command, the command_string now 1778 // has the command expanded to the full name. For example, if the input 1779 // was "br s -n main", command_string is now "breakpoint set -n main". 1780 1781 if (log) 1782 { 1783 log->Printf("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); 1784 log->Printf("HandleCommand, (revised) command_string: '%s'", command_string.c_str()); 1785 const bool wants_raw_input = (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false; 1786 log->Printf("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); 1787 } 1788 1789 // Phase 2. 1790 // Take care of things like setting up the history command & calling the appropriate Execute method on the 1791 // CommandObject, with the appropriate arguments. 1792 1793 if (cmd_obj != nullptr) 1794 { 1795 if (add_to_history) 1796 { 1797 Args command_args (command_string); 1798 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); 1799 if (repeat_command != nullptr) 1800 m_repeat_command.assign(repeat_command); 1801 else 1802 m_repeat_command.assign(original_command_string.c_str()); 1803 1804 m_command_history.AppendString (original_command_string); 1805 } 1806 1807 std::string remainder; 1808 const std::size_t actual_cmd_name_len = strlen (cmd_obj->GetCommandName()); 1809 if (actual_cmd_name_len < command_string.length()) 1810 remainder = command_string.substr (actual_cmd_name_len); 1811 1812 // Remove any initial spaces 1813 size_t pos = remainder.find_first_not_of (k_white_space); 1814 if (pos != 0 && pos != std::string::npos) 1815 remainder.erase(0, pos); 1816 1817 if (log) 1818 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str()); 1819 1820 cmd_obj->Execute (remainder.c_str(), result); 1821 } 1822 else 1823 { 1824 // We didn't find the first command object, so complete the first argument. 1825 Args command_args (command_string); 1826 StringList matches; 1827 int num_matches; 1828 int cursor_index = 0; 1829 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); 1830 bool word_complete; 1831 num_matches = HandleCompletionMatches (command_args, 1832 cursor_index, 1833 cursor_char_position, 1834 0, 1835 -1, 1836 word_complete, 1837 matches); 1838 1839 if (num_matches > 0) 1840 { 1841 std::string error_msg; 1842 error_msg.assign ("ambiguous command '"); 1843 error_msg.append(command_args.GetArgumentAtIndex(0)); 1844 error_msg.append ("'."); 1845 1846 error_msg.append (" Possible completions:"); 1847 for (int i = 0; i < num_matches; i++) 1848 { 1849 error_msg.append ("\n\t"); 1850 error_msg.append (matches.GetStringAtIndex (i)); 1851 } 1852 error_msg.append ("\n"); 1853 result.AppendRawError (error_msg.c_str()); 1854 } 1855 else 1856 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0)); 1857 1858 result.SetStatus (eReturnStatusFailed); 1859 } 1860 1861 if (log) 1862 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed")); 1863 1864 return result.Succeeded(); 1865 } 1866 1867 int 1868 CommandInterpreter::HandleCompletionMatches (Args &parsed_line, 1869 int &cursor_index, 1870 int &cursor_char_position, 1871 int match_start_point, 1872 int max_return_elements, 1873 bool &word_complete, 1874 StringList &matches) 1875 { 1876 int num_command_matches = 0; 1877 bool look_for_subcommand = false; 1878 1879 // For any of the command completions a unique match will be a complete word. 1880 word_complete = true; 1881 1882 if (cursor_index == -1) 1883 { 1884 // We got nothing on the command line, so return the list of commands 1885 bool include_aliases = true; 1886 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches); 1887 } 1888 else if (cursor_index == 0) 1889 { 1890 // The cursor is in the first argument, so just do a lookup in the dictionary. 1891 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches); 1892 num_command_matches = matches.GetSize(); 1893 1894 if (num_command_matches == 1 1895 && cmd_obj && cmd_obj->IsMultiwordObject() 1896 && matches.GetStringAtIndex(0) != nullptr 1897 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 1898 { 1899 if (parsed_line.GetArgumentCount() == 1) 1900 { 1901 word_complete = true; 1902 } 1903 else 1904 { 1905 look_for_subcommand = true; 1906 num_command_matches = 0; 1907 matches.DeleteStringAtIndex(0); 1908 parsed_line.AppendArgument (""); 1909 cursor_index++; 1910 cursor_char_position = 0; 1911 } 1912 } 1913 } 1914 1915 if (cursor_index > 0 || look_for_subcommand) 1916 { 1917 // We are completing further on into a commands arguments, so find the command and tell it 1918 // to complete the command. 1919 // First see if there is a matching initial command: 1920 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); 1921 if (command_object == nullptr) 1922 { 1923 return 0; 1924 } 1925 else 1926 { 1927 parsed_line.Shift(); 1928 cursor_index--; 1929 num_command_matches = command_object->HandleCompletion (parsed_line, 1930 cursor_index, 1931 cursor_char_position, 1932 match_start_point, 1933 max_return_elements, 1934 word_complete, 1935 matches); 1936 } 1937 } 1938 1939 return num_command_matches; 1940 1941 } 1942 1943 int 1944 CommandInterpreter::HandleCompletion (const char *current_line, 1945 const char *cursor, 1946 const char *last_char, 1947 int match_start_point, 1948 int max_return_elements, 1949 StringList &matches) 1950 { 1951 // We parse the argument up to the cursor, so the last argument in parsed_line is 1952 // the one containing the cursor, and the cursor is after the last character. 1953 1954 Args parsed_line(llvm::StringRef(current_line, last_char - current_line)); 1955 Args partial_parsed_line(llvm::StringRef(current_line, cursor - current_line)); 1956 1957 // Don't complete comments, and if the line we are completing is just the history repeat character, 1958 // substitute the appropriate history line. 1959 const char *first_arg = parsed_line.GetArgumentAtIndex(0); 1960 if (first_arg) 1961 { 1962 if (first_arg[0] == m_comment_char) 1963 return 0; 1964 else if (first_arg[0] == CommandHistory::g_repeat_char) 1965 { 1966 const char *history_string = m_command_history.FindString (first_arg); 1967 if (history_string != nullptr) 1968 { 1969 matches.Clear(); 1970 matches.InsertStringAtIndex(0, history_string); 1971 return -2; 1972 } 1973 else 1974 return 0; 1975 1976 } 1977 } 1978 1979 1980 int num_args = partial_parsed_line.GetArgumentCount(); 1981 int cursor_index = partial_parsed_line.GetArgumentCount() - 1; 1982 int cursor_char_position; 1983 1984 if (cursor_index == -1) 1985 cursor_char_position = 0; 1986 else 1987 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index)); 1988 1989 if (cursor > current_line && cursor[-1] == ' ') 1990 { 1991 // We are just after a space. If we are in an argument, then we will continue 1992 // parsing, but if we are between arguments, then we have to complete whatever the next 1993 // element would be. 1994 // We can distinguish the two cases because if we are in an argument (e.g. because the space is 1995 // protected by a quote) then the space will also be in the parsed argument... 1996 1997 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index); 1998 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ') 1999 { 2000 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0'); 2001 cursor_index++; 2002 cursor_char_position = 0; 2003 } 2004 } 2005 2006 int num_command_matches; 2007 2008 matches.Clear(); 2009 2010 // Only max_return_elements == -1 is supported at present: 2011 assert (max_return_elements == -1); 2012 bool word_complete; 2013 num_command_matches = HandleCompletionMatches (parsed_line, 2014 cursor_index, 2015 cursor_char_position, 2016 match_start_point, 2017 max_return_elements, 2018 word_complete, 2019 matches); 2020 2021 if (num_command_matches <= 0) 2022 return num_command_matches; 2023 2024 if (num_args == 0) 2025 { 2026 // If we got an empty string, insert nothing. 2027 matches.InsertStringAtIndex(0, ""); 2028 } 2029 else 2030 { 2031 // Now figure out if there is a common substring, and if so put that in element 0, otherwise 2032 // put an empty string in element 0. 2033 std::string command_partial_str; 2034 if (cursor_index >= 0) 2035 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), 2036 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position); 2037 2038 std::string common_prefix; 2039 matches.LongestCommonPrefix (common_prefix); 2040 const size_t partial_name_len = command_partial_str.size(); 2041 common_prefix.erase (0, partial_name_len); 2042 2043 // If we matched a unique single command, add a space... 2044 // Only do this if the completer told us this was a complete word, however... 2045 if (num_command_matches == 1 && word_complete) 2046 { 2047 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); 2048 common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char); 2049 if (quote_char != '\0') 2050 common_prefix.push_back(quote_char); 2051 common_prefix.push_back(' '); 2052 } 2053 matches.InsertStringAtIndex(0, common_prefix.c_str()); 2054 } 2055 return num_command_matches; 2056 } 2057 2058 2059 CommandInterpreter::~CommandInterpreter () 2060 { 2061 } 2062 2063 void 2064 CommandInterpreter::UpdatePrompt (const char *new_prompt) 2065 { 2066 EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; 2067 BroadcastEvent (prompt_change_event_sp); 2068 if (m_command_io_handler_sp) 2069 m_command_io_handler_sp->SetPrompt(new_prompt); 2070 } 2071 2072 2073 bool 2074 CommandInterpreter::Confirm (const char *message, bool default_answer) 2075 { 2076 // Check AutoConfirm first: 2077 if (m_debugger.GetAutoConfirm()) 2078 return default_answer; 2079 2080 IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger, 2081 message, 2082 default_answer); 2083 IOHandlerSP io_handler_sp (confirm); 2084 m_debugger.RunIOHandler (io_handler_sp); 2085 return confirm->GetResponse(); 2086 } 2087 2088 OptionArgVectorSP 2089 CommandInterpreter::GetAliasOptions (const char *alias_name) 2090 { 2091 OptionArgMap::iterator pos; 2092 OptionArgVectorSP ret_val; 2093 2094 std::string alias (alias_name); 2095 2096 if (HasAliasOptions()) 2097 { 2098 pos = m_alias_options.find (alias); 2099 if (pos != m_alias_options.end()) 2100 ret_val = pos->second; 2101 } 2102 2103 return ret_val; 2104 } 2105 2106 void 2107 CommandInterpreter::RemoveAliasOptions (const char *alias_name) 2108 { 2109 OptionArgMap::iterator pos = m_alias_options.find(alias_name); 2110 if (pos != m_alias_options.end()) 2111 { 2112 m_alias_options.erase (pos); 2113 } 2114 } 2115 2116 void 2117 CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp) 2118 { 2119 m_alias_options[alias_name] = option_arg_vector_sp; 2120 } 2121 2122 bool 2123 CommandInterpreter::HasCommands () 2124 { 2125 return (!m_command_dict.empty()); 2126 } 2127 2128 bool 2129 CommandInterpreter::HasAliases () 2130 { 2131 return (!m_alias_dict.empty()); 2132 } 2133 2134 bool 2135 CommandInterpreter::HasUserCommands () 2136 { 2137 return (!m_user_dict.empty()); 2138 } 2139 2140 bool 2141 CommandInterpreter::HasAliasOptions () 2142 { 2143 return (!m_alias_options.empty()); 2144 } 2145 2146 void 2147 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, 2148 const char *alias_name, 2149 Args &cmd_args, 2150 std::string &raw_input_string, 2151 CommandReturnObject &result) 2152 { 2153 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 2154 2155 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); 2156 2157 // Make sure that the alias name is the 0th element in cmd_args 2158 std::string alias_name_str = alias_name; 2159 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) 2160 cmd_args.Unshift (alias_name); 2161 2162 Args new_args (alias_cmd_obj->GetCommandName()); 2163 if (new_args.GetArgumentCount() == 2) 2164 new_args.Shift(); 2165 2166 if (option_arg_vector_sp.get()) 2167 { 2168 if (wants_raw_input) 2169 { 2170 // We have a command that both has command options and takes raw input. Make *sure* it has a 2171 // " -- " in the right place in the raw_input_string. 2172 size_t pos = raw_input_string.find(" -- "); 2173 if (pos == std::string::npos) 2174 { 2175 // None found; assume it goes at the beginning of the raw input string 2176 raw_input_string.insert (0, " -- "); 2177 } 2178 } 2179 2180 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 2181 const size_t old_size = cmd_args.GetArgumentCount(); 2182 std::vector<bool> used (old_size + 1, false); 2183 2184 used[0] = true; 2185 2186 for (size_t i = 0; i < option_arg_vector->size(); ++i) 2187 { 2188 OptionArgPair option_pair = (*option_arg_vector)[i]; 2189 OptionArgValue value_pair = option_pair.second; 2190 int value_type = value_pair.first; 2191 std::string option = option_pair.first; 2192 std::string value = value_pair.second; 2193 if (option.compare ("<argument>") == 0) 2194 { 2195 if (!wants_raw_input 2196 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice 2197 new_args.AppendArgument (value.c_str()); 2198 } 2199 else 2200 { 2201 if (value_type != OptionParser::eOptionalArgument) 2202 new_args.AppendArgument (option.c_str()); 2203 if (value.compare ("<no-argument>") != 0) 2204 { 2205 int index = GetOptionArgumentPosition (value.c_str()); 2206 if (index == 0) 2207 { 2208 // value was NOT a positional argument; must be a real value 2209 if (value_type != OptionParser::eOptionalArgument) 2210 new_args.AppendArgument (value.c_str()); 2211 else 2212 { 2213 char buffer[255]; 2214 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str()); 2215 new_args.AppendArgument (buffer); 2216 } 2217 2218 } 2219 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) 2220 { 2221 result.AppendErrorWithFormat 2222 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 2223 index); 2224 result.SetStatus (eReturnStatusFailed); 2225 return; 2226 } 2227 else 2228 { 2229 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string 2230 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 2231 if (strpos != std::string::npos) 2232 { 2233 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index))); 2234 } 2235 2236 if (value_type != OptionParser::eOptionalArgument) 2237 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); 2238 else 2239 { 2240 char buffer[255]; 2241 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), 2242 cmd_args.GetArgumentAtIndex (index)); 2243 new_args.AppendArgument (buffer); 2244 } 2245 used[index] = true; 2246 } 2247 } 2248 } 2249 } 2250 2251 for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) 2252 { 2253 if (!used[j] && !wants_raw_input) 2254 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); 2255 } 2256 2257 cmd_args.Clear(); 2258 cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); 2259 } 2260 else 2261 { 2262 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2263 // This alias was not created with any options; nothing further needs to be done, unless it is a command that 2264 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw 2265 // input string. 2266 if (wants_raw_input) 2267 { 2268 cmd_args.Clear(); 2269 cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); 2270 } 2271 return; 2272 } 2273 2274 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2275 return; 2276 } 2277 2278 2279 int 2280 CommandInterpreter::GetOptionArgumentPosition (const char *in_string) 2281 { 2282 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position 2283 // of zero. 2284 2285 const char *cptr = in_string; 2286 2287 // Does it start with '%' 2288 if (cptr[0] == '%') 2289 { 2290 ++cptr; 2291 2292 // Is the rest of it entirely digits? 2293 if (isdigit (cptr[0])) 2294 { 2295 const char *start = cptr; 2296 while (isdigit (cptr[0])) 2297 ++cptr; 2298 2299 // We've gotten to the end of the digits; are we at the end of the string? 2300 if (cptr[0] == '\0') 2301 position = atoi (start); 2302 } 2303 } 2304 2305 return position; 2306 } 2307 2308 void 2309 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) 2310 { 2311 FileSpec init_file; 2312 if (in_cwd) 2313 { 2314 // In the current working directory we don't load any program specific 2315 // .lldbinit files, we only look for a "./.lldbinit" file. 2316 if (m_skip_lldbinit_files) 2317 return; 2318 2319 init_file.SetFile ("./.lldbinit", true); 2320 } 2321 else 2322 { 2323 // If we aren't looking in the current working directory we are looking 2324 // in the home directory. We will first see if there is an application 2325 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a 2326 // "-" and the name of the program. If this file doesn't exist, we fall 2327 // back to just the "~/.lldbinit" file. We also obey any requests to not 2328 // load the init files. 2329 llvm::SmallString<64> home_dir_path; 2330 llvm::sys::path::home_directory(home_dir_path); 2331 FileSpec profilePath(home_dir_path.c_str(), false); 2332 profilePath.AppendPathComponent(".lldbinit"); 2333 std::string init_file_path = profilePath.GetPath(); 2334 2335 if (m_skip_app_init_files == false) 2336 { 2337 FileSpec program_file_spec(HostInfo::GetProgramFileSpec()); 2338 const char *program_name = program_file_spec.GetFilename().AsCString(); 2339 2340 if (program_name) 2341 { 2342 char program_init_file_name[PATH_MAX]; 2343 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name); 2344 init_file.SetFile (program_init_file_name, true); 2345 if (!init_file.Exists()) 2346 init_file.Clear(); 2347 } 2348 } 2349 2350 if (!init_file && !m_skip_lldbinit_files) 2351 init_file.SetFile (init_file_path.c_str(), false); 2352 } 2353 2354 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting 2355 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details). 2356 2357 if (init_file.Exists()) 2358 { 2359 const bool saved_batch = SetBatchCommandMode (true); 2360 CommandInterpreterRunOptions options; 2361 options.SetSilent (true); 2362 options.SetStopOnError (false); 2363 options.SetStopOnContinue (true); 2364 2365 HandleCommandsFromFile (init_file, 2366 nullptr, // Execution context 2367 options, 2368 result); 2369 SetBatchCommandMode (saved_batch); 2370 } 2371 else 2372 { 2373 // nothing to be done if the file doesn't exist 2374 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2375 } 2376 } 2377 2378 const char * 2379 CommandInterpreter::GetCommandPrefix() 2380 { 2381 const char * prefix = GetDebugger().GetIOHandlerCommandPrefix(); 2382 return prefix == NULL ? "" : prefix; 2383 } 2384 2385 PlatformSP 2386 CommandInterpreter::GetPlatform (bool prefer_target_platform) 2387 { 2388 PlatformSP platform_sp; 2389 if (prefer_target_platform) 2390 { 2391 ExecutionContext exe_ctx(GetExecutionContext()); 2392 Target *target = exe_ctx.GetTargetPtr(); 2393 if (target) 2394 platform_sp = target->GetPlatform(); 2395 } 2396 2397 if (!platform_sp) 2398 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform(); 2399 return platform_sp; 2400 } 2401 2402 void 2403 CommandInterpreter::HandleCommands (const StringList &commands, 2404 ExecutionContext *override_context, 2405 CommandInterpreterRunOptions &options, 2406 CommandReturnObject &result) 2407 { 2408 size_t num_lines = commands.GetSize(); 2409 2410 // If we are going to continue past a "continue" then we need to run the commands synchronously. 2411 // Make sure you reset this value anywhere you return from the function. 2412 2413 bool old_async_execution = m_debugger.GetAsyncExecution(); 2414 2415 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will 2416 // cause series of commands that change the context, then do an operation that relies on that context to fail. 2417 2418 if (override_context != nullptr) 2419 UpdateExecutionContext (override_context); 2420 2421 if (!options.GetStopOnContinue()) 2422 { 2423 m_debugger.SetAsyncExecution (false); 2424 } 2425 2426 for (size_t idx = 0; idx < num_lines; idx++) 2427 { 2428 const char *cmd = commands.GetStringAtIndex(idx); 2429 if (cmd[0] == '\0') 2430 continue; 2431 2432 if (options.GetEchoCommands()) 2433 { 2434 result.AppendMessageWithFormat ("%s %s\n", 2435 m_debugger.GetPrompt(), 2436 cmd); 2437 } 2438 2439 CommandReturnObject tmp_result; 2440 // If override_context is not NULL, pass no_context_switching = true for 2441 // HandleCommand() since we updated our context already. 2442 2443 // We might call into a regex or alias command, in which case the add_to_history will get lost. This 2444 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here. 2445 if (!options.GetAddToHistory()) 2446 m_command_source_depth++; 2447 bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result, 2448 nullptr, /* override_context */ 2449 true, /* repeat_on_empty_command */ 2450 override_context != nullptr /* no_context_switching */); 2451 if (!options.GetAddToHistory()) 2452 m_command_source_depth--; 2453 2454 if (options.GetPrintResults()) 2455 { 2456 if (tmp_result.Succeeded()) 2457 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); 2458 } 2459 2460 if (!success || !tmp_result.Succeeded()) 2461 { 2462 const char *error_msg = tmp_result.GetErrorData(); 2463 if (error_msg == nullptr || error_msg[0] == '\0') 2464 error_msg = "<unknown error>.\n"; 2465 if (options.GetStopOnError()) 2466 { 2467 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s", 2468 (uint64_t)idx, cmd, error_msg); 2469 result.SetStatus (eReturnStatusFailed); 2470 m_debugger.SetAsyncExecution (old_async_execution); 2471 return; 2472 } 2473 else if (options.GetPrintResults()) 2474 { 2475 result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s", 2476 (uint64_t)idx + 1, 2477 cmd, 2478 error_msg); 2479 } 2480 } 2481 2482 if (result.GetImmediateOutputStream()) 2483 result.GetImmediateOutputStream()->Flush(); 2484 2485 if (result.GetImmediateErrorStream()) 2486 result.GetImmediateErrorStream()->Flush(); 2487 2488 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution 2489 // could be running (for instance in Breakpoint Commands. 2490 // So we check the return value to see if it is has running in it. 2491 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) 2492 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) 2493 { 2494 if (options.GetStopOnContinue()) 2495 { 2496 // If we caused the target to proceed, and we're going to stop in that case, set the 2497 // status in our real result before returning. This is an error if the continue was not the 2498 // last command in the set of commands to be run. 2499 if (idx != num_lines - 1) 2500 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n", 2501 (uint64_t)idx + 1, cmd); 2502 else 2503 result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd); 2504 2505 result.SetStatus(tmp_result.GetStatus()); 2506 m_debugger.SetAsyncExecution (old_async_execution); 2507 2508 return; 2509 } 2510 } 2511 2512 // Also check for "stop on crash here: 2513 bool should_stop = false; 2514 if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) 2515 { 2516 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 2517 if (target_sp) 2518 { 2519 ProcessSP process_sp (target_sp->GetProcessSP()); 2520 if (process_sp) 2521 { 2522 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) 2523 { 2524 StopReason reason = thread_sp->GetStopReason(); 2525 if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) 2526 { 2527 should_stop = true; 2528 break; 2529 } 2530 } 2531 } 2532 } 2533 if (should_stop) 2534 { 2535 if (idx != num_lines - 1) 2536 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n", 2537 (uint64_t)idx + 1, cmd); 2538 else 2539 result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd); 2540 2541 result.SetStatus(tmp_result.GetStatus()); 2542 m_debugger.SetAsyncExecution (old_async_execution); 2543 2544 return; 2545 } 2546 } 2547 2548 } 2549 2550 result.SetStatus (eReturnStatusSuccessFinishResult); 2551 m_debugger.SetAsyncExecution (old_async_execution); 2552 2553 return; 2554 } 2555 2556 // Make flags that we can pass into the IOHandler so our delegates can do the right thing 2557 enum { 2558 eHandleCommandFlagStopOnContinue = (1u << 0), 2559 eHandleCommandFlagStopOnError = (1u << 1), 2560 eHandleCommandFlagEchoCommand = (1u << 2), 2561 eHandleCommandFlagPrintResult = (1u << 3), 2562 eHandleCommandFlagStopOnCrash = (1u << 4) 2563 }; 2564 2565 void 2566 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, 2567 ExecutionContext *context, 2568 CommandInterpreterRunOptions &options, 2569 CommandReturnObject &result) 2570 { 2571 if (cmd_file.Exists()) 2572 { 2573 StreamFileSP input_file_sp (new StreamFile()); 2574 2575 std::string cmd_file_path = cmd_file.GetPath(); 2576 Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead); 2577 2578 if (error.Success()) 2579 { 2580 Debugger &debugger = GetDebugger(); 2581 2582 uint32_t flags = 0; 2583 2584 if (options.m_stop_on_continue == eLazyBoolCalculate) 2585 { 2586 if (m_command_source_flags.empty()) 2587 { 2588 // Stop on continue by default 2589 flags |= eHandleCommandFlagStopOnContinue; 2590 } 2591 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue) 2592 { 2593 flags |= eHandleCommandFlagStopOnContinue; 2594 } 2595 } 2596 else if (options.m_stop_on_continue == eLazyBoolYes) 2597 { 2598 flags |= eHandleCommandFlagStopOnContinue; 2599 } 2600 2601 if (options.m_stop_on_error == eLazyBoolCalculate) 2602 { 2603 if (m_command_source_flags.empty()) 2604 { 2605 if (GetStopCmdSourceOnError()) 2606 flags |= eHandleCommandFlagStopOnError; 2607 } 2608 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError) 2609 { 2610 flags |= eHandleCommandFlagStopOnError; 2611 } 2612 } 2613 else if (options.m_stop_on_error == eLazyBoolYes) 2614 { 2615 flags |= eHandleCommandFlagStopOnError; 2616 } 2617 2618 if (options.GetStopOnCrash()) 2619 { 2620 if (m_command_source_flags.empty()) 2621 { 2622 // Echo command by default 2623 flags |= eHandleCommandFlagStopOnCrash; 2624 } 2625 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) 2626 { 2627 flags |= eHandleCommandFlagStopOnCrash; 2628 } 2629 } 2630 2631 if (options.m_echo_commands == eLazyBoolCalculate) 2632 { 2633 if (m_command_source_flags.empty()) 2634 { 2635 // Echo command by default 2636 flags |= eHandleCommandFlagEchoCommand; 2637 } 2638 else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand) 2639 { 2640 flags |= eHandleCommandFlagEchoCommand; 2641 } 2642 } 2643 else if (options.m_echo_commands == eLazyBoolYes) 2644 { 2645 flags |= eHandleCommandFlagEchoCommand; 2646 } 2647 2648 if (options.m_print_results == eLazyBoolCalculate) 2649 { 2650 if (m_command_source_flags.empty()) 2651 { 2652 // Print output by default 2653 flags |= eHandleCommandFlagPrintResult; 2654 } 2655 else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult) 2656 { 2657 flags |= eHandleCommandFlagPrintResult; 2658 } 2659 } 2660 else if (options.m_print_results == eLazyBoolYes) 2661 { 2662 flags |= eHandleCommandFlagPrintResult; 2663 } 2664 2665 if (flags & eHandleCommandFlagPrintResult) 2666 { 2667 debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str()); 2668 } 2669 2670 // Used for inheriting the right settings when "command source" might have 2671 // nested "command source" commands 2672 lldb::StreamFileSP empty_stream_sp; 2673 m_command_source_flags.push_back(flags); 2674 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 2675 IOHandler::Type::CommandInterpreter, 2676 input_file_sp, 2677 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream 2678 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream 2679 flags, 2680 nullptr, // Pass in NULL for "editline_name" so no history is saved, or written 2681 debugger.GetPrompt(), 2682 NULL, 2683 false, // Not multi-line 2684 debugger.GetUseColor(), 2685 0, 2686 *this)); 2687 const bool old_async_execution = debugger.GetAsyncExecution(); 2688 2689 // Set synchronous execution if we are not stopping on continue 2690 if ((flags & eHandleCommandFlagStopOnContinue) == 0) 2691 debugger.SetAsyncExecution (false); 2692 2693 m_command_source_depth++; 2694 2695 debugger.RunIOHandler(io_handler_sp); 2696 if (!m_command_source_flags.empty()) 2697 m_command_source_flags.pop_back(); 2698 m_command_source_depth--; 2699 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2700 debugger.SetAsyncExecution (old_async_execution); 2701 } 2702 else 2703 { 2704 result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString()); 2705 result.SetStatus (eReturnStatusFailed); 2706 } 2707 2708 2709 } 2710 else 2711 { 2712 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", 2713 cmd_file.GetFilename().AsCString("<Unknown>")); 2714 result.SetStatus (eReturnStatusFailed); 2715 return; 2716 } 2717 } 2718 2719 ScriptInterpreter * 2720 CommandInterpreter::GetScriptInterpreter(bool can_create) 2721 { 2722 if (m_script_interpreter_sp) 2723 return m_script_interpreter_sp.get(); 2724 2725 if (!can_create) 2726 return nullptr; 2727 2728 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); 2729 m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this); 2730 return m_script_interpreter_sp.get(); 2731 } 2732 2733 bool 2734 CommandInterpreter::GetSynchronous () 2735 { 2736 return m_synchronous_execution; 2737 } 2738 2739 void 2740 CommandInterpreter::SetSynchronous (bool value) 2741 { 2742 m_synchronous_execution = value; 2743 } 2744 2745 void 2746 CommandInterpreter::OutputFormattedHelpText (Stream &strm, 2747 const char *prefix, 2748 const char *help_text) 2749 { 2750 const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2751 if (prefix == NULL) 2752 prefix = ""; 2753 2754 size_t prefix_width = strlen(prefix); 2755 size_t line_width_max = max_columns - prefix_width; 2756 const char *help_text_end = help_text + strlen(help_text); 2757 const char *line_start = help_text; 2758 if (line_width_max < 16) 2759 line_width_max = help_text_end - help_text + prefix_width; 2760 2761 strm.IndentMore (prefix_width); 2762 while (line_start < help_text_end) 2763 { 2764 // Break each line at the first newline or last space/tab before 2765 // the maximum number of characters that fit on a line. Lines with no 2766 // natural break are left unbroken to wrap. 2767 const char *line_end = help_text_end; 2768 const char *line_scan = line_start; 2769 const char *line_scan_end = help_text_end; 2770 while (line_scan < line_scan_end) 2771 { 2772 char next = *line_scan; 2773 if (next == '\t' || next == ' ') 2774 { 2775 line_end = line_scan; 2776 line_scan_end = line_start + line_width_max; 2777 } 2778 else if (next == '\n' || next == '\0') 2779 { 2780 line_end = line_scan; 2781 break; 2782 } 2783 ++line_scan; 2784 } 2785 2786 // Prefix the first line, indent subsequent lines to line up 2787 if (line_start == help_text) 2788 strm.Write (prefix, prefix_width); 2789 else 2790 strm.Indent(); 2791 strm.Write (line_start, line_end - line_start); 2792 strm.EOL(); 2793 2794 // When a line breaks at whitespace consume it before continuing 2795 line_start = line_end; 2796 char next = *line_start; 2797 if (next == '\n') 2798 ++line_start; 2799 else while (next == ' ' || next == '\t') 2800 next = *(++line_start); 2801 } 2802 strm.IndentLess (prefix_width); 2803 } 2804 2805 void 2806 CommandInterpreter::OutputFormattedHelpText (Stream &strm, 2807 const char *word_text, 2808 const char *separator, 2809 const char *help_text, 2810 size_t max_word_len) 2811 { 2812 StreamString prefix_stream; 2813 prefix_stream.Printf (" %-*s %s ", (int)max_word_len, word_text, separator); 2814 OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text); 2815 } 2816 2817 void 2818 CommandInterpreter::OutputHelpText (Stream &strm, 2819 const char *word_text, 2820 const char *separator, 2821 const char *help_text, 2822 uint32_t max_word_len) 2823 { 2824 int indent_size = max_word_len + strlen (separator) + 2; 2825 2826 strm.IndentMore (indent_size); 2827 2828 StreamString text_strm; 2829 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text); 2830 2831 const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2832 2833 size_t len = text_strm.GetSize(); 2834 const char *text = text_strm.GetData(); 2835 2836 uint32_t chars_left = max_columns; 2837 2838 for (uint32_t i = 0; i < len; i++) 2839 { 2840 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n') 2841 { 2842 chars_left = max_columns - indent_size; 2843 strm.EOL(); 2844 strm.Indent(); 2845 } 2846 else 2847 { 2848 strm.PutChar(text[i]); 2849 chars_left--; 2850 } 2851 2852 } 2853 2854 strm.EOL(); 2855 strm.IndentLess(indent_size); 2856 } 2857 2858 void 2859 CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found, 2860 StringList &commands_help, bool search_builtin_commands, bool search_user_commands) 2861 { 2862 CommandObject::CommandMap::const_iterator pos; 2863 2864 if (search_builtin_commands) 2865 { 2866 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 2867 { 2868 const char *command_name = pos->first.c_str(); 2869 CommandObject *cmd_obj = pos->second.get(); 2870 2871 if (cmd_obj->HelpTextContainsWord (search_word)) 2872 { 2873 commands_found.AppendString (command_name); 2874 commands_help.AppendString (cmd_obj->GetHelp()); 2875 } 2876 2877 if (cmd_obj->IsMultiwordObject()) 2878 cmd_obj->AproposAllSubCommands (command_name, 2879 search_word, 2880 commands_found, 2881 commands_help); 2882 2883 } 2884 } 2885 2886 if (search_user_commands) 2887 { 2888 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 2889 { 2890 const char *command_name = pos->first.c_str(); 2891 CommandObject *cmd_obj = pos->second.get(); 2892 2893 if (cmd_obj->HelpTextContainsWord (search_word)) 2894 { 2895 commands_found.AppendString (command_name); 2896 commands_help.AppendString (cmd_obj->GetHelp()); 2897 } 2898 2899 if (cmd_obj->IsMultiwordObject()) 2900 cmd_obj->AproposAllSubCommands (command_name, 2901 search_word, 2902 commands_found, 2903 commands_help); 2904 2905 } 2906 } 2907 } 2908 2909 void 2910 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context) 2911 { 2912 if (override_context != nullptr) 2913 { 2914 m_exe_ctx_ref = *override_context; 2915 } 2916 else 2917 { 2918 const bool adopt_selected = true; 2919 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected); 2920 } 2921 } 2922 2923 2924 size_t 2925 CommandInterpreter::GetProcessOutput () 2926 { 2927 // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 2928 char stdio_buffer[1024]; 2929 size_t len; 2930 size_t total_bytes = 0; 2931 Error error; 2932 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 2933 if (target_sp) 2934 { 2935 ProcessSP process_sp (target_sp->GetProcessSP()); 2936 if (process_sp) 2937 { 2938 while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 2939 { 2940 size_t bytes_written = len; 2941 m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written); 2942 total_bytes += len; 2943 } 2944 while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 2945 { 2946 size_t bytes_written = len; 2947 m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written); 2948 total_bytes += len; 2949 } 2950 } 2951 } 2952 return total_bytes; 2953 } 2954 2955 void 2956 CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) 2957 { 2958 const bool is_interactive = io_handler.GetIsInteractive(); 2959 if (is_interactive == false) 2960 { 2961 // When we are not interactive, don't execute blank lines. This will happen 2962 // sourcing a commands file. We don't want blank lines to repeat the previous 2963 // command and cause any errors to occur (like redefining an alias, get an error 2964 // and stop parsing the commands file). 2965 if (line.empty()) 2966 return; 2967 2968 // When using a non-interactive file handle (like when sourcing commands from a file) 2969 // we need to echo the command out so we don't just see the command output and no 2970 // command... 2971 if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand)) 2972 io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str()); 2973 } 2974 2975 lldb_private::CommandReturnObject result; 2976 HandleCommand(line.c_str(), eLazyBoolCalculate, result); 2977 2978 // Now emit the command output text from the command we just executed 2979 if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) 2980 { 2981 // Display any STDOUT/STDERR _prior_ to emitting the command result text 2982 GetProcessOutput (); 2983 2984 if (!result.GetImmediateOutputStream()) 2985 { 2986 const char *output = result.GetOutputData(); 2987 if (output && output[0]) 2988 io_handler.GetOutputStreamFile()->PutCString(output); 2989 } 2990 2991 // Now emit the command error text from the command we just executed 2992 if (!result.GetImmediateErrorStream()) 2993 { 2994 const char *error = result.GetErrorData(); 2995 if (error && error[0]) 2996 io_handler.GetErrorStreamFile()->PutCString(error); 2997 } 2998 } 2999 3000 switch (result.GetStatus()) 3001 { 3002 case eReturnStatusInvalid: 3003 case eReturnStatusSuccessFinishNoResult: 3004 case eReturnStatusSuccessFinishResult: 3005 case eReturnStatusStarted: 3006 break; 3007 3008 case eReturnStatusSuccessContinuingNoResult: 3009 case eReturnStatusSuccessContinuingResult: 3010 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue)) 3011 io_handler.SetIsDone(true); 3012 break; 3013 3014 case eReturnStatusFailed: 3015 m_num_errors++; 3016 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) 3017 io_handler.SetIsDone(true); 3018 break; 3019 3020 case eReturnStatusQuit: 3021 m_quit_requested = true; 3022 io_handler.SetIsDone(true); 3023 break; 3024 } 3025 3026 // Finally, if we're going to stop on crash, check that here: 3027 if (!m_quit_requested 3028 && result.GetDidChangeProcessState() 3029 && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) 3030 { 3031 bool should_stop = false; 3032 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 3033 if (target_sp) 3034 { 3035 ProcessSP process_sp (target_sp->GetProcessSP()); 3036 if (process_sp) 3037 { 3038 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) 3039 { 3040 StopReason reason = thread_sp->GetStopReason(); 3041 if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) 3042 { 3043 should_stop = true; 3044 break; 3045 } 3046 } 3047 } 3048 } 3049 if (should_stop) 3050 { 3051 io_handler.SetIsDone(true); 3052 m_stopped_for_crash = true; 3053 } 3054 } 3055 } 3056 3057 bool 3058 CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler) 3059 { 3060 ExecutionContext exe_ctx (GetExecutionContext()); 3061 Process *process = exe_ctx.GetProcessPtr(); 3062 3063 if (process) 3064 { 3065 StateType state = process->GetState(); 3066 if (StateIsRunningState(state)) 3067 { 3068 process->Halt(); 3069 return true; // Don't do any updating when we are running 3070 } 3071 } 3072 3073 ScriptInterpreter *script_interpreter = GetScriptInterpreter (false); 3074 if (script_interpreter) 3075 { 3076 if (script_interpreter->Interrupt()) 3077 return true; 3078 } 3079 return false; 3080 } 3081 3082 void 3083 CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt, 3084 IOHandlerDelegate &delegate, 3085 bool asynchronously, 3086 void *baton) 3087 { 3088 Debugger &debugger = GetDebugger(); 3089 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 3090 IOHandler::Type::CommandList, 3091 "lldb", // Name of input reader for history 3092 prompt, // Prompt 3093 NULL, // Continuation prompt 3094 true, // Get multiple lines 3095 debugger.GetUseColor(), 3096 0, // Don't show line numbers 3097 delegate)); // IOHandlerDelegate 3098 3099 if (io_handler_sp) 3100 { 3101 io_handler_sp->SetUserData (baton); 3102 if (asynchronously) 3103 debugger.PushIOHandler(io_handler_sp); 3104 else 3105 debugger.RunIOHandler(io_handler_sp); 3106 } 3107 3108 } 3109 3110 3111 void 3112 CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt, 3113 IOHandlerDelegate &delegate, 3114 bool asynchronously, 3115 void *baton) 3116 { 3117 Debugger &debugger = GetDebugger(); 3118 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 3119 IOHandler::Type::PythonCode, 3120 "lldb-python", // Name of input reader for history 3121 prompt, // Prompt 3122 NULL, // Continuation prompt 3123 true, // Get multiple lines 3124 debugger.GetUseColor(), 3125 0, // Don't show line numbers 3126 delegate)); // IOHandlerDelegate 3127 3128 if (io_handler_sp) 3129 { 3130 io_handler_sp->SetUserData (baton); 3131 if (asynchronously) 3132 debugger.PushIOHandler(io_handler_sp); 3133 else 3134 debugger.RunIOHandler(io_handler_sp); 3135 } 3136 3137 } 3138 3139 bool 3140 CommandInterpreter::IsActive () 3141 { 3142 return m_debugger.IsTopIOHandler (m_command_io_handler_sp); 3143 } 3144 3145 lldb::IOHandlerSP 3146 CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options) 3147 { 3148 // Always re-create the IOHandlerEditline in case the input 3149 // changed. The old instance might have had a non-interactive 3150 // input and now it does or vice versa. 3151 if (force_create || !m_command_io_handler_sp) 3152 { 3153 // Always re-create the IOHandlerEditline in case the input 3154 // changed. The old instance might have had a non-interactive 3155 // input and now it does or vice versa. 3156 uint32_t flags = 0; 3157 3158 if (options) 3159 { 3160 if (options->m_stop_on_continue == eLazyBoolYes) 3161 flags |= eHandleCommandFlagStopOnContinue; 3162 if (options->m_stop_on_error == eLazyBoolYes) 3163 flags |= eHandleCommandFlagStopOnError; 3164 if (options->m_stop_on_crash == eLazyBoolYes) 3165 flags |= eHandleCommandFlagStopOnCrash; 3166 if (options->m_echo_commands != eLazyBoolNo) 3167 flags |= eHandleCommandFlagEchoCommand; 3168 if (options->m_print_results != eLazyBoolNo) 3169 flags |= eHandleCommandFlagPrintResult; 3170 } 3171 else 3172 { 3173 flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult; 3174 } 3175 3176 m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, 3177 IOHandler::Type::CommandInterpreter, 3178 m_debugger.GetInputFile(), 3179 m_debugger.GetOutputFile(), 3180 m_debugger.GetErrorFile(), 3181 flags, 3182 "lldb", 3183 m_debugger.GetPrompt(), 3184 NULL, // Continuation prompt 3185 false, // Don't enable multiple line input, just single line commands 3186 m_debugger.GetUseColor(), 3187 0, // Don't show line numbers 3188 *this)); 3189 } 3190 return m_command_io_handler_sp; 3191 } 3192 3193 void 3194 CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, 3195 bool spawn_thread, 3196 CommandInterpreterRunOptions &options) 3197 { 3198 // Always re-create the command interpreter when we run it in case 3199 // any file handles have changed. 3200 bool force_create = true; 3201 m_debugger.PushIOHandler(GetIOHandler(force_create, &options)); 3202 m_stopped_for_crash = false; 3203 3204 if (auto_handle_events) 3205 m_debugger.StartEventHandlerThread(); 3206 3207 if (spawn_thread) 3208 { 3209 m_debugger.StartIOHandlerThread(); 3210 } 3211 else 3212 { 3213 m_debugger.ExecuteIOHandlers(); 3214 3215 if (auto_handle_events) 3216 m_debugger.StopEventHandlerThread(); 3217 } 3218 3219 } 3220 3221 CommandObject * 3222 CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnObject &result) 3223 { 3224 std::string scratch_command(command_line); // working copy so we don't modify command_line unless we succeed 3225 CommandObject *cmd_obj = nullptr; 3226 StreamString revised_command_line; 3227 bool wants_raw_input = false; 3228 size_t actual_cmd_name_len = 0; 3229 std::string next_word; 3230 StringList matches; 3231 bool done = false; 3232 while (!done) 3233 { 3234 char quote_char = '\0'; 3235 std::string suffix; 3236 ExtractCommand(scratch_command, next_word, suffix, quote_char); 3237 if (cmd_obj == nullptr) 3238 { 3239 std::string full_name; 3240 if (GetAliasFullName(next_word.c_str(), full_name)) 3241 { 3242 std::string alias_result; 3243 cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, alias_result, result); 3244 revised_command_line.Printf("%s", alias_result.c_str()); 3245 if (cmd_obj) 3246 { 3247 wants_raw_input = cmd_obj->WantsRawCommandString(); 3248 actual_cmd_name_len = strlen(cmd_obj->GetCommandName()); 3249 } 3250 } 3251 else 3252 { 3253 cmd_obj = GetCommandObject(next_word.c_str(), &matches); 3254 if (cmd_obj) 3255 { 3256 actual_cmd_name_len += strlen(cmd_obj->GetCommandName()); 3257 revised_command_line.Printf("%s", cmd_obj->GetCommandName()); 3258 wants_raw_input = cmd_obj->WantsRawCommandString(); 3259 } 3260 else 3261 { 3262 revised_command_line.Printf ("%s", next_word.c_str()); 3263 } 3264 } 3265 } 3266 else 3267 { 3268 if (cmd_obj->IsMultiwordObject ()) 3269 { 3270 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject(next_word.c_str()); 3271 if (sub_cmd_obj) 3272 { 3273 // The subcommand's name includes the parent command's name, 3274 // so restart rather than append to the revised_command_line. 3275 actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1; 3276 revised_command_line.Clear(); 3277 revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName()); 3278 cmd_obj = sub_cmd_obj; 3279 wants_raw_input = cmd_obj->WantsRawCommandString(); 3280 } 3281 else 3282 { 3283 if (quote_char) 3284 revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 3285 else 3286 revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str()); 3287 done = true; 3288 } 3289 } 3290 else 3291 { 3292 if (quote_char) 3293 revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 3294 else 3295 revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str()); 3296 done = true; 3297 } 3298 } 3299 3300 if (cmd_obj == nullptr) 3301 { 3302 const size_t num_matches = matches.GetSize(); 3303 if (matches.GetSize() > 1) { 3304 StreamString error_msg; 3305 error_msg.Printf("Ambiguous command '%s'. Possible matches:\n", next_word.c_str()); 3306 3307 for (uint32_t i = 0; i < num_matches; ++i) { 3308 error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i)); 3309 } 3310 result.AppendRawError(error_msg.GetString().c_str()); 3311 } else { 3312 // We didn't have only one match, otherwise we wouldn't get here. 3313 assert(num_matches == 0); 3314 result.AppendErrorWithFormat("'%s' is not a valid command.\n", next_word.c_str()); 3315 } 3316 result.SetStatus(eReturnStatusFailed); 3317 return nullptr; 3318 } 3319 3320 if (cmd_obj->IsMultiwordObject()) 3321 { 3322 if (!suffix.empty()) 3323 { 3324 result.AppendErrorWithFormat("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n", 3325 cmd_obj->GetCommandName(), 3326 next_word.empty() ? "" : next_word.c_str(), 3327 next_word.empty() ? " -- " : " ", 3328 suffix.c_str()); 3329 result.SetStatus(eReturnStatusFailed); 3330 return nullptr; 3331 } 3332 } 3333 else 3334 { 3335 // If we found a normal command, we are done 3336 done = true; 3337 if (!suffix.empty()) 3338 { 3339 switch (suffix[0]) 3340 { 3341 case '/': 3342 // GDB format suffixes 3343 { 3344 Options *command_options = cmd_obj->GetOptions(); 3345 if (command_options && command_options->SupportsLongOption("gdb-format")) 3346 { 3347 std::string gdb_format_option("--gdb-format="); 3348 gdb_format_option += (suffix.c_str() + 1); 3349 3350 bool inserted = false; 3351 std::string &cmd = revised_command_line.GetString(); 3352 size_t arg_terminator_idx = FindArgumentTerminator(cmd); 3353 if (arg_terminator_idx != std::string::npos) 3354 { 3355 // Insert the gdb format option before the "--" that terminates options 3356 gdb_format_option.append(1,' '); 3357 cmd.insert(arg_terminator_idx, gdb_format_option); 3358 inserted = true; 3359 } 3360 3361 if (!inserted) 3362 revised_command_line.Printf(" %s", gdb_format_option.c_str()); 3363 3364 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos) 3365 revised_command_line.PutCString(" --"); 3366 } 3367 else 3368 { 3369 result.AppendErrorWithFormat("the '%s' command doesn't support the --gdb-format option\n", 3370 cmd_obj->GetCommandName()); 3371 result.SetStatus(eReturnStatusFailed); 3372 return nullptr; 3373 } 3374 } 3375 break; 3376 3377 default: 3378 result.AppendErrorWithFormat("unknown command shorthand suffix: '%s'\n", 3379 suffix.c_str()); 3380 result.SetStatus(eReturnStatusFailed); 3381 return nullptr; 3382 } 3383 } 3384 } 3385 if (scratch_command.empty()) 3386 done = true; 3387 } 3388 3389 if (!scratch_command.empty()) 3390 revised_command_line.Printf(" %s", scratch_command.c_str()); 3391 3392 if (cmd_obj != NULL) 3393 command_line = revised_command_line.GetData(); 3394 3395 return cmd_obj; 3396 } 3397