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 "lldb/lldb-python.h" 11 12 #include <string> 13 #include <vector> 14 #include <stdlib.h> 15 16 #include "CommandObjectScript.h" 17 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 18 19 #include "../Commands/CommandObjectApropos.h" 20 #include "../Commands/CommandObjectArgs.h" 21 #include "../Commands/CommandObjectBreakpoint.h" 22 #include "../Commands/CommandObjectDisassemble.h" 23 #include "../Commands/CommandObjectExpression.h" 24 #include "../Commands/CommandObjectFrame.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 43 44 #include "lldb/Core/Debugger.h" 45 #include "lldb/Core/InputReader.h" 46 #include "lldb/Core/Log.h" 47 #include "lldb/Core/Stream.h" 48 #include "lldb/Core/Timer.h" 49 50 #include "lldb/Host/Host.h" 51 52 #include "lldb/Interpreter/Args.h" 53 #include "lldb/Interpreter/CommandCompletions.h" 54 #include "lldb/Interpreter/CommandInterpreter.h" 55 #include "lldb/Interpreter/CommandReturnObject.h" 56 #include "lldb/Interpreter/Options.h" 57 #include "lldb/Interpreter/ScriptInterpreterNone.h" 58 #include "lldb/Interpreter/ScriptInterpreterPython.h" 59 60 61 #include "lldb/Target/Process.h" 62 #include "lldb/Target/Thread.h" 63 #include "lldb/Target/TargetList.h" 64 65 #include "lldb/Utility/CleanUp.h" 66 67 using namespace lldb; 68 using namespace lldb_private; 69 70 71 static PropertyDefinition 72 g_properties[] = 73 { 74 { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, NULL, NULL, "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." }, 75 { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, NULL, NULL, "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." }, 76 { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, NULL, NULL, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, 77 { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 78 }; 79 80 enum 81 { 82 ePropertyExpandRegexAliases = 0, 83 ePropertyPromptOnQuit = 1, 84 ePropertyStopCmdSourceOnError = 2 85 }; 86 87 ConstString & 88 CommandInterpreter::GetStaticBroadcasterClass () 89 { 90 static ConstString class_name ("lldb.commandInterpreter"); 91 return class_name; 92 } 93 94 CommandInterpreter::CommandInterpreter 95 ( 96 Debugger &debugger, 97 ScriptLanguage script_language, 98 bool synchronous_execution 99 ) : 100 Broadcaster (&debugger, "lldb.command-interpreter"), 101 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), 102 m_debugger (debugger), 103 m_synchronous_execution (synchronous_execution), 104 m_skip_lldbinit_files (false), 105 m_skip_app_init_files (false), 106 m_script_interpreter_ap (), 107 m_comment_char ('#'), 108 m_batch_command_mode (false), 109 m_truncation_warning(eNoTruncation), 110 m_command_source_depth (0) 111 { 112 debugger.SetScriptLanguage (script_language); 113 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); 114 SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); 115 SetEventName (eBroadcastBitQuitCommandReceived, "quit"); 116 CheckInWithManager (); 117 m_collection_sp->Initialize (g_properties); 118 } 119 120 bool 121 CommandInterpreter::GetExpandRegexAliases () const 122 { 123 const uint32_t idx = ePropertyExpandRegexAliases; 124 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 125 } 126 127 bool 128 CommandInterpreter::GetPromptOnQuit () const 129 { 130 const uint32_t idx = ePropertyPromptOnQuit; 131 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 132 } 133 134 bool 135 CommandInterpreter::GetStopCmdSourceOnError () const 136 { 137 const uint32_t idx = ePropertyStopCmdSourceOnError; 138 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 139 } 140 141 void 142 CommandInterpreter::Initialize () 143 { 144 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 145 146 CommandReturnObject result; 147 148 LoadCommandDictionary (); 149 150 // Set up some initial aliases. 151 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false); 152 if (cmd_obj_sp) 153 { 154 AddAlias ("q", cmd_obj_sp); 155 AddAlias ("exit", cmd_obj_sp); 156 } 157 158 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false); 159 if (cmd_obj_sp) 160 { 161 AddAlias ("attach", cmd_obj_sp); 162 } 163 164 cmd_obj_sp = GetCommandSPExact ("process detach",false); 165 if (cmd_obj_sp) 166 { 167 AddAlias ("detach", cmd_obj_sp); 168 } 169 170 cmd_obj_sp = GetCommandSPExact ("process continue", false); 171 if (cmd_obj_sp) 172 { 173 AddAlias ("c", cmd_obj_sp); 174 AddAlias ("continue", cmd_obj_sp); 175 } 176 177 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false); 178 if (cmd_obj_sp) 179 AddAlias ("b", cmd_obj_sp); 180 181 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false); 182 if (cmd_obj_sp) 183 AddAlias ("tbreak", cmd_obj_sp); 184 185 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false); 186 if (cmd_obj_sp) 187 { 188 AddAlias ("stepi", cmd_obj_sp); 189 AddAlias ("si", cmd_obj_sp); 190 } 191 192 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false); 193 if (cmd_obj_sp) 194 { 195 AddAlias ("nexti", cmd_obj_sp); 196 AddAlias ("ni", cmd_obj_sp); 197 } 198 199 cmd_obj_sp = GetCommandSPExact ("thread step-in", false); 200 if (cmd_obj_sp) 201 { 202 AddAlias ("s", cmd_obj_sp); 203 AddAlias ("step", cmd_obj_sp); 204 } 205 206 cmd_obj_sp = GetCommandSPExact ("thread step-over", false); 207 if (cmd_obj_sp) 208 { 209 AddAlias ("n", cmd_obj_sp); 210 AddAlias ("next", cmd_obj_sp); 211 } 212 213 cmd_obj_sp = GetCommandSPExact ("thread step-out", false); 214 if (cmd_obj_sp) 215 { 216 AddAlias ("finish", cmd_obj_sp); 217 } 218 219 cmd_obj_sp = GetCommandSPExact ("frame select", false); 220 if (cmd_obj_sp) 221 { 222 AddAlias ("f", cmd_obj_sp); 223 } 224 225 cmd_obj_sp = GetCommandSPExact ("thread select", false); 226 if (cmd_obj_sp) 227 { 228 AddAlias ("t", cmd_obj_sp); 229 } 230 231 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false); 232 if (cmd_obj_sp) 233 { 234 AddAlias ("l", cmd_obj_sp); 235 AddAlias ("list", cmd_obj_sp); 236 } 237 238 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false); 239 if (cmd_obj_sp) 240 { 241 AddAlias ("env", cmd_obj_sp); 242 } 243 244 cmd_obj_sp = GetCommandSPExact ("memory read", false); 245 if (cmd_obj_sp) 246 AddAlias ("x", cmd_obj_sp); 247 248 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false); 249 if (cmd_obj_sp) 250 AddAlias ("up", cmd_obj_sp); 251 252 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false); 253 if (cmd_obj_sp) 254 AddAlias ("down", cmd_obj_sp); 255 256 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false); 257 if (cmd_obj_sp) 258 AddAlias ("display", cmd_obj_sp); 259 260 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 261 if (cmd_obj_sp) 262 AddAlias ("dis", cmd_obj_sp); 263 264 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 265 if (cmd_obj_sp) 266 AddAlias ("di", cmd_obj_sp); 267 268 269 270 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false); 271 if (cmd_obj_sp) 272 AddAlias ("undisplay", cmd_obj_sp); 273 274 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false); 275 if (cmd_obj_sp) 276 AddAlias ("bt", cmd_obj_sp); 277 278 cmd_obj_sp = GetCommandSPExact ("target create", false); 279 if (cmd_obj_sp) 280 AddAlias ("file", cmd_obj_sp); 281 282 cmd_obj_sp = GetCommandSPExact ("target modules", false); 283 if (cmd_obj_sp) 284 AddAlias ("image", cmd_obj_sp); 285 286 287 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector); 288 289 cmd_obj_sp = GetCommandSPExact ("expression", false); 290 if (cmd_obj_sp) 291 { 292 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 293 AddAlias ("p", cmd_obj_sp); 294 AddAlias ("print", cmd_obj_sp); 295 AddAlias ("call", cmd_obj_sp); 296 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp); 297 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp); 298 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp); 299 300 alias_arguments_vector_sp.reset (new OptionArgVector); 301 ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp); 302 AddAlias ("po", cmd_obj_sp); 303 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp); 304 } 305 306 cmd_obj_sp = GetCommandSPExact ("process kill", false); 307 if (cmd_obj_sp) 308 { 309 AddAlias ("kill", cmd_obj_sp); 310 } 311 312 cmd_obj_sp = GetCommandSPExact ("process launch", false); 313 if (cmd_obj_sp) 314 { 315 alias_arguments_vector_sp.reset (new OptionArgVector); 316 #if defined (__arm__) 317 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 318 #else 319 ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=" LLDB_DEFAULT_SHELL " --", alias_arguments_vector_sp); 320 #endif 321 AddAlias ("r", cmd_obj_sp); 322 AddAlias ("run", cmd_obj_sp); 323 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp); 324 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp); 325 } 326 327 cmd_obj_sp = GetCommandSPExact ("target symbols add", false); 328 if (cmd_obj_sp) 329 { 330 AddAlias ("add-dsym", cmd_obj_sp); 331 } 332 333 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false); 334 if (cmd_obj_sp) 335 { 336 alias_arguments_vector_sp.reset (new OptionArgVector); 337 ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp); 338 AddAlias ("rbreak", cmd_obj_sp); 339 AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp); 340 } 341 } 342 343 const char * 344 CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) 345 { 346 // This function has not yet been implemented. 347 348 // Look for any embedded script command 349 // If found, 350 // get interpreter object from the command dictionary, 351 // call execute_one_command on it, 352 // get the results as a string, 353 // substitute that string for current stuff. 354 355 return arg; 356 } 357 358 359 void 360 CommandInterpreter::LoadCommandDictionary () 361 { 362 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 363 364 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); 365 366 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); 367 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); 368 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); 369 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); 370 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this)); 371 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); 372 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this)); 373 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); 374 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); 375 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this)); 376 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this)); 377 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); 378 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this)); 379 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); 380 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language)); 381 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); 382 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); 383 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); 384 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); 385 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this)); 386 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this)); 387 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); 388 389 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, 390 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, 391 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, 392 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, 393 {"^(-.*)$", "breakpoint set %1"}, 394 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"}, 395 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, 396 {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}}; 397 398 size_t num_regexes = sizeof break_regexes/sizeof(char *[2]); 399 400 std::unique_ptr<CommandObjectRegexCommand> 401 break_regex_cmd_ap(new CommandObjectRegexCommand (*this, 402 "_regexp-break", 403 "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 404 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 405 2, 406 CommandCompletions::eSymbolCompletion | 407 CommandCompletions::eSourceFileCompletion)); 408 409 if (break_regex_cmd_ap.get()) 410 { 411 bool success = true; 412 for (size_t i = 0; i < num_regexes; i++) 413 { 414 success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]); 415 if (!success) 416 break; 417 } 418 success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 419 420 if (success) 421 { 422 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); 423 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; 424 } 425 } 426 427 std::unique_ptr<CommandObjectRegexCommand> 428 tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this, 429 "_regexp-tbreak", 430 "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 431 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 432 2, 433 CommandCompletions::eSymbolCompletion | 434 CommandCompletions::eSourceFileCompletion)); 435 436 if (tbreak_regex_cmd_ap.get()) 437 { 438 bool success = true; 439 for (size_t i = 0; i < num_regexes; i++) 440 { 441 // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer. 442 char buffer[1024]; 443 int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); 444 assert (num_printed < 1024); 445 success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); 446 if (!success) 447 break; 448 } 449 success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 450 451 if (success) 452 { 453 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); 454 m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp; 455 } 456 } 457 458 std::unique_ptr<CommandObjectRegexCommand> 459 attach_regex_cmd_ap(new CommandObjectRegexCommand (*this, 460 "_regexp-attach", 461 "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", 462 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", 463 2)); 464 if (attach_regex_cmd_ap.get()) 465 { 466 if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && 467 attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach' 468 attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") && 469 attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) 470 { 471 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); 472 m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp; 473 } 474 } 475 476 std::unique_ptr<CommandObjectRegexCommand> 477 down_regex_cmd_ap(new CommandObjectRegexCommand (*this, 478 "_regexp-down", 479 "Go down \"n\" frames in the stack (1 frame by default).", 480 "_regexp-down [n]", 2)); 481 if (down_regex_cmd_ap.get()) 482 { 483 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && 484 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1")) 485 { 486 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); 487 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp; 488 } 489 } 490 491 std::unique_ptr<CommandObjectRegexCommand> 492 up_regex_cmd_ap(new CommandObjectRegexCommand (*this, 493 "_regexp-up", 494 "Go up \"n\" frames in the stack (1 frame by default).", 495 "_regexp-up [n]", 2)); 496 if (up_regex_cmd_ap.get()) 497 { 498 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && 499 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) 500 { 501 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); 502 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp; 503 } 504 } 505 506 std::unique_ptr<CommandObjectRegexCommand> 507 display_regex_cmd_ap(new CommandObjectRegexCommand (*this, 508 "_regexp-display", 509 "Add an expression evaluation stop-hook.", 510 "_regexp-display expression", 2)); 511 if (display_regex_cmd_ap.get()) 512 { 513 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) 514 { 515 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); 516 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp; 517 } 518 } 519 520 std::unique_ptr<CommandObjectRegexCommand> 521 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, 522 "_regexp-undisplay", 523 "Remove an expression evaluation stop-hook.", 524 "_regexp-undisplay stop-hook-number", 2)); 525 if (undisplay_regex_cmd_ap.get()) 526 { 527 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) 528 { 529 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); 530 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp; 531 } 532 } 533 534 std::unique_ptr<CommandObjectRegexCommand> 535 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, 536 "gdb-remote", 537 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", 538 "gdb-remote [<hostname>:]<portnum>", 2)); 539 if (connect_gdb_remote_cmd_ap.get()) 540 { 541 if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && 542 connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) 543 { 544 CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); 545 m_command_dict[command_sp->GetCommandName ()] = command_sp; 546 } 547 } 548 549 std::unique_ptr<CommandObjectRegexCommand> 550 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, 551 "kdp-remote", 552 "Connect to a remote KDP server. udp port 41139 is the default port number.", 553 "kdp-remote <hostname>[:<portnum>]", 2)); 554 if (connect_kdp_remote_cmd_ap.get()) 555 { 556 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && 557 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) 558 { 559 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); 560 m_command_dict[command_sp->GetCommandName ()] = command_sp; 561 } 562 } 563 564 std::unique_ptr<CommandObjectRegexCommand> 565 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, 566 "_regexp-bt", 567 "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.", 568 "bt [<digit>|all]", 2)); 569 if (bt_regex_cmd_ap.get()) 570 { 571 // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace 572 // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and 573 // so now "bt 3" is the preferred form, in line with gdb. 574 if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") && 575 bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") && 576 bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && 577 bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) 578 { 579 CommandObjectSP command_sp(bt_regex_cmd_ap.release()); 580 m_command_dict[command_sp->GetCommandName ()] = command_sp; 581 } 582 } 583 584 std::unique_ptr<CommandObjectRegexCommand> 585 list_regex_cmd_ap(new CommandObjectRegexCommand (*this, 586 "_regexp-list", 587 "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", 588 "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]", 589 2, 590 CommandCompletions::eSourceFileCompletion)); 591 if (list_regex_cmd_ap.get()) 592 { 593 if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && 594 list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") && 595 list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") && 596 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") && 597 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") && 598 list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") && 599 list_regex_cmd_ap->AddRegexCommand("^$", "source list")) 600 { 601 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); 602 m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp; 603 } 604 } 605 606 std::unique_ptr<CommandObjectRegexCommand> 607 env_regex_cmd_ap(new CommandObjectRegexCommand (*this, 608 "_regexp-env", 609 "Implements a shortcut to viewing and setting environment variables.", 610 "_regexp-env\n_regexp-env FOO=BAR", 2)); 611 if (env_regex_cmd_ap.get()) 612 { 613 if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && 614 env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1")) 615 { 616 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); 617 m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp; 618 } 619 } 620 621 } 622 623 int 624 CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, 625 StringList &matches) 626 { 627 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); 628 629 if (include_aliases) 630 { 631 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); 632 } 633 634 return matches.GetSize(); 635 } 636 637 CommandObjectSP 638 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) 639 { 640 CommandObject::CommandMap::iterator pos; 641 CommandObjectSP command_sp; 642 643 std::string cmd(cmd_cstr); 644 645 if (HasCommands()) 646 { 647 pos = m_command_dict.find(cmd); 648 if (pos != m_command_dict.end()) 649 command_sp = pos->second; 650 } 651 652 if (include_aliases && HasAliases()) 653 { 654 pos = m_alias_dict.find(cmd); 655 if (pos != m_alias_dict.end()) 656 command_sp = pos->second; 657 } 658 659 if (HasUserCommands()) 660 { 661 pos = m_user_dict.find(cmd); 662 if (pos != m_user_dict.end()) 663 command_sp = pos->second; 664 } 665 666 if (!exact && !command_sp) 667 { 668 // We will only get into here if we didn't find any exact matches. 669 670 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; 671 672 StringList local_matches; 673 if (matches == NULL) 674 matches = &local_matches; 675 676 unsigned int num_cmd_matches = 0; 677 unsigned int num_alias_matches = 0; 678 unsigned int num_user_matches = 0; 679 680 // Look through the command dictionaries one by one, and if we get only one match from any of 681 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. 682 683 if (HasCommands()) 684 { 685 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); 686 } 687 688 if (num_cmd_matches == 1) 689 { 690 cmd.assign(matches->GetStringAtIndex(0)); 691 pos = m_command_dict.find(cmd); 692 if (pos != m_command_dict.end()) 693 real_match_sp = pos->second; 694 } 695 696 if (include_aliases && HasAliases()) 697 { 698 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); 699 700 } 701 702 if (num_alias_matches == 1) 703 { 704 cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); 705 pos = m_alias_dict.find(cmd); 706 if (pos != m_alias_dict.end()) 707 alias_match_sp = pos->second; 708 } 709 710 if (HasUserCommands()) 711 { 712 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); 713 } 714 715 if (num_user_matches == 1) 716 { 717 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); 718 719 pos = m_user_dict.find (cmd); 720 if (pos != m_user_dict.end()) 721 user_match_sp = pos->second; 722 } 723 724 // If we got exactly one match, return that, otherwise return the match list. 725 726 if (num_user_matches + num_cmd_matches + num_alias_matches == 1) 727 { 728 if (num_cmd_matches) 729 return real_match_sp; 730 else if (num_alias_matches) 731 return alias_match_sp; 732 else 733 return user_match_sp; 734 } 735 } 736 else if (matches && command_sp) 737 { 738 matches->AppendString (cmd_cstr); 739 } 740 741 742 return command_sp; 743 } 744 745 bool 746 CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) 747 { 748 if (name && name[0]) 749 { 750 std::string name_sstr(name); 751 bool found = (m_command_dict.find (name_sstr) != m_command_dict.end()); 752 if (found && !can_replace) 753 return false; 754 if (found && m_command_dict[name_sstr]->IsRemovable() == false) 755 return false; 756 m_command_dict[name_sstr] = cmd_sp; 757 return true; 758 } 759 return false; 760 } 761 762 bool 763 CommandInterpreter::AddUserCommand (std::string name, 764 const lldb::CommandObjectSP &cmd_sp, 765 bool can_replace) 766 { 767 if (!name.empty()) 768 { 769 770 const char* name_cstr = name.c_str(); 771 772 // do not allow replacement of internal commands 773 if (CommandExists(name_cstr)) 774 { 775 if (can_replace == false) 776 return false; 777 if (m_command_dict[name]->IsRemovable() == false) 778 return false; 779 } 780 781 if (UserCommandExists(name_cstr)) 782 { 783 if (can_replace == false) 784 return false; 785 if (m_user_dict[name]->IsRemovable() == false) 786 return false; 787 } 788 789 m_user_dict[name] = cmd_sp; 790 return true; 791 } 792 return false; 793 } 794 795 CommandObjectSP 796 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) 797 { 798 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command. 799 CommandObjectSP ret_val; // Possibly empty return value. 800 801 if (cmd_cstr == NULL) 802 return ret_val; 803 804 if (cmd_words.GetArgumentCount() == 1) 805 return GetCommandSP(cmd_cstr, include_aliases, true, NULL); 806 else 807 { 808 // We have a multi-word command (seemingly), so we need to do more work. 809 // First, get the cmd_obj_sp for the first word in the command. 810 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL); 811 if (cmd_obj_sp.get() != NULL) 812 { 813 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a 814 // command name), and find the appropriate sub-command SP for each command word.... 815 size_t end = cmd_words.GetArgumentCount(); 816 for (size_t j= 1; j < end; ++j) 817 { 818 if (cmd_obj_sp->IsMultiwordObject()) 819 { 820 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); 821 if (cmd_obj_sp.get() == NULL) 822 // The sub-command name was invalid. Fail and return the empty 'ret_val'. 823 return ret_val; 824 } 825 else 826 // We have more words in the command name, but we don't have a multiword object. Fail and return 827 // empty 'ret_val'. 828 return ret_val; 829 } 830 // We successfully looped through all the command words and got valid command objects for them. Assign the 831 // last object retrieved to 'ret_val'. 832 ret_val = cmd_obj_sp; 833 } 834 } 835 return ret_val; 836 } 837 838 CommandObject * 839 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) 840 { 841 return GetCommandSPExact (cmd_cstr, include_aliases).get(); 842 } 843 844 CommandObject * 845 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) 846 { 847 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); 848 849 // If we didn't find an exact match to the command string in the commands, look in 850 // the aliases. 851 852 if (command_obj) 853 return command_obj; 854 855 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); 856 857 if (command_obj) 858 return command_obj; 859 860 // If there wasn't an exact match then look for an inexact one in just the commands 861 command_obj = GetCommandSP(cmd_cstr, false, false, NULL).get(); 862 863 // Finally, if there wasn't an inexact match among the commands, look for an inexact 864 // match in both the commands and aliases. 865 866 if (command_obj) 867 { 868 if (matches) 869 matches->AppendString(command_obj->GetCommandName()); 870 return command_obj; 871 } 872 873 return GetCommandSP(cmd_cstr, true, false, matches).get(); 874 } 875 876 bool 877 CommandInterpreter::CommandExists (const char *cmd) 878 { 879 return m_command_dict.find(cmd) != m_command_dict.end(); 880 } 881 882 bool 883 CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, 884 const char *options_args, 885 OptionArgVectorSP &option_arg_vector_sp) 886 { 887 bool success = true; 888 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 889 890 if (!options_args || (strlen (options_args) < 1)) 891 return true; 892 893 std::string options_string (options_args); 894 Args args (options_args); 895 CommandReturnObject result; 896 // Check to see if the command being aliased can take any command options. 897 Options *options = cmd_obj_sp->GetOptions (); 898 if (options) 899 { 900 // See if any options were specified as part of the alias; if so, handle them appropriately. 901 options->NotifyOptionParsingStarting (); 902 args.Unshift ("dummy_arg"); 903 args.ParseAliasOptions (*options, result, option_arg_vector, options_string); 904 args.Shift (); 905 if (result.Succeeded()) 906 options->VerifyPartialOptions (result); 907 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 908 { 909 result.AppendError ("Unable to create requested alias.\n"); 910 return false; 911 } 912 } 913 914 if (!options_string.empty()) 915 { 916 if (cmd_obj_sp->WantsRawCommandString ()) 917 option_arg_vector->push_back (OptionArgPair ("<argument>", 918 OptionArgValue (-1, 919 options_string))); 920 else 921 { 922 const size_t argc = args.GetArgumentCount(); 923 for (size_t i = 0; i < argc; ++i) 924 if (strcmp (args.GetArgumentAtIndex (i), "") != 0) 925 option_arg_vector->push_back 926 (OptionArgPair ("<argument>", 927 OptionArgValue (-1, 928 std::string (args.GetArgumentAtIndex (i))))); 929 } 930 } 931 932 return success; 933 } 934 935 bool 936 CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name) 937 { 938 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); 939 if (exact_match) 940 { 941 full_name.assign(cmd); 942 return exact_match; 943 } 944 else 945 { 946 StringList matches; 947 size_t num_alias_matches; 948 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches); 949 if (num_alias_matches == 1) 950 { 951 // Make sure this isn't shadowing a command in the regular command space: 952 StringList regular_matches; 953 const bool include_aliases = false; 954 const bool exact = false; 955 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches)); 956 if (cmd_obj_sp || regular_matches.GetSize() > 0) 957 return false; 958 else 959 { 960 full_name.assign (matches.GetStringAtIndex(0)); 961 return true; 962 } 963 } 964 else 965 return false; 966 } 967 } 968 969 bool 970 CommandInterpreter::AliasExists (const char *cmd) 971 { 972 return m_alias_dict.find(cmd) != m_alias_dict.end(); 973 } 974 975 bool 976 CommandInterpreter::UserCommandExists (const char *cmd) 977 { 978 return m_user_dict.find(cmd) != m_user_dict.end(); 979 } 980 981 void 982 CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp) 983 { 984 command_obj_sp->SetIsAlias (true); 985 m_alias_dict[alias_name] = command_obj_sp; 986 } 987 988 bool 989 CommandInterpreter::RemoveAlias (const char *alias_name) 990 { 991 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name); 992 if (pos != m_alias_dict.end()) 993 { 994 m_alias_dict.erase(pos); 995 return true; 996 } 997 return false; 998 } 999 bool 1000 CommandInterpreter::RemoveUser (const char *alias_name) 1001 { 1002 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); 1003 if (pos != m_user_dict.end()) 1004 { 1005 m_user_dict.erase(pos); 1006 return true; 1007 } 1008 return false; 1009 } 1010 1011 void 1012 CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string) 1013 { 1014 help_string.Printf ("'%s", command_name); 1015 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1016 1017 if (option_arg_vector_sp) 1018 { 1019 OptionArgVector *options = option_arg_vector_sp.get(); 1020 for (size_t i = 0; i < options->size(); ++i) 1021 { 1022 OptionArgPair cur_option = (*options)[i]; 1023 std::string opt = cur_option.first; 1024 OptionArgValue value_pair = cur_option.second; 1025 std::string value = value_pair.second; 1026 if (opt.compare("<argument>") == 0) 1027 { 1028 help_string.Printf (" %s", value.c_str()); 1029 } 1030 else 1031 { 1032 help_string.Printf (" %s", opt.c_str()); 1033 if ((value.compare ("<no-argument>") != 0) 1034 && (value.compare ("<need-argument") != 0)) 1035 { 1036 help_string.Printf (" %s", value.c_str()); 1037 } 1038 } 1039 } 1040 } 1041 1042 help_string.Printf ("'"); 1043 } 1044 1045 size_t 1046 CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict) 1047 { 1048 CommandObject::CommandMap::const_iterator pos; 1049 CommandObject::CommandMap::const_iterator end = dict.end(); 1050 size_t max_len = 0; 1051 1052 for (pos = dict.begin(); pos != end; ++pos) 1053 { 1054 size_t len = pos->first.size(); 1055 if (max_len < len) 1056 max_len = len; 1057 } 1058 return max_len; 1059 } 1060 1061 void 1062 CommandInterpreter::GetHelp (CommandReturnObject &result, 1063 uint32_t cmd_types) 1064 { 1065 CommandObject::CommandMap::const_iterator pos; 1066 size_t max_len = FindLongestCommandWord (m_command_dict); 1067 1068 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) 1069 { 1070 1071 result.AppendMessage("The following is a list of built-in, permanent debugger commands:"); 1072 result.AppendMessage(""); 1073 1074 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 1075 { 1076 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1077 max_len); 1078 } 1079 result.AppendMessage(""); 1080 1081 } 1082 1083 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) 1084 { 1085 result.AppendMessage("The following is a list of your current command abbreviations " 1086 "(see 'help command alias' for more info):"); 1087 result.AppendMessage(""); 1088 max_len = FindLongestCommandWord (m_alias_dict); 1089 1090 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos) 1091 { 1092 StreamString sstr; 1093 StreamString translation_and_help; 1094 std::string entry_name = pos->first; 1095 std::string second_entry = pos->second.get()->GetCommandName(); 1096 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr); 1097 1098 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp()); 1099 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 1100 translation_and_help.GetData(), max_len); 1101 } 1102 result.AppendMessage(""); 1103 } 1104 1105 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) 1106 { 1107 result.AppendMessage ("The following is a list of your current user-defined commands:"); 1108 result.AppendMessage(""); 1109 max_len = FindLongestCommandWord (m_user_dict); 1110 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 1111 { 1112 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1113 max_len); 1114 } 1115 result.AppendMessage(""); 1116 } 1117 1118 result.AppendMessage("For more information on any particular command, try 'help <command-name>'."); 1119 } 1120 1121 CommandObject * 1122 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) 1123 { 1124 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will 1125 // eventually be invoked by the given command line. 1126 1127 CommandObject *cmd_obj = NULL; 1128 std::string white_space (" \t\v"); 1129 size_t start = command_string.find_first_not_of (white_space); 1130 size_t end = 0; 1131 bool done = false; 1132 while (!done) 1133 { 1134 if (start != std::string::npos) 1135 { 1136 // Get the next word from command_string. 1137 end = command_string.find_first_of (white_space, start); 1138 if (end == std::string::npos) 1139 end = command_string.size(); 1140 std::string cmd_word = command_string.substr (start, end - start); 1141 1142 if (cmd_obj == NULL) 1143 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid 1144 // command or alias. 1145 cmd_obj = GetCommandObject (cmd_word.c_str()); 1146 else if (cmd_obj->IsMultiwordObject ()) 1147 { 1148 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object. 1149 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str()); 1150 if (sub_cmd_obj) 1151 cmd_obj = sub_cmd_obj; 1152 else // cmd_word was not a valid sub-command word, so we are donee 1153 done = true; 1154 } 1155 else 1156 // We have a cmd_obj and it is not a multi-word object, so we are done. 1157 done = true; 1158 1159 // If we didn't find a valid command object, or our command object is not a multi-word object, or 1160 // we are at the end of the command_string, then we are done. Otherwise, find the start of the 1161 // next word. 1162 1163 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) 1164 done = true; 1165 else 1166 start = command_string.find_first_not_of (white_space, end); 1167 } 1168 else 1169 // Unable to find any more words. 1170 done = true; 1171 } 1172 1173 if (end == command_string.size()) 1174 command_string.clear(); 1175 else 1176 command_string = command_string.substr(end); 1177 1178 return cmd_obj; 1179 } 1180 1181 static const char *k_white_space = " \t\v"; 1182 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; 1183 static void 1184 StripLeadingSpaces (std::string &s) 1185 { 1186 if (!s.empty()) 1187 { 1188 size_t pos = s.find_first_not_of (k_white_space); 1189 if (pos == std::string::npos) 1190 s.clear(); 1191 else if (pos == 0) 1192 return; 1193 s.erase (0, pos); 1194 } 1195 } 1196 1197 static size_t 1198 FindArgumentTerminator (const std::string &s) 1199 { 1200 const size_t s_len = s.size(); 1201 size_t offset = 0; 1202 while (offset < s_len) 1203 { 1204 size_t pos = s.find ("--", offset); 1205 if (pos == std::string::npos) 1206 break; 1207 if (pos > 0) 1208 { 1209 if (isspace(s[pos-1])) 1210 { 1211 // Check if the string ends "\s--" (where \s is a space character) 1212 // or if we have "\s--\s". 1213 if ((pos + 2 >= s_len) || isspace(s[pos+2])) 1214 { 1215 return pos; 1216 } 1217 } 1218 } 1219 offset = pos + 2; 1220 } 1221 return std::string::npos; 1222 } 1223 1224 static bool 1225 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char) 1226 { 1227 command.clear(); 1228 suffix.clear(); 1229 StripLeadingSpaces (command_string); 1230 1231 bool result = false; 1232 quote_char = '\0'; 1233 1234 if (!command_string.empty()) 1235 { 1236 const char first_char = command_string[0]; 1237 if (first_char == '\'' || first_char == '"') 1238 { 1239 quote_char = first_char; 1240 const size_t end_quote_pos = command_string.find (quote_char, 1); 1241 if (end_quote_pos == std::string::npos) 1242 { 1243 command.swap (command_string); 1244 command_string.erase (); 1245 } 1246 else 1247 { 1248 command.assign (command_string, 1, end_quote_pos - 1); 1249 if (end_quote_pos + 1 < command_string.size()) 1250 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1)); 1251 else 1252 command_string.erase (); 1253 } 1254 } 1255 else 1256 { 1257 const size_t first_space_pos = command_string.find_first_of (k_white_space); 1258 if (first_space_pos == std::string::npos) 1259 { 1260 command.swap (command_string); 1261 command_string.erase(); 1262 } 1263 else 1264 { 1265 command.assign (command_string, 0, first_space_pos); 1266 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos)); 1267 } 1268 } 1269 result = true; 1270 } 1271 1272 1273 if (!command.empty()) 1274 { 1275 // actual commands can't start with '-' or '_' 1276 if (command[0] != '-' && command[0] != '_') 1277 { 1278 size_t pos = command.find_first_not_of(k_valid_command_chars); 1279 if (pos > 0 && pos != std::string::npos) 1280 { 1281 suffix.assign (command.begin() + pos, command.end()); 1282 command.erase (pos); 1283 } 1284 } 1285 } 1286 1287 return result; 1288 } 1289 1290 CommandObject * 1291 CommandInterpreter::BuildAliasResult (const char *alias_name, 1292 std::string &raw_input_string, 1293 std::string &alias_result, 1294 CommandReturnObject &result) 1295 { 1296 CommandObject *alias_cmd_obj = NULL; 1297 Args cmd_args (raw_input_string.c_str()); 1298 alias_cmd_obj = GetCommandObject (alias_name); 1299 StreamString result_str; 1300 1301 if (alias_cmd_obj) 1302 { 1303 std::string alias_name_str = alias_name; 1304 if ((cmd_args.GetArgumentCount() == 0) 1305 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) 1306 cmd_args.Unshift (alias_name); 1307 1308 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); 1309 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1310 1311 if (option_arg_vector_sp.get()) 1312 { 1313 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 1314 1315 for (size_t i = 0; i < option_arg_vector->size(); ++i) 1316 { 1317 OptionArgPair option_pair = (*option_arg_vector)[i]; 1318 OptionArgValue value_pair = option_pair.second; 1319 int value_type = value_pair.first; 1320 std::string option = option_pair.first; 1321 std::string value = value_pair.second; 1322 if (option.compare ("<argument>") == 0) 1323 result_str.Printf (" %s", value.c_str()); 1324 else 1325 { 1326 result_str.Printf (" %s", option.c_str()); 1327 if (value_type != OptionParser::eOptionalArgument) 1328 result_str.Printf (" "); 1329 if (value.compare ("<OptionParser::eNoArgument>") != 0) 1330 { 1331 int index = GetOptionArgumentPosition (value.c_str()); 1332 if (index == 0) 1333 result_str.Printf ("%s", value.c_str()); 1334 else if (index >= cmd_args.GetArgumentCount()) 1335 { 1336 1337 result.AppendErrorWithFormat 1338 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 1339 index); 1340 result.SetStatus (eReturnStatusFailed); 1341 return alias_cmd_obj; 1342 } 1343 else 1344 { 1345 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 1346 if (strpos != std::string::npos) 1347 raw_input_string = raw_input_string.erase (strpos, 1348 strlen (cmd_args.GetArgumentAtIndex (index))); 1349 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index)); 1350 } 1351 } 1352 } 1353 } 1354 } 1355 1356 alias_result = result_str.GetData(); 1357 } 1358 return alias_cmd_obj; 1359 } 1360 1361 Error 1362 CommandInterpreter::PreprocessCommand (std::string &command) 1363 { 1364 // The command preprocessor needs to do things to the command 1365 // line before any parsing of arguments or anything else is done. 1366 // The only current stuff that gets proprocessed is anyting enclosed 1367 // in backtick ('`') characters is evaluated as an expression and 1368 // the result of the expression must be a scalar that can be substituted 1369 // into the command. An example would be: 1370 // (lldb) memory read `$rsp + 20` 1371 Error error; // Error for any expressions that might not evaluate 1372 size_t start_backtick; 1373 size_t pos = 0; 1374 while ((start_backtick = command.find ('`', pos)) != std::string::npos) 1375 { 1376 if (start_backtick > 0 && command[start_backtick-1] == '\\') 1377 { 1378 // The backtick was preceeded by a '\' character, remove the slash 1379 // and don't treat the backtick as the start of an expression 1380 command.erase(start_backtick-1, 1); 1381 // No need to add one to start_backtick since we just deleted a char 1382 pos = start_backtick; 1383 } 1384 else 1385 { 1386 const size_t expr_content_start = start_backtick + 1; 1387 const size_t end_backtick = command.find ('`', expr_content_start); 1388 if (end_backtick == std::string::npos) 1389 return error; 1390 else if (end_backtick == expr_content_start) 1391 { 1392 // Empty expression (two backticks in a row) 1393 command.erase (start_backtick, 2); 1394 } 1395 else 1396 { 1397 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start); 1398 1399 ExecutionContext exe_ctx(GetExecutionContext()); 1400 Target *target = exe_ctx.GetTargetPtr(); 1401 // Get a dummy target to allow for calculator mode while processing backticks. 1402 // This also helps break the infinite loop caused when target is null. 1403 if (!target) 1404 target = Host::GetDummyTarget(GetDebugger()).get(); 1405 if (target) 1406 { 1407 ValueObjectSP expr_result_valobj_sp; 1408 1409 EvaluateExpressionOptions options; 1410 options.SetCoerceToId(false) 1411 .SetUnwindOnError(true) 1412 .SetIgnoreBreakpoints(true) 1413 .SetKeepInMemory(false) 1414 .SetRunOthers(true) 1415 .SetTimeoutUsec(0); 1416 1417 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1418 exe_ctx.GetFramePtr(), 1419 expr_result_valobj_sp, 1420 options); 1421 1422 if (expr_result == eExecutionCompleted) 1423 { 1424 Scalar scalar; 1425 if (expr_result_valobj_sp->ResolveValue (scalar)) 1426 { 1427 command.erase (start_backtick, end_backtick - start_backtick + 1); 1428 StreamString value_strm; 1429 const bool show_type = false; 1430 scalar.GetValue (&value_strm, show_type); 1431 size_t value_string_size = value_strm.GetSize(); 1432 if (value_string_size) 1433 { 1434 command.insert (start_backtick, value_strm.GetData(), value_string_size); 1435 pos = start_backtick + value_string_size; 1436 continue; 1437 } 1438 else 1439 { 1440 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1441 } 1442 } 1443 else 1444 { 1445 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1446 } 1447 } 1448 else 1449 { 1450 if (expr_result_valobj_sp) 1451 error = expr_result_valobj_sp->GetError(); 1452 if (error.Success()) 1453 { 1454 1455 switch (expr_result) 1456 { 1457 case eExecutionSetupError: 1458 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str()); 1459 break; 1460 case eExecutionCompleted: 1461 break; 1462 case eExecutionDiscarded: 1463 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str()); 1464 break; 1465 case eExecutionInterrupted: 1466 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str()); 1467 break; 1468 case eExecutionHitBreakpoint: 1469 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str()); 1470 break; 1471 case eExecutionTimedOut: 1472 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str()); 1473 break; 1474 } 1475 } 1476 } 1477 } 1478 } 1479 if (error.Fail()) 1480 break; 1481 } 1482 } 1483 return error; 1484 } 1485 1486 1487 bool 1488 CommandInterpreter::HandleCommand (const char *command_line, 1489 LazyBool lazy_add_to_history, 1490 CommandReturnObject &result, 1491 ExecutionContext *override_context, 1492 bool repeat_on_empty_command, 1493 bool no_context_switching) 1494 1495 { 1496 1497 bool done = false; 1498 CommandObject *cmd_obj = NULL; 1499 bool wants_raw_input = false; 1500 std::string command_string (command_line); 1501 std::string original_command_string (command_line); 1502 1503 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); 1504 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); 1505 1506 // Make a scoped cleanup object that will clear the crash description string 1507 // on exit of this function. 1508 lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription); 1509 1510 if (log) 1511 log->Printf ("Processing command: %s", command_line); 1512 1513 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line); 1514 1515 if (!no_context_switching) 1516 UpdateExecutionContext (override_context); 1517 1518 bool add_to_history; 1519 if (lazy_add_to_history == eLazyBoolCalculate) 1520 add_to_history = (m_command_source_depth == 0); 1521 else 1522 add_to_history = (lazy_add_to_history == eLazyBoolYes); 1523 1524 bool empty_command = false; 1525 bool comment_command = false; 1526 if (command_string.empty()) 1527 empty_command = true; 1528 else 1529 { 1530 const char *k_space_characters = "\t\n\v\f\r "; 1531 1532 size_t non_space = command_string.find_first_not_of (k_space_characters); 1533 // Check for empty line or comment line (lines whose first 1534 // non-space character is the comment character for this interpreter) 1535 if (non_space == std::string::npos) 1536 empty_command = true; 1537 else if (command_string[non_space] == m_comment_char) 1538 comment_command = true; 1539 else if (command_string[non_space] == CommandHistory::g_repeat_char) 1540 { 1541 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space); 1542 if (history_string == NULL) 1543 { 1544 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); 1545 result.SetStatus(eReturnStatusFailed); 1546 return false; 1547 } 1548 add_to_history = false; 1549 command_string = history_string; 1550 original_command_string = history_string; 1551 } 1552 } 1553 1554 if (empty_command) 1555 { 1556 if (repeat_on_empty_command) 1557 { 1558 if (m_command_history.IsEmpty()) 1559 { 1560 result.AppendError ("empty command"); 1561 result.SetStatus(eReturnStatusFailed); 1562 return false; 1563 } 1564 else 1565 { 1566 command_line = m_repeat_command.c_str(); 1567 command_string = command_line; 1568 original_command_string = command_line; 1569 if (m_repeat_command.empty()) 1570 { 1571 result.AppendErrorWithFormat("No auto repeat.\n"); 1572 result.SetStatus (eReturnStatusFailed); 1573 return false; 1574 } 1575 } 1576 add_to_history = false; 1577 } 1578 else 1579 { 1580 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1581 return true; 1582 } 1583 } 1584 else if (comment_command) 1585 { 1586 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1587 return true; 1588 } 1589 1590 1591 Error error (PreprocessCommand (command_string)); 1592 1593 if (error.Fail()) 1594 { 1595 result.AppendError (error.AsCString()); 1596 result.SetStatus(eReturnStatusFailed); 1597 return false; 1598 } 1599 // Phase 1. 1600 1601 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object 1602 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that 1603 // the user could have specified an alias, and in translating the alias there may also be command options and/or 1604 // even data (including raw text strings) that need to be found and inserted into the command line as part of 1605 // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command 1606 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions & 1607 // replacements taken care of; 3). whether or not the Execute function wants raw input or not. 1608 1609 StreamString revised_command_line; 1610 size_t actual_cmd_name_len = 0; 1611 std::string next_word; 1612 StringList matches; 1613 while (!done) 1614 { 1615 char quote_char = '\0'; 1616 std::string suffix; 1617 ExtractCommand (command_string, next_word, suffix, quote_char); 1618 if (cmd_obj == NULL) 1619 { 1620 std::string full_name; 1621 if (GetAliasFullName(next_word.c_str(), full_name)) 1622 { 1623 std::string alias_result; 1624 cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result); 1625 revised_command_line.Printf ("%s", alias_result.c_str()); 1626 if (cmd_obj) 1627 { 1628 wants_raw_input = cmd_obj->WantsRawCommandString (); 1629 actual_cmd_name_len = strlen (cmd_obj->GetCommandName()); 1630 } 1631 } 1632 else 1633 { 1634 cmd_obj = GetCommandObject (next_word.c_str(), &matches); 1635 if (cmd_obj) 1636 { 1637 actual_cmd_name_len += next_word.length(); 1638 revised_command_line.Printf ("%s", next_word.c_str()); 1639 wants_raw_input = cmd_obj->WantsRawCommandString (); 1640 } 1641 else 1642 { 1643 revised_command_line.Printf ("%s", next_word.c_str()); 1644 } 1645 } 1646 } 1647 else 1648 { 1649 if (cmd_obj->IsMultiwordObject ()) 1650 { 1651 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str()); 1652 if (sub_cmd_obj) 1653 { 1654 actual_cmd_name_len += next_word.length() + 1; 1655 revised_command_line.Printf (" %s", next_word.c_str()); 1656 cmd_obj = sub_cmd_obj; 1657 wants_raw_input = cmd_obj->WantsRawCommandString (); 1658 } 1659 else 1660 { 1661 if (quote_char) 1662 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 1663 else 1664 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str()); 1665 done = true; 1666 } 1667 } 1668 else 1669 { 1670 if (quote_char) 1671 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 1672 else 1673 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str()); 1674 done = true; 1675 } 1676 } 1677 1678 if (cmd_obj == NULL) 1679 { 1680 const size_t num_matches = matches.GetSize(); 1681 if (matches.GetSize() > 1) { 1682 StreamString error_msg; 1683 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str()); 1684 1685 for (uint32_t i = 0; i < num_matches; ++i) { 1686 error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i)); 1687 } 1688 result.AppendRawError (error_msg.GetString().c_str()); 1689 } else { 1690 // We didn't have only one match, otherwise we wouldn't get here. 1691 assert(num_matches == 0); 1692 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str()); 1693 } 1694 result.SetStatus (eReturnStatusFailed); 1695 return false; 1696 } 1697 1698 if (cmd_obj->IsMultiwordObject ()) 1699 { 1700 if (!suffix.empty()) 1701 { 1702 1703 result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n", 1704 cmd_obj->GetCommandName(), 1705 next_word.empty() ? "" : next_word.c_str(), 1706 next_word.empty() ? " -- " : " ", 1707 suffix.c_str()); 1708 result.SetStatus (eReturnStatusFailed); 1709 return false; 1710 } 1711 } 1712 else 1713 { 1714 // If we found a normal command, we are done 1715 done = true; 1716 if (!suffix.empty()) 1717 { 1718 switch (suffix[0]) 1719 { 1720 case '/': 1721 // GDB format suffixes 1722 { 1723 Options *command_options = cmd_obj->GetOptions(); 1724 if (command_options && command_options->SupportsLongOption("gdb-format")) 1725 { 1726 std::string gdb_format_option ("--gdb-format="); 1727 gdb_format_option += (suffix.c_str() + 1); 1728 1729 bool inserted = false; 1730 std::string &cmd = revised_command_line.GetString(); 1731 size_t arg_terminator_idx = FindArgumentTerminator (cmd); 1732 if (arg_terminator_idx != std::string::npos) 1733 { 1734 // Insert the gdb format option before the "--" that terminates options 1735 gdb_format_option.append(1,' '); 1736 cmd.insert(arg_terminator_idx, gdb_format_option); 1737 inserted = true; 1738 } 1739 1740 if (!inserted) 1741 revised_command_line.Printf (" %s", gdb_format_option.c_str()); 1742 1743 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos) 1744 revised_command_line.PutCString (" --"); 1745 } 1746 else 1747 { 1748 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n", 1749 cmd_obj->GetCommandName()); 1750 result.SetStatus (eReturnStatusFailed); 1751 return false; 1752 } 1753 } 1754 break; 1755 1756 default: 1757 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n", 1758 suffix.c_str()); 1759 result.SetStatus (eReturnStatusFailed); 1760 return false; 1761 1762 } 1763 } 1764 } 1765 if (command_string.length() == 0) 1766 done = true; 1767 1768 } 1769 1770 if (!command_string.empty()) 1771 revised_command_line.Printf (" %s", command_string.c_str()); 1772 1773 // End of Phase 1. 1774 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command 1775 // specified was valid; revised_command_line contains the complete command line (including command name(s)), 1776 // fully translated with all substitutions & translations taken care of (still in raw text format); and 1777 // wants_raw_input specifies whether the Execute method expects raw input or not. 1778 1779 1780 if (log) 1781 { 1782 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); 1783 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData()); 1784 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); 1785 } 1786 1787 // Phase 2. 1788 // Take care of things like setting up the history command & calling the appropriate Execute method on the 1789 // CommandObject, with the appropriate arguments. 1790 1791 if (cmd_obj != NULL) 1792 { 1793 if (add_to_history) 1794 { 1795 Args command_args (revised_command_line.GetData()); 1796 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); 1797 if (repeat_command != NULL) 1798 m_repeat_command.assign(repeat_command); 1799 else 1800 m_repeat_command.assign(original_command_string.c_str()); 1801 1802 m_command_history.AppendString (original_command_string); 1803 } 1804 1805 command_string = revised_command_line.GetData(); 1806 std::string command_name (cmd_obj->GetCommandName()); 1807 std::string remainder; 1808 if (actual_cmd_name_len < command_string.length()) 1809 remainder = command_string.substr (actual_cmd_name_len); // Note: 'actual_cmd_name_len' may be considerably shorter 1810 // than cmd_obj->GetCommandName(), because name completion 1811 // allows users to enter short versions of the names, 1812 // e.g. 'br s' for 'breakpoint set'. 1813 1814 // Remove any initial spaces 1815 std::string white_space (" \t\v"); 1816 size_t pos = remainder.find_first_not_of (white_space); 1817 if (pos != 0 && pos != std::string::npos) 1818 remainder.erase(0, pos); 1819 1820 if (log) 1821 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str()); 1822 1823 cmd_obj->Execute (remainder.c_str(), result); 1824 } 1825 else 1826 { 1827 // We didn't find the first command object, so complete the first argument. 1828 Args command_args (revised_command_line.GetData()); 1829 StringList matches; 1830 int num_matches; 1831 int cursor_index = 0; 1832 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); 1833 bool word_complete; 1834 num_matches = HandleCompletionMatches (command_args, 1835 cursor_index, 1836 cursor_char_position, 1837 0, 1838 -1, 1839 word_complete, 1840 matches); 1841 1842 if (num_matches > 0) 1843 { 1844 std::string error_msg; 1845 error_msg.assign ("ambiguous command '"); 1846 error_msg.append(command_args.GetArgumentAtIndex(0)); 1847 error_msg.append ("'."); 1848 1849 error_msg.append (" Possible completions:"); 1850 for (int i = 0; i < num_matches; i++) 1851 { 1852 error_msg.append ("\n\t"); 1853 error_msg.append (matches.GetStringAtIndex (i)); 1854 } 1855 error_msg.append ("\n"); 1856 result.AppendRawError (error_msg.c_str()); 1857 } 1858 else 1859 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0)); 1860 1861 result.SetStatus (eReturnStatusFailed); 1862 } 1863 1864 if (log) 1865 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed")); 1866 1867 return result.Succeeded(); 1868 } 1869 1870 int 1871 CommandInterpreter::HandleCompletionMatches (Args &parsed_line, 1872 int &cursor_index, 1873 int &cursor_char_position, 1874 int match_start_point, 1875 int max_return_elements, 1876 bool &word_complete, 1877 StringList &matches) 1878 { 1879 int num_command_matches = 0; 1880 bool look_for_subcommand = false; 1881 1882 // For any of the command completions a unique match will be a complete word. 1883 word_complete = true; 1884 1885 if (cursor_index == -1) 1886 { 1887 // We got nothing on the command line, so return the list of commands 1888 bool include_aliases = true; 1889 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches); 1890 } 1891 else if (cursor_index == 0) 1892 { 1893 // The cursor is in the first argument, so just do a lookup in the dictionary. 1894 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches); 1895 num_command_matches = matches.GetSize(); 1896 1897 if (num_command_matches == 1 1898 && cmd_obj && cmd_obj->IsMultiwordObject() 1899 && matches.GetStringAtIndex(0) != NULL 1900 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 1901 { 1902 look_for_subcommand = true; 1903 num_command_matches = 0; 1904 matches.DeleteStringAtIndex(0); 1905 parsed_line.AppendArgument (""); 1906 cursor_index++; 1907 cursor_char_position = 0; 1908 } 1909 } 1910 1911 if (cursor_index > 0 || look_for_subcommand) 1912 { 1913 // We are completing further on into a commands arguments, so find the command and tell it 1914 // to complete the command. 1915 // First see if there is a matching initial command: 1916 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); 1917 if (command_object == NULL) 1918 { 1919 return 0; 1920 } 1921 else 1922 { 1923 parsed_line.Shift(); 1924 cursor_index--; 1925 num_command_matches = command_object->HandleCompletion (parsed_line, 1926 cursor_index, 1927 cursor_char_position, 1928 match_start_point, 1929 max_return_elements, 1930 word_complete, 1931 matches); 1932 } 1933 } 1934 1935 return num_command_matches; 1936 1937 } 1938 1939 int 1940 CommandInterpreter::HandleCompletion (const char *current_line, 1941 const char *cursor, 1942 const char *last_char, 1943 int match_start_point, 1944 int max_return_elements, 1945 StringList &matches) 1946 { 1947 // We parse the argument up to the cursor, so the last argument in parsed_line is 1948 // the one containing the cursor, and the cursor is after the last character. 1949 1950 Args parsed_line(current_line, last_char - current_line); 1951 Args partial_parsed_line(current_line, cursor - current_line); 1952 1953 // Don't complete comments, and if the line we are completing is just the history repeat character, 1954 // substitute the appropriate history line. 1955 const char *first_arg = parsed_line.GetArgumentAtIndex(0); 1956 if (first_arg) 1957 { 1958 if (first_arg[0] == m_comment_char) 1959 return 0; 1960 else if (first_arg[0] == CommandHistory::g_repeat_char) 1961 { 1962 const char *history_string = m_command_history.FindString (first_arg); 1963 if (history_string != NULL) 1964 { 1965 matches.Clear(); 1966 matches.InsertStringAtIndex(0, history_string); 1967 return -2; 1968 } 1969 else 1970 return 0; 1971 1972 } 1973 } 1974 1975 1976 int num_args = partial_parsed_line.GetArgumentCount(); 1977 int cursor_index = partial_parsed_line.GetArgumentCount() - 1; 1978 int cursor_char_position; 1979 1980 if (cursor_index == -1) 1981 cursor_char_position = 0; 1982 else 1983 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index)); 1984 1985 if (cursor > current_line && cursor[-1] == ' ') 1986 { 1987 // We are just after a space. If we are in an argument, then we will continue 1988 // parsing, but if we are between arguments, then we have to complete whatever the next 1989 // element would be. 1990 // We can distinguish the two cases because if we are in an argument (e.g. because the space is 1991 // protected by a quote) then the space will also be in the parsed argument... 1992 1993 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index); 1994 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ') 1995 { 1996 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '"'); 1997 cursor_index++; 1998 cursor_char_position = 0; 1999 } 2000 } 2001 2002 int num_command_matches; 2003 2004 matches.Clear(); 2005 2006 // Only max_return_elements == -1 is supported at present: 2007 assert (max_return_elements == -1); 2008 bool word_complete; 2009 num_command_matches = HandleCompletionMatches (parsed_line, 2010 cursor_index, 2011 cursor_char_position, 2012 match_start_point, 2013 max_return_elements, 2014 word_complete, 2015 matches); 2016 2017 if (num_command_matches <= 0) 2018 return num_command_matches; 2019 2020 if (num_args == 0) 2021 { 2022 // If we got an empty string, insert nothing. 2023 matches.InsertStringAtIndex(0, ""); 2024 } 2025 else 2026 { 2027 // Now figure out if there is a common substring, and if so put that in element 0, otherwise 2028 // put an empty string in element 0. 2029 std::string command_partial_str; 2030 if (cursor_index >= 0) 2031 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), 2032 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position); 2033 2034 std::string common_prefix; 2035 matches.LongestCommonPrefix (common_prefix); 2036 const size_t partial_name_len = command_partial_str.size(); 2037 2038 // If we matched a unique single command, add a space... 2039 // Only do this if the completer told us this was a complete word, however... 2040 if (num_command_matches == 1 && word_complete) 2041 { 2042 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); 2043 if (quote_char != '\0') 2044 common_prefix.push_back(quote_char); 2045 2046 common_prefix.push_back(' '); 2047 } 2048 common_prefix.erase (0, partial_name_len); 2049 matches.InsertStringAtIndex(0, common_prefix.c_str()); 2050 } 2051 return num_command_matches; 2052 } 2053 2054 2055 CommandInterpreter::~CommandInterpreter () 2056 { 2057 } 2058 2059 const char * 2060 CommandInterpreter::GetPrompt () 2061 { 2062 return m_debugger.GetPrompt(); 2063 } 2064 2065 void 2066 CommandInterpreter::SetPrompt (const char *new_prompt) 2067 { 2068 m_debugger.SetPrompt (new_prompt); 2069 } 2070 2071 size_t 2072 CommandInterpreter::GetConfirmationInputReaderCallback 2073 ( 2074 void *baton, 2075 InputReader &reader, 2076 lldb::InputReaderAction action, 2077 const char *bytes, 2078 size_t bytes_len 2079 ) 2080 { 2081 File &out_file = reader.GetDebugger().GetOutputFile(); 2082 bool *response_ptr = (bool *) baton; 2083 2084 switch (action) 2085 { 2086 case eInputReaderActivate: 2087 if (out_file.IsValid()) 2088 { 2089 if (reader.GetPrompt()) 2090 { 2091 out_file.Printf ("%s", reader.GetPrompt()); 2092 out_file.Flush (); 2093 } 2094 } 2095 break; 2096 2097 case eInputReaderDeactivate: 2098 break; 2099 2100 case eInputReaderReactivate: 2101 if (out_file.IsValid() && reader.GetPrompt()) 2102 { 2103 out_file.Printf ("%s", reader.GetPrompt()); 2104 out_file.Flush (); 2105 } 2106 break; 2107 2108 case eInputReaderAsynchronousOutputWritten: 2109 break; 2110 2111 case eInputReaderGotToken: 2112 if (bytes_len == 0) 2113 { 2114 reader.SetIsDone(true); 2115 } 2116 else if (bytes[0] == 'y' || bytes[0] == 'Y') 2117 { 2118 *response_ptr = true; 2119 reader.SetIsDone(true); 2120 } 2121 else if (bytes[0] == 'n' || bytes[0] == 'N') 2122 { 2123 *response_ptr = false; 2124 reader.SetIsDone(true); 2125 } 2126 else 2127 { 2128 if (out_file.IsValid() && !reader.IsDone() && reader.GetPrompt()) 2129 { 2130 out_file.Printf ("Please answer \"y\" or \"n\".\n%s", reader.GetPrompt()); 2131 out_file.Flush (); 2132 } 2133 } 2134 break; 2135 2136 case eInputReaderInterrupt: 2137 case eInputReaderEndOfFile: 2138 *response_ptr = false; // Assume ^C or ^D means cancel the proposed action 2139 reader.SetIsDone (true); 2140 break; 2141 2142 case eInputReaderDone: 2143 break; 2144 } 2145 2146 return bytes_len; 2147 2148 } 2149 2150 bool 2151 CommandInterpreter::Confirm (const char *message, bool default_answer) 2152 { 2153 // Check AutoConfirm first: 2154 if (m_debugger.GetAutoConfirm()) 2155 return default_answer; 2156 2157 InputReaderSP reader_sp (new InputReader(GetDebugger())); 2158 bool response = default_answer; 2159 if (reader_sp) 2160 { 2161 std::string prompt(message); 2162 prompt.append(": ["); 2163 if (default_answer) 2164 prompt.append ("Y/n] "); 2165 else 2166 prompt.append ("y/N] "); 2167 2168 Error err (reader_sp->Initialize (CommandInterpreter::GetConfirmationInputReaderCallback, 2169 &response, // baton 2170 eInputReaderGranularityLine, // token size, to pass to callback function 2171 NULL, // end token 2172 prompt.c_str(), // prompt 2173 true)); // echo input 2174 if (err.Success()) 2175 { 2176 GetDebugger().PushInputReader (reader_sp); 2177 } 2178 reader_sp->WaitOnReaderIsDone(); 2179 } 2180 return response; 2181 } 2182 2183 OptionArgVectorSP 2184 CommandInterpreter::GetAliasOptions (const char *alias_name) 2185 { 2186 OptionArgMap::iterator pos; 2187 OptionArgVectorSP ret_val; 2188 2189 std::string alias (alias_name); 2190 2191 if (HasAliasOptions()) 2192 { 2193 pos = m_alias_options.find (alias); 2194 if (pos != m_alias_options.end()) 2195 ret_val = pos->second; 2196 } 2197 2198 return ret_val; 2199 } 2200 2201 void 2202 CommandInterpreter::RemoveAliasOptions (const char *alias_name) 2203 { 2204 OptionArgMap::iterator pos = m_alias_options.find(alias_name); 2205 if (pos != m_alias_options.end()) 2206 { 2207 m_alias_options.erase (pos); 2208 } 2209 } 2210 2211 void 2212 CommandInterpreter::AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp) 2213 { 2214 m_alias_options[alias_name] = option_arg_vector_sp; 2215 } 2216 2217 bool 2218 CommandInterpreter::HasCommands () 2219 { 2220 return (!m_command_dict.empty()); 2221 } 2222 2223 bool 2224 CommandInterpreter::HasAliases () 2225 { 2226 return (!m_alias_dict.empty()); 2227 } 2228 2229 bool 2230 CommandInterpreter::HasUserCommands () 2231 { 2232 return (!m_user_dict.empty()); 2233 } 2234 2235 bool 2236 CommandInterpreter::HasAliasOptions () 2237 { 2238 return (!m_alias_options.empty()); 2239 } 2240 2241 void 2242 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, 2243 const char *alias_name, 2244 Args &cmd_args, 2245 std::string &raw_input_string, 2246 CommandReturnObject &result) 2247 { 2248 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 2249 2250 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); 2251 2252 // Make sure that the alias name is the 0th element in cmd_args 2253 std::string alias_name_str = alias_name; 2254 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) 2255 cmd_args.Unshift (alias_name); 2256 2257 Args new_args (alias_cmd_obj->GetCommandName()); 2258 if (new_args.GetArgumentCount() == 2) 2259 new_args.Shift(); 2260 2261 if (option_arg_vector_sp.get()) 2262 { 2263 if (wants_raw_input) 2264 { 2265 // We have a command that both has command options and takes raw input. Make *sure* it has a 2266 // " -- " in the right place in the raw_input_string. 2267 size_t pos = raw_input_string.find(" -- "); 2268 if (pos == std::string::npos) 2269 { 2270 // None found; assume it goes at the beginning of the raw input string 2271 raw_input_string.insert (0, " -- "); 2272 } 2273 } 2274 2275 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 2276 const size_t old_size = cmd_args.GetArgumentCount(); 2277 std::vector<bool> used (old_size + 1, false); 2278 2279 used[0] = true; 2280 2281 for (size_t i = 0; i < option_arg_vector->size(); ++i) 2282 { 2283 OptionArgPair option_pair = (*option_arg_vector)[i]; 2284 OptionArgValue value_pair = option_pair.second; 2285 int value_type = value_pair.first; 2286 std::string option = option_pair.first; 2287 std::string value = value_pair.second; 2288 if (option.compare ("<argument>") == 0) 2289 { 2290 if (!wants_raw_input 2291 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice 2292 new_args.AppendArgument (value.c_str()); 2293 } 2294 else 2295 { 2296 if (value_type != OptionParser::eOptionalArgument) 2297 new_args.AppendArgument (option.c_str()); 2298 if (value.compare ("<no-argument>") != 0) 2299 { 2300 int index = GetOptionArgumentPosition (value.c_str()); 2301 if (index == 0) 2302 { 2303 // value was NOT a positional argument; must be a real value 2304 if (value_type != OptionParser::eOptionalArgument) 2305 new_args.AppendArgument (value.c_str()); 2306 else 2307 { 2308 char buffer[255]; 2309 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str()); 2310 new_args.AppendArgument (buffer); 2311 } 2312 2313 } 2314 else if (index >= cmd_args.GetArgumentCount()) 2315 { 2316 result.AppendErrorWithFormat 2317 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 2318 index); 2319 result.SetStatus (eReturnStatusFailed); 2320 return; 2321 } 2322 else 2323 { 2324 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string 2325 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 2326 if (strpos != std::string::npos) 2327 { 2328 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index))); 2329 } 2330 2331 if (value_type != OptionParser::eOptionalArgument) 2332 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); 2333 else 2334 { 2335 char buffer[255]; 2336 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), 2337 cmd_args.GetArgumentAtIndex (index)); 2338 new_args.AppendArgument (buffer); 2339 } 2340 used[index] = true; 2341 } 2342 } 2343 } 2344 } 2345 2346 for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) 2347 { 2348 if (!used[j] && !wants_raw_input) 2349 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); 2350 } 2351 2352 cmd_args.Clear(); 2353 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); 2354 } 2355 else 2356 { 2357 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2358 // This alias was not created with any options; nothing further needs to be done, unless it is a command that 2359 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw 2360 // input string. 2361 if (wants_raw_input) 2362 { 2363 cmd_args.Clear(); 2364 cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); 2365 } 2366 return; 2367 } 2368 2369 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2370 return; 2371 } 2372 2373 2374 int 2375 CommandInterpreter::GetOptionArgumentPosition (const char *in_string) 2376 { 2377 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position 2378 // of zero. 2379 2380 char *cptr = (char *) in_string; 2381 2382 // Does it start with '%' 2383 if (cptr[0] == '%') 2384 { 2385 ++cptr; 2386 2387 // Is the rest of it entirely digits? 2388 if (isdigit (cptr[0])) 2389 { 2390 const char *start = cptr; 2391 while (isdigit (cptr[0])) 2392 ++cptr; 2393 2394 // We've gotten to the end of the digits; are we at the end of the string? 2395 if (cptr[0] == '\0') 2396 position = atoi (start); 2397 } 2398 } 2399 2400 return position; 2401 } 2402 2403 void 2404 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) 2405 { 2406 FileSpec init_file; 2407 if (in_cwd) 2408 { 2409 // In the current working directory we don't load any program specific 2410 // .lldbinit files, we only look for a "./.lldbinit" file. 2411 if (m_skip_lldbinit_files) 2412 return; 2413 2414 init_file.SetFile ("./.lldbinit", true); 2415 } 2416 else 2417 { 2418 // If we aren't looking in the current working directory we are looking 2419 // in the home directory. We will first see if there is an application 2420 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a 2421 // "-" and the name of the program. If this file doesn't exist, we fall 2422 // back to just the "~/.lldbinit" file. We also obey any requests to not 2423 // load the init files. 2424 const char *init_file_path = "~/.lldbinit"; 2425 2426 if (m_skip_app_init_files == false) 2427 { 2428 FileSpec program_file_spec (Host::GetProgramFileSpec()); 2429 const char *program_name = program_file_spec.GetFilename().AsCString(); 2430 2431 if (program_name) 2432 { 2433 char program_init_file_name[PATH_MAX]; 2434 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path, program_name); 2435 init_file.SetFile (program_init_file_name, true); 2436 if (!init_file.Exists()) 2437 init_file.Clear(); 2438 } 2439 } 2440 2441 if (!init_file && !m_skip_lldbinit_files) 2442 init_file.SetFile (init_file_path, true); 2443 } 2444 2445 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting 2446 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details). 2447 2448 if (init_file.Exists()) 2449 { 2450 ExecutionContext *exe_ctx = NULL; // We don't have any context yet. 2451 bool stop_on_continue = true; 2452 bool stop_on_error = false; 2453 bool echo_commands = false; 2454 bool print_results = false; 2455 2456 HandleCommandsFromFile (init_file, exe_ctx, stop_on_continue, stop_on_error, echo_commands, print_results, eLazyBoolNo, result); 2457 } 2458 else 2459 { 2460 // nothing to be done if the file doesn't exist 2461 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2462 } 2463 } 2464 2465 PlatformSP 2466 CommandInterpreter::GetPlatform (bool prefer_target_platform) 2467 { 2468 PlatformSP platform_sp; 2469 if (prefer_target_platform) 2470 { 2471 ExecutionContext exe_ctx(GetExecutionContext()); 2472 Target *target = exe_ctx.GetTargetPtr(); 2473 if (target) 2474 platform_sp = target->GetPlatform(); 2475 } 2476 2477 if (!platform_sp) 2478 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform(); 2479 return platform_sp; 2480 } 2481 2482 void 2483 CommandInterpreter::HandleCommands (const StringList &commands, 2484 ExecutionContext *override_context, 2485 bool stop_on_continue, 2486 bool stop_on_error, 2487 bool echo_commands, 2488 bool print_results, 2489 LazyBool add_to_history, 2490 CommandReturnObject &result) 2491 { 2492 size_t num_lines = commands.GetSize(); 2493 2494 // If we are going to continue past a "continue" then we need to run the commands synchronously. 2495 // Make sure you reset this value anywhere you return from the function. 2496 2497 bool old_async_execution = m_debugger.GetAsyncExecution(); 2498 2499 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will 2500 // cause series of commands that change the context, then do an operation that relies on that context to fail. 2501 2502 if (override_context != NULL) 2503 UpdateExecutionContext (override_context); 2504 2505 if (!stop_on_continue) 2506 { 2507 m_debugger.SetAsyncExecution (false); 2508 } 2509 2510 for (size_t idx = 0; idx < num_lines; idx++) 2511 { 2512 const char *cmd = commands.GetStringAtIndex(idx); 2513 if (cmd[0] == '\0') 2514 continue; 2515 2516 if (echo_commands) 2517 { 2518 result.AppendMessageWithFormat ("%s %s\n", 2519 GetPrompt(), 2520 cmd); 2521 } 2522 2523 CommandReturnObject tmp_result; 2524 // If override_context is not NULL, pass no_context_switching = true for 2525 // HandleCommand() since we updated our context already. 2526 2527 // We might call into a regex or alias command, in which case the add_to_history will get lost. This 2528 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here. 2529 if (!add_to_history) 2530 m_command_source_depth++; 2531 bool success = HandleCommand(cmd, add_to_history, tmp_result, 2532 NULL, /* override_context */ 2533 true, /* repeat_on_empty_command */ 2534 override_context != NULL /* no_context_switching */); 2535 if (!add_to_history) 2536 m_command_source_depth--; 2537 2538 if (print_results) 2539 { 2540 if (tmp_result.Succeeded()) 2541 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); 2542 } 2543 2544 if (!success || !tmp_result.Succeeded()) 2545 { 2546 const char *error_msg = tmp_result.GetErrorData(); 2547 if (error_msg == NULL || error_msg[0] == '\0') 2548 error_msg = "<unknown error>.\n"; 2549 if (stop_on_error) 2550 { 2551 result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' failed with %s", 2552 idx, cmd, error_msg); 2553 result.SetStatus (eReturnStatusFailed); 2554 m_debugger.SetAsyncExecution (old_async_execution); 2555 return; 2556 } 2557 else if (print_results) 2558 { 2559 result.AppendMessageWithFormat ("Command #%zu '%s' failed with %s", 2560 idx + 1, 2561 cmd, 2562 error_msg); 2563 } 2564 } 2565 2566 if (result.GetImmediateOutputStream()) 2567 result.GetImmediateOutputStream()->Flush(); 2568 2569 if (result.GetImmediateErrorStream()) 2570 result.GetImmediateErrorStream()->Flush(); 2571 2572 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution 2573 // could be running (for instance in Breakpoint Commands. 2574 // So we check the return value to see if it is has running in it. 2575 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) 2576 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) 2577 { 2578 if (stop_on_continue) 2579 { 2580 // If we caused the target to proceed, and we're going to stop in that case, set the 2581 // status in our real result before returning. This is an error if the continue was not the 2582 // last command in the set of commands to be run. 2583 if (idx != num_lines - 1) 2584 result.AppendErrorWithFormat("Aborting reading of commands after command #%zu: '%s' continued the target.\n", 2585 idx + 1, cmd); 2586 else 2587 result.AppendMessageWithFormat ("Command #%zu '%s' continued the target.\n", idx + 1, cmd); 2588 2589 result.SetStatus(tmp_result.GetStatus()); 2590 m_debugger.SetAsyncExecution (old_async_execution); 2591 2592 return; 2593 } 2594 } 2595 2596 } 2597 2598 result.SetStatus (eReturnStatusSuccessFinishResult); 2599 m_debugger.SetAsyncExecution (old_async_execution); 2600 2601 return; 2602 } 2603 2604 void 2605 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, 2606 ExecutionContext *context, 2607 bool stop_on_continue, 2608 bool stop_on_error, 2609 bool echo_command, 2610 bool print_result, 2611 LazyBool add_to_history, 2612 CommandReturnObject &result) 2613 { 2614 if (cmd_file.Exists()) 2615 { 2616 bool success; 2617 StringList commands; 2618 success = commands.ReadFileLines(cmd_file); 2619 if (!success) 2620 { 2621 result.AppendErrorWithFormat ("Error reading commands from file: %s.\n", cmd_file.GetFilename().AsCString()); 2622 result.SetStatus (eReturnStatusFailed); 2623 return; 2624 } 2625 m_command_source_depth++; 2626 HandleCommands (commands, context, stop_on_continue, stop_on_error, echo_command, print_result, add_to_history, result); 2627 m_command_source_depth--; 2628 } 2629 else 2630 { 2631 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", 2632 cmd_file.GetFilename().AsCString()); 2633 result.SetStatus (eReturnStatusFailed); 2634 return; 2635 } 2636 } 2637 2638 ScriptInterpreter * 2639 CommandInterpreter::GetScriptInterpreter (bool can_create) 2640 { 2641 if (m_script_interpreter_ap.get() != NULL) 2642 return m_script_interpreter_ap.get(); 2643 2644 if (!can_create) 2645 return NULL; 2646 2647 // <rdar://problem/11751427> 2648 // we need to protect the initialization of the script interpreter 2649 // otherwise we could end up with two threads both trying to create 2650 // their instance of it, and for some languages (e.g. Python) 2651 // this is a bulletproof recipe for disaster! 2652 // this needs to be a function-level static because multiple Debugger instances living in the same process 2653 // still need to be isolated and not try to initialize Python concurrently 2654 static Mutex g_interpreter_mutex(Mutex::eMutexTypeRecursive); 2655 Mutex::Locker interpreter_lock(g_interpreter_mutex); 2656 2657 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); 2658 if (log) 2659 log->Printf("Initializing the ScriptInterpreter now\n"); 2660 2661 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); 2662 switch (script_lang) 2663 { 2664 case eScriptLanguagePython: 2665 #ifndef LLDB_DISABLE_PYTHON 2666 m_script_interpreter_ap.reset (new ScriptInterpreterPython (*this)); 2667 break; 2668 #else 2669 // Fall through to the None case when python is disabled 2670 #endif 2671 case eScriptLanguageNone: 2672 m_script_interpreter_ap.reset (new ScriptInterpreterNone (*this)); 2673 break; 2674 }; 2675 2676 return m_script_interpreter_ap.get(); 2677 } 2678 2679 2680 2681 bool 2682 CommandInterpreter::GetSynchronous () 2683 { 2684 return m_synchronous_execution; 2685 } 2686 2687 void 2688 CommandInterpreter::SetSynchronous (bool value) 2689 { 2690 m_synchronous_execution = value; 2691 } 2692 2693 void 2694 CommandInterpreter::OutputFormattedHelpText (Stream &strm, 2695 const char *word_text, 2696 const char *separator, 2697 const char *help_text, 2698 size_t max_word_len) 2699 { 2700 const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2701 2702 int indent_size = max_word_len + strlen (separator) + 2; 2703 2704 strm.IndentMore (indent_size); 2705 2706 StreamString text_strm; 2707 text_strm.Printf ("%-*s %s %s", (int)max_word_len, word_text, separator, help_text); 2708 2709 size_t len = text_strm.GetSize(); 2710 const char *text = text_strm.GetData(); 2711 if (text[len - 1] == '\n') 2712 { 2713 text_strm.EOL(); 2714 len = text_strm.GetSize(); 2715 } 2716 2717 if (len < max_columns) 2718 { 2719 // Output it as a single line. 2720 strm.Printf ("%s", text); 2721 } 2722 else 2723 { 2724 // We need to break it up into multiple lines. 2725 bool first_line = true; 2726 int text_width; 2727 size_t start = 0; 2728 size_t end = start; 2729 const size_t final_end = strlen (text); 2730 2731 while (end < final_end) 2732 { 2733 if (first_line) 2734 text_width = max_columns - 1; 2735 else 2736 text_width = max_columns - indent_size - 1; 2737 2738 // Don't start the 'text' on a space, since we're already outputting the indentation. 2739 if (!first_line) 2740 { 2741 while ((start < final_end) && (text[start] == ' ')) 2742 start++; 2743 } 2744 2745 end = start + text_width; 2746 if (end > final_end) 2747 end = final_end; 2748 else 2749 { 2750 // If we're not at the end of the text, make sure we break the line on white space. 2751 while (end > start 2752 && text[end] != ' ' && text[end] != '\t' && text[end] != '\n') 2753 end--; 2754 assert (end > 0); 2755 } 2756 2757 const size_t sub_len = end - start; 2758 if (start != 0) 2759 strm.EOL(); 2760 if (!first_line) 2761 strm.Indent(); 2762 else 2763 first_line = false; 2764 assert (start <= final_end); 2765 assert (start + sub_len <= final_end); 2766 if (sub_len > 0) 2767 strm.Write (text + start, sub_len); 2768 start = end + 1; 2769 } 2770 } 2771 strm.EOL(); 2772 strm.IndentLess(indent_size); 2773 } 2774 2775 void 2776 CommandInterpreter::OutputHelpText (Stream &strm, 2777 const char *word_text, 2778 const char *separator, 2779 const char *help_text, 2780 uint32_t max_word_len) 2781 { 2782 int indent_size = max_word_len + strlen (separator) + 2; 2783 2784 strm.IndentMore (indent_size); 2785 2786 StreamString text_strm; 2787 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text); 2788 2789 const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2790 2791 size_t len = text_strm.GetSize(); 2792 const char *text = text_strm.GetData(); 2793 2794 uint32_t chars_left = max_columns; 2795 2796 for (uint32_t i = 0; i < len; i++) 2797 { 2798 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n') 2799 { 2800 chars_left = max_columns - indent_size; 2801 strm.EOL(); 2802 strm.Indent(); 2803 } 2804 else 2805 { 2806 strm.PutChar(text[i]); 2807 chars_left--; 2808 } 2809 2810 } 2811 2812 strm.EOL(); 2813 strm.IndentLess(indent_size); 2814 } 2815 2816 void 2817 CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found, 2818 StringList &commands_help, bool search_builtin_commands, bool search_user_commands) 2819 { 2820 CommandObject::CommandMap::const_iterator pos; 2821 2822 if (search_builtin_commands) 2823 { 2824 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 2825 { 2826 const char *command_name = pos->first.c_str(); 2827 CommandObject *cmd_obj = pos->second.get(); 2828 2829 if (cmd_obj->HelpTextContainsWord (search_word)) 2830 { 2831 commands_found.AppendString (command_name); 2832 commands_help.AppendString (cmd_obj->GetHelp()); 2833 } 2834 2835 if (cmd_obj->IsMultiwordObject()) 2836 cmd_obj->AproposAllSubCommands (command_name, 2837 search_word, 2838 commands_found, 2839 commands_help); 2840 2841 } 2842 } 2843 2844 if (search_user_commands) 2845 { 2846 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 2847 { 2848 const char *command_name = pos->first.c_str(); 2849 CommandObject *cmd_obj = pos->second.get(); 2850 2851 if (cmd_obj->HelpTextContainsWord (search_word)) 2852 { 2853 commands_found.AppendString (command_name); 2854 commands_help.AppendString (cmd_obj->GetHelp()); 2855 } 2856 2857 if (cmd_obj->IsMultiwordObject()) 2858 cmd_obj->AproposAllSubCommands (command_name, 2859 search_word, 2860 commands_found, 2861 commands_help); 2862 2863 } 2864 } 2865 } 2866 2867 2868 void 2869 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context) 2870 { 2871 if (override_context != NULL) 2872 { 2873 m_exe_ctx_ref = *override_context; 2874 } 2875 else 2876 { 2877 const bool adopt_selected = true; 2878 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected); 2879 } 2880 } 2881