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