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