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