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