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