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 15 #include <getopt.h> 16 #include <stdlib.h> 17 18 #include "CommandObjectScript.h" 19 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 20 21 #include "../Commands/CommandObjectApropos.h" 22 #include "../Commands/CommandObjectArgs.h" 23 #include "../Commands/CommandObjectBreakpoint.h" 24 #include "../Commands/CommandObjectDisassemble.h" 25 #include "../Commands/CommandObjectExpression.h" 26 #include "../Commands/CommandObjectFrame.h" 27 #include "../Commands/CommandObjectHelp.h" 28 #include "../Commands/CommandObjectLog.h" 29 #include "../Commands/CommandObjectMemory.h" 30 #include "../Commands/CommandObjectPlatform.h" 31 #include "../Commands/CommandObjectPlugin.h" 32 #include "../Commands/CommandObjectProcess.h" 33 #include "../Commands/CommandObjectQuit.h" 34 #include "../Commands/CommandObjectRegister.h" 35 #include "../Commands/CommandObjectSettings.h" 36 #include "../Commands/CommandObjectSource.h" 37 #include "../Commands/CommandObjectCommands.h" 38 #include "../Commands/CommandObjectSyntax.h" 39 #include "../Commands/CommandObjectTarget.h" 40 #include "../Commands/CommandObjectThread.h" 41 #include "../Commands/CommandObjectType.h" 42 #include "../Commands/CommandObjectVersion.h" 43 #include "../Commands/CommandObjectWatchpoint.h" 44 45 46 #include "lldb/Core/Debugger.h" 47 #include "lldb/Core/InputReader.h" 48 #include "lldb/Core/Log.h" 49 #include "lldb/Core/Stream.h" 50 #include "lldb/Core/Timer.h" 51 52 #include "lldb/Host/Host.h" 53 54 #include "lldb/Interpreter/Args.h" 55 #include "lldb/Interpreter/CommandCompletions.h" 56 #include "lldb/Interpreter/CommandInterpreter.h" 57 #include "lldb/Interpreter/CommandReturnObject.h" 58 #include "lldb/Interpreter/Options.h" 59 #include "lldb/Interpreter/ScriptInterpreterNone.h" 60 #include "lldb/Interpreter/ScriptInterpreterPython.h" 61 62 63 #include "lldb/Target/Process.h" 64 #include "lldb/Target/Thread.h" 65 #include "lldb/Target/TargetList.h" 66 67 #include "lldb/Utility/CleanUp.h" 68 69 using namespace lldb; 70 using namespace lldb_private; 71 72 73 static PropertyDefinition 74 g_properties[] = 75 { 76 { "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." }, 77 { "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." }, 78 { "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." }, 79 { NULL , OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL } 80 }; 81 82 enum 83 { 84 ePropertyExpandRegexAliases = 0, 85 ePropertyPromptOnQuit = 1, 86 ePropertyStopCmdSourceOnError = 2 87 }; 88 89 ConstString & 90 CommandInterpreter::GetStaticBroadcasterClass () 91 { 92 static ConstString class_name ("lldb.commandInterpreter"); 93 return class_name; 94 } 95 96 CommandInterpreter::CommandInterpreter 97 ( 98 Debugger &debugger, 99 ScriptLanguage script_language, 100 bool synchronous_execution 101 ) : 102 Broadcaster (&debugger, "lldb.command-interpreter"), 103 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), 104 m_debugger (debugger), 105 m_synchronous_execution (synchronous_execution), 106 m_skip_lldbinit_files (false), 107 m_skip_app_init_files (false), 108 m_script_interpreter_ap (), 109 m_comment_char ('#'), 110 m_repeat_char ('!'), 111 m_batch_command_mode (false), 112 m_truncation_warning(eNoTruncation), 113 m_command_source_depth (0) 114 { 115 debugger.SetScriptLanguage (script_language); 116 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); 117 SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); 118 SetEventName (eBroadcastBitQuitCommandReceived, "quit"); 119 CheckInWithManager (); 120 m_collection_sp->Initialize (g_properties); 121 } 122 123 bool 124 CommandInterpreter::GetExpandRegexAliases () const 125 { 126 const uint32_t idx = ePropertyExpandRegexAliases; 127 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 128 } 129 130 bool 131 CommandInterpreter::GetPromptOnQuit () const 132 { 133 const uint32_t idx = ePropertyPromptOnQuit; 134 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 135 } 136 137 bool 138 CommandInterpreter::GetStopCmdSourceOnError () const 139 { 140 const uint32_t idx = ePropertyStopCmdSourceOnError; 141 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 142 } 143 144 void 145 CommandInterpreter::Initialize () 146 { 147 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 148 149 CommandReturnObject result; 150 151 LoadCommandDictionary (); 152 153 // Set up some initial aliases. 154 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false); 155 if (cmd_obj_sp) 156 { 157 AddAlias ("q", cmd_obj_sp); 158 AddAlias ("exit", cmd_obj_sp); 159 } 160 161 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false); 162 if (cmd_obj_sp) 163 { 164 AddAlias ("attach", cmd_obj_sp); 165 } 166 167 cmd_obj_sp = GetCommandSPExact ("process detach",false); 168 if (cmd_obj_sp) 169 { 170 AddAlias ("detach", cmd_obj_sp); 171 } 172 173 cmd_obj_sp = GetCommandSPExact ("process continue", false); 174 if (cmd_obj_sp) 175 { 176 AddAlias ("c", cmd_obj_sp); 177 AddAlias ("continue", cmd_obj_sp); 178 } 179 180 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false); 181 if (cmd_obj_sp) 182 AddAlias ("b", cmd_obj_sp); 183 184 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false); 185 if (cmd_obj_sp) 186 AddAlias ("tbreak", cmd_obj_sp); 187 188 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false); 189 if (cmd_obj_sp) 190 { 191 AddAlias ("stepi", cmd_obj_sp); 192 AddAlias ("si", cmd_obj_sp); 193 } 194 195 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false); 196 if (cmd_obj_sp) 197 { 198 AddAlias ("nexti", cmd_obj_sp); 199 AddAlias ("ni", cmd_obj_sp); 200 } 201 202 cmd_obj_sp = GetCommandSPExact ("thread step-in", false); 203 if (cmd_obj_sp) 204 { 205 AddAlias ("s", cmd_obj_sp); 206 AddAlias ("step", cmd_obj_sp); 207 } 208 209 cmd_obj_sp = GetCommandSPExact ("thread step-over", false); 210 if (cmd_obj_sp) 211 { 212 AddAlias ("n", cmd_obj_sp); 213 AddAlias ("next", cmd_obj_sp); 214 } 215 216 cmd_obj_sp = GetCommandSPExact ("thread step-out", false); 217 if (cmd_obj_sp) 218 { 219 AddAlias ("finish", cmd_obj_sp); 220 } 221 222 cmd_obj_sp = GetCommandSPExact ("frame select", false); 223 if (cmd_obj_sp) 224 { 225 AddAlias ("f", cmd_obj_sp); 226 } 227 228 cmd_obj_sp = GetCommandSPExact ("thread select", false); 229 if (cmd_obj_sp) 230 { 231 AddAlias ("t", cmd_obj_sp); 232 } 233 234 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false); 235 if (cmd_obj_sp) 236 { 237 AddAlias ("l", cmd_obj_sp); 238 AddAlias ("list", cmd_obj_sp); 239 } 240 241 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false); 242 if (cmd_obj_sp) 243 { 244 AddAlias ("env", cmd_obj_sp); 245 } 246 247 cmd_obj_sp = GetCommandSPExact ("memory read", false); 248 if (cmd_obj_sp) 249 AddAlias ("x", cmd_obj_sp); 250 251 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false); 252 if (cmd_obj_sp) 253 AddAlias ("up", cmd_obj_sp); 254 255 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false); 256 if (cmd_obj_sp) 257 AddAlias ("down", cmd_obj_sp); 258 259 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false); 260 if (cmd_obj_sp) 261 AddAlias ("display", cmd_obj_sp); 262 263 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 264 if (cmd_obj_sp) 265 AddAlias ("dis", cmd_obj_sp); 266 267 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 268 if (cmd_obj_sp) 269 AddAlias ("di", cmd_obj_sp); 270 271 272 273 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false); 274 if (cmd_obj_sp) 275 AddAlias ("undisplay", cmd_obj_sp); 276 277 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false); 278 if (cmd_obj_sp) 279 AddAlias ("bt", cmd_obj_sp); 280 281 cmd_obj_sp = GetCommandSPExact ("target create", false); 282 if (cmd_obj_sp) 283 AddAlias ("file", cmd_obj_sp); 284 285 cmd_obj_sp = GetCommandSPExact ("target modules", false); 286 if (cmd_obj_sp) 287 AddAlias ("image", cmd_obj_sp); 288 289 290 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector); 291 292 cmd_obj_sp = GetCommandSPExact ("expression", false); 293 if (cmd_obj_sp) 294 { 295 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 296 AddAlias ("p", cmd_obj_sp); 297 AddAlias ("print", cmd_obj_sp); 298 AddAlias ("call", cmd_obj_sp); 299 AddOrReplaceAliasOptions ("p", alias_arguments_vector_sp); 300 AddOrReplaceAliasOptions ("print", alias_arguments_vector_sp); 301 AddOrReplaceAliasOptions ("call", alias_arguments_vector_sp); 302 303 alias_arguments_vector_sp.reset (new OptionArgVector); 304 ProcessAliasOptionsArgs (cmd_obj_sp, "-O -- ", alias_arguments_vector_sp); 305 AddAlias ("po", cmd_obj_sp); 306 AddOrReplaceAliasOptions ("po", alias_arguments_vector_sp); 307 } 308 309 cmd_obj_sp = GetCommandSPExact ("process kill", false); 310 if (cmd_obj_sp) 311 { 312 AddAlias ("kill", cmd_obj_sp); 313 } 314 315 cmd_obj_sp = GetCommandSPExact ("process launch", false); 316 if (cmd_obj_sp) 317 { 318 alias_arguments_vector_sp.reset (new OptionArgVector); 319 #if defined (__arm__) 320 ProcessAliasOptionsArgs (cmd_obj_sp, "--", alias_arguments_vector_sp); 321 #else 322 ProcessAliasOptionsArgs (cmd_obj_sp, "--shell=/bin/bash --", alias_arguments_vector_sp); 323 #endif 324 AddAlias ("r", cmd_obj_sp); 325 AddAlias ("run", cmd_obj_sp); 326 AddOrReplaceAliasOptions ("r", alias_arguments_vector_sp); 327 AddOrReplaceAliasOptions ("run", alias_arguments_vector_sp); 328 } 329 330 cmd_obj_sp = GetCommandSPExact ("target symbols add", false); 331 if (cmd_obj_sp) 332 { 333 AddAlias ("add-dsym", cmd_obj_sp); 334 } 335 336 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false); 337 if (cmd_obj_sp) 338 { 339 alias_arguments_vector_sp.reset (new OptionArgVector); 340 ProcessAliasOptionsArgs (cmd_obj_sp, "--func-regex %1", alias_arguments_vector_sp); 341 AddAlias ("rbreak", cmd_obj_sp); 342 AddOrReplaceAliasOptions("rbreak", alias_arguments_vector_sp); 343 } 344 } 345 346 const char * 347 CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) 348 { 349 // This function has not yet been implemented. 350 351 // Look for any embedded script command 352 // If found, 353 // get interpreter object from the command dictionary, 354 // call execute_one_command on it, 355 // get the results as a string, 356 // substitute that string for current stuff. 357 358 return arg; 359 } 360 361 362 void 363 CommandInterpreter::LoadCommandDictionary () 364 { 365 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 366 367 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); 368 369 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); 370 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); 371 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); 372 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); 373 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this)); 374 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); 375 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this)); 376 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); 377 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); 378 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this)); 379 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this)); 380 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); 381 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this)); 382 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); 383 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language)); 384 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); 385 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); 386 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); 387 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); 388 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this)); 389 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this)); 390 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); 391 392 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, 393 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, 394 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, 395 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, 396 {"^(-.*)$", "breakpoint set %1"}, 397 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"}, 398 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, 399 {"^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"}}; 400 401 size_t num_regexes = sizeof break_regexes/sizeof(char *[2]); 402 403 std::unique_ptr<CommandObjectRegexCommand> 404 break_regex_cmd_ap(new CommandObjectRegexCommand (*this, 405 "_regexp-break", 406 "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 407 "_regexp-break [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 408 2, 409 CommandCompletions::eSymbolCompletion | 410 CommandCompletions::eSourceFileCompletion)); 411 412 if (break_regex_cmd_ap.get()) 413 { 414 bool success = true; 415 for (size_t i = 0; i < num_regexes; i++) 416 { 417 success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]); 418 if (!success) 419 break; 420 } 421 success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 422 423 if (success) 424 { 425 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); 426 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; 427 } 428 } 429 430 std::unique_ptr<CommandObjectRegexCommand> 431 tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this, 432 "_regexp-tbreak", 433 "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 434 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 435 2, 436 CommandCompletions::eSymbolCompletion | 437 CommandCompletions::eSourceFileCompletion)); 438 439 if (tbreak_regex_cmd_ap.get()) 440 { 441 bool success = true; 442 for (size_t i = 0; i < num_regexes; i++) 443 { 444 // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer. 445 char buffer[1024]; 446 int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); 447 assert (num_printed < 1024); 448 success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); 449 if (!success) 450 break; 451 } 452 success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 453 454 if (success) 455 { 456 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); 457 m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp; 458 } 459 } 460 461 std::unique_ptr<CommandObjectRegexCommand> 462 attach_regex_cmd_ap(new CommandObjectRegexCommand (*this, 463 "_regexp-attach", 464 "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", 465 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", 466 2)); 467 if (attach_regex_cmd_ap.get()) 468 { 469 if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && 470 attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach' 471 attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") && 472 attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) 473 { 474 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); 475 m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp; 476 } 477 } 478 479 std::unique_ptr<CommandObjectRegexCommand> 480 down_regex_cmd_ap(new CommandObjectRegexCommand (*this, 481 "_regexp-down", 482 "Go down \"n\" frames in the stack (1 frame by default).", 483 "_regexp-down [n]", 2)); 484 if (down_regex_cmd_ap.get()) 485 { 486 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && 487 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1")) 488 { 489 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); 490 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp; 491 } 492 } 493 494 std::unique_ptr<CommandObjectRegexCommand> 495 up_regex_cmd_ap(new CommandObjectRegexCommand (*this, 496 "_regexp-up", 497 "Go up \"n\" frames in the stack (1 frame by default).", 498 "_regexp-up [n]", 2)); 499 if (up_regex_cmd_ap.get()) 500 { 501 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && 502 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) 503 { 504 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); 505 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp; 506 } 507 } 508 509 std::unique_ptr<CommandObjectRegexCommand> 510 display_regex_cmd_ap(new CommandObjectRegexCommand (*this, 511 "_regexp-display", 512 "Add an expression evaluation stop-hook.", 513 "_regexp-display expression", 2)); 514 if (display_regex_cmd_ap.get()) 515 { 516 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) 517 { 518 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); 519 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp; 520 } 521 } 522 523 std::unique_ptr<CommandObjectRegexCommand> 524 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, 525 "_regexp-undisplay", 526 "Remove an expression evaluation stop-hook.", 527 "_regexp-undisplay stop-hook-number", 2)); 528 if (undisplay_regex_cmd_ap.get()) 529 { 530 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) 531 { 532 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); 533 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp; 534 } 535 } 536 537 std::unique_ptr<CommandObjectRegexCommand> 538 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, 539 "gdb-remote", 540 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", 541 "gdb-remote [<hostname>:]<portnum>", 2)); 542 if (connect_gdb_remote_cmd_ap.get()) 543 { 544 if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && 545 connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) 546 { 547 CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); 548 m_command_dict[command_sp->GetCommandName ()] = command_sp; 549 } 550 } 551 552 std::unique_ptr<CommandObjectRegexCommand> 553 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, 554 "kdp-remote", 555 "Connect to a remote KDP server. udp port 41139 is the default port number.", 556 "kdp-remote <hostname>[:<portnum>]", 2)); 557 if (connect_kdp_remote_cmd_ap.get()) 558 { 559 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && 560 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) 561 { 562 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); 563 m_command_dict[command_sp->GetCommandName ()] = command_sp; 564 } 565 } 566 567 std::unique_ptr<CommandObjectRegexCommand> 568 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, 569 "_regexp-bt", 570 "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.", 571 "bt [<digit>|all]", 2)); 572 if (bt_regex_cmd_ap.get()) 573 { 574 // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace 575 // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and 576 // so now "bt 3" is the preferred form, in line with gdb. 577 if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") && 578 bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") && 579 bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && 580 bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) 581 { 582 CommandObjectSP command_sp(bt_regex_cmd_ap.release()); 583 m_command_dict[command_sp->GetCommandName ()] = command_sp; 584 } 585 } 586 587 std::unique_ptr<CommandObjectRegexCommand> 588 list_regex_cmd_ap(new CommandObjectRegexCommand (*this, 589 "_regexp-list", 590 "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", 591 "_regexp-list [<line>]\n_regexp-attach [<file>:<line>]\n_regexp-attach [<file>:<line>]", 592 2, 593 CommandCompletions::eSourceFileCompletion)); 594 if (list_regex_cmd_ap.get()) 595 { 596 if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && 597 list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") && 598 list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") && 599 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") && 600 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") && 601 list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") && 602 list_regex_cmd_ap->AddRegexCommand("^$", "source list")) 603 { 604 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); 605 m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp; 606 } 607 } 608 609 std::unique_ptr<CommandObjectRegexCommand> 610 env_regex_cmd_ap(new CommandObjectRegexCommand (*this, 611 "_regexp-env", 612 "Implements a shortcut to viewing and setting environment variables.", 613 "_regexp-env\n_regexp-env FOO=BAR", 2)); 614 if (env_regex_cmd_ap.get()) 615 { 616 if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && 617 env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1")) 618 { 619 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); 620 m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp; 621 } 622 } 623 624 } 625 626 int 627 CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, 628 StringList &matches) 629 { 630 CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); 631 632 if (include_aliases) 633 { 634 CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); 635 } 636 637 return matches.GetSize(); 638 } 639 640 CommandObjectSP 641 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) 642 { 643 CommandObject::CommandMap::iterator pos; 644 CommandObjectSP command_sp; 645 646 std::string cmd(cmd_cstr); 647 648 if (HasCommands()) 649 { 650 pos = m_command_dict.find(cmd); 651 if (pos != m_command_dict.end()) 652 command_sp = pos->second; 653 } 654 655 if (include_aliases && HasAliases()) 656 { 657 pos = m_alias_dict.find(cmd); 658 if (pos != m_alias_dict.end()) 659 command_sp = pos->second; 660 } 661 662 if (HasUserCommands()) 663 { 664 pos = m_user_dict.find(cmd); 665 if (pos != m_user_dict.end()) 666 command_sp = pos->second; 667 } 668 669 if (!exact && !command_sp) 670 { 671 // We will only get into here if we didn't find any exact matches. 672 673 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; 674 675 StringList local_matches; 676 if (matches == NULL) 677 matches = &local_matches; 678 679 unsigned int num_cmd_matches = 0; 680 unsigned int num_alias_matches = 0; 681 unsigned int num_user_matches = 0; 682 683 // Look through the command dictionaries one by one, and if we get only one match from any of 684 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. 685 686 if (HasCommands()) 687 { 688 num_cmd_matches = CommandObject::AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); 689 } 690 691 if (num_cmd_matches == 1) 692 { 693 cmd.assign(matches->GetStringAtIndex(0)); 694 pos = m_command_dict.find(cmd); 695 if (pos != m_command_dict.end()) 696 real_match_sp = pos->second; 697 } 698 699 if (include_aliases && HasAliases()) 700 { 701 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); 702 703 } 704 705 if (num_alias_matches == 1) 706 { 707 cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); 708 pos = m_alias_dict.find(cmd); 709 if (pos != m_alias_dict.end()) 710 alias_match_sp = pos->second; 711 } 712 713 if (HasUserCommands()) 714 { 715 num_user_matches = CommandObject::AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); 716 } 717 718 if (num_user_matches == 1) 719 { 720 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); 721 722 pos = m_user_dict.find (cmd); 723 if (pos != m_user_dict.end()) 724 user_match_sp = pos->second; 725 } 726 727 // If we got exactly one match, return that, otherwise return the match list. 728 729 if (num_user_matches + num_cmd_matches + num_alias_matches == 1) 730 { 731 if (num_cmd_matches) 732 return real_match_sp; 733 else if (num_alias_matches) 734 return alias_match_sp; 735 else 736 return user_match_sp; 737 } 738 } 739 else if (matches && command_sp) 740 { 741 matches->AppendString (cmd_cstr); 742 } 743 744 745 return command_sp; 746 } 747 748 bool 749 CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) 750 { 751 if (name && name[0]) 752 { 753 std::string name_sstr(name); 754 bool found = (m_command_dict.find (name_sstr) != m_command_dict.end()); 755 if (found && !can_replace) 756 return false; 757 if (found && m_command_dict[name_sstr]->IsRemovable() == false) 758 return false; 759 m_command_dict[name_sstr] = cmd_sp; 760 return true; 761 } 762 return false; 763 } 764 765 bool 766 CommandInterpreter::AddUserCommand (std::string name, 767 const lldb::CommandObjectSP &cmd_sp, 768 bool can_replace) 769 { 770 if (!name.empty()) 771 { 772 773 const char* name_cstr = name.c_str(); 774 775 // do not allow replacement of internal commands 776 if (CommandExists(name_cstr)) 777 { 778 if (can_replace == false) 779 return false; 780 if (m_command_dict[name]->IsRemovable() == false) 781 return false; 782 } 783 784 if (UserCommandExists(name_cstr)) 785 { 786 if (can_replace == false) 787 return false; 788 if (m_user_dict[name]->IsRemovable() == false) 789 return false; 790 } 791 792 m_user_dict[name] = cmd_sp; 793 return true; 794 } 795 return false; 796 } 797 798 CommandObjectSP 799 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) 800 { 801 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command. 802 CommandObjectSP ret_val; // Possibly empty return value. 803 804 if (cmd_cstr == NULL) 805 return ret_val; 806 807 if (cmd_words.GetArgumentCount() == 1) 808 return GetCommandSP(cmd_cstr, include_aliases, true, NULL); 809 else 810 { 811 // We have a multi-word command (seemingly), so we need to do more work. 812 // First, get the cmd_obj_sp for the first word in the command. 813 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, NULL); 814 if (cmd_obj_sp.get() != NULL) 815 { 816 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a 817 // command name), and find the appropriate sub-command SP for each command word.... 818 size_t end = cmd_words.GetArgumentCount(); 819 for (size_t j= 1; j < end; ++j) 820 { 821 if (cmd_obj_sp->IsMultiwordObject()) 822 { 823 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); 824 if (cmd_obj_sp.get() == NULL) 825 // The sub-command name was invalid. Fail and return the empty 'ret_val'. 826 return ret_val; 827 } 828 else 829 // We have more words in the command name, but we don't have a multiword object. Fail and return 830 // empty 'ret_val'. 831 return ret_val; 832 } 833 // We successfully looped through all the command words and got valid command objects for them. Assign the 834 // last object retrieved to 'ret_val'. 835 ret_val = cmd_obj_sp; 836 } 837 } 838 return ret_val; 839 } 840 841 CommandObject * 842 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) 843 { 844 return GetCommandSPExact (cmd_cstr, include_aliases).get(); 845 } 846 847 CommandObject * 848 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) 849 { 850 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); 851 852 // If we didn't find an exact match to the command string in the commands, look in 853 // the aliases. 854 855 if (command_obj == NULL) 856 { 857 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); 858 } 859 860 // If there wasn't an exact match among the aliases, look for an inexact match 861 // in just the commands. 862 863 if (command_obj == NULL) 864 command_obj = GetCommandSP(cmd_cstr, false, false, matches).get(); 865 866 // Finally, if there wasn't an inexact match among the commands, look for an inexact 867 // match in both the commands and aliases. 868 if (command_obj == NULL) 869 command_obj = GetCommandSP(cmd_cstr, true, false, matches).get(); 870 871 return command_obj; 872 } 873 874 bool 875 CommandInterpreter::CommandExists (const char *cmd) 876 { 877 return m_command_dict.find(cmd) != m_command_dict.end(); 878 } 879 880 bool 881 CommandInterpreter::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, 882 const char *options_args, 883 OptionArgVectorSP &option_arg_vector_sp) 884 { 885 bool success = true; 886 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 887 888 if (!options_args || (strlen (options_args) < 1)) 889 return true; 890 891 std::string options_string (options_args); 892 Args args (options_args); 893 CommandReturnObject result; 894 // Check to see if the command being aliased can take any command options. 895 Options *options = cmd_obj_sp->GetOptions (); 896 if (options) 897 { 898 // See if any options were specified as part of the alias; if so, handle them appropriately. 899 options->NotifyOptionParsingStarting (); 900 args.Unshift ("dummy_arg"); 901 args.ParseAliasOptions (*options, result, option_arg_vector, options_string); 902 args.Shift (); 903 if (result.Succeeded()) 904 options->VerifyPartialOptions (result); 905 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 906 { 907 result.AppendError ("Unable to create requested alias.\n"); 908 return false; 909 } 910 } 911 912 if (!options_string.empty()) 913 { 914 if (cmd_obj_sp->WantsRawCommandString ()) 915 option_arg_vector->push_back (OptionArgPair ("<argument>", 916 OptionArgValue (-1, 917 options_string))); 918 else 919 { 920 const size_t argc = args.GetArgumentCount(); 921 for (size_t i = 0; i < argc; ++i) 922 if (strcmp (args.GetArgumentAtIndex (i), "") != 0) 923 option_arg_vector->push_back 924 (OptionArgPair ("<argument>", 925 OptionArgValue (-1, 926 std::string (args.GetArgumentAtIndex (i))))); 927 } 928 } 929 930 return success; 931 } 932 933 bool 934 CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name) 935 { 936 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); 937 if (exact_match) 938 { 939 full_name.assign(cmd); 940 return exact_match; 941 } 942 else 943 { 944 StringList matches; 945 size_t num_alias_matches; 946 num_alias_matches = CommandObject::AddNamesMatchingPartialString (m_alias_dict, cmd, matches); 947 if (num_alias_matches == 1) 948 { 949 // Make sure this isn't shadowing a command in the regular command space: 950 StringList regular_matches; 951 const bool include_aliases = false; 952 const bool exact = false; 953 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches)); 954 if (cmd_obj_sp || regular_matches.GetSize() > 0) 955 return false; 956 else 957 { 958 full_name.assign (matches.GetStringAtIndex(0)); 959 return true; 960 } 961 } 962 else 963 return false; 964 } 965 } 966 967 bool 968 CommandInterpreter::AliasExists (const char *cmd) 969 { 970 return m_alias_dict.find(cmd) != m_alias_dict.end(); 971 } 972 973 bool 974 CommandInterpreter::UserCommandExists (const char *cmd) 975 { 976 return m_user_dict.find(cmd) != m_user_dict.end(); 977 } 978 979 void 980 CommandInterpreter::AddAlias (const char *alias_name, CommandObjectSP& command_obj_sp) 981 { 982 command_obj_sp->SetIsAlias (true); 983 m_alias_dict[alias_name] = command_obj_sp; 984 } 985 986 bool 987 CommandInterpreter::RemoveAlias (const char *alias_name) 988 { 989 CommandObject::CommandMap::iterator pos = m_alias_dict.find(alias_name); 990 if (pos != m_alias_dict.end()) 991 { 992 m_alias_dict.erase(pos); 993 return true; 994 } 995 return false; 996 } 997 bool 998 CommandInterpreter::RemoveUser (const char *alias_name) 999 { 1000 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); 1001 if (pos != m_user_dict.end()) 1002 { 1003 m_user_dict.erase(pos); 1004 return true; 1005 } 1006 return false; 1007 } 1008 1009 void 1010 CommandInterpreter::GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string) 1011 { 1012 help_string.Printf ("'%s", command_name); 1013 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1014 1015 if (option_arg_vector_sp) 1016 { 1017 OptionArgVector *options = option_arg_vector_sp.get(); 1018 for (int i = 0; i < options->size(); ++i) 1019 { 1020 OptionArgPair cur_option = (*options)[i]; 1021 std::string opt = cur_option.first; 1022 OptionArgValue value_pair = cur_option.second; 1023 std::string value = value_pair.second; 1024 if (opt.compare("<argument>") == 0) 1025 { 1026 help_string.Printf (" %s", value.c_str()); 1027 } 1028 else 1029 { 1030 help_string.Printf (" %s", opt.c_str()); 1031 if ((value.compare ("<no-argument>") != 0) 1032 && (value.compare ("<need-argument") != 0)) 1033 { 1034 help_string.Printf (" %s", value.c_str()); 1035 } 1036 } 1037 } 1038 } 1039 1040 help_string.Printf ("'"); 1041 } 1042 1043 size_t 1044 CommandInterpreter::FindLongestCommandWord (CommandObject::CommandMap &dict) 1045 { 1046 CommandObject::CommandMap::const_iterator pos; 1047 CommandObject::CommandMap::const_iterator end = dict.end(); 1048 size_t max_len = 0; 1049 1050 for (pos = dict.begin(); pos != end; ++pos) 1051 { 1052 size_t len = pos->first.size(); 1053 if (max_len < len) 1054 max_len = len; 1055 } 1056 return max_len; 1057 } 1058 1059 void 1060 CommandInterpreter::GetHelp (CommandReturnObject &result, 1061 uint32_t cmd_types) 1062 { 1063 CommandObject::CommandMap::const_iterator pos; 1064 size_t max_len = FindLongestCommandWord (m_command_dict); 1065 1066 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) 1067 { 1068 1069 result.AppendMessage("The following is a list of built-in, permanent debugger commands:"); 1070 result.AppendMessage(""); 1071 1072 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 1073 { 1074 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1075 max_len); 1076 } 1077 result.AppendMessage(""); 1078 1079 } 1080 1081 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) 1082 { 1083 result.AppendMessage("The following is a list of your current command abbreviations " 1084 "(see 'help command alias' for more info):"); 1085 result.AppendMessage(""); 1086 max_len = FindLongestCommandWord (m_alias_dict); 1087 1088 for (pos = m_alias_dict.begin(); pos != m_alias_dict.end(); ++pos) 1089 { 1090 StreamString sstr; 1091 StreamString translation_and_help; 1092 std::string entry_name = pos->first; 1093 std::string second_entry = pos->second.get()->GetCommandName(); 1094 GetAliasHelp (pos->first.c_str(), pos->second->GetCommandName(), sstr); 1095 1096 translation_and_help.Printf ("(%s) %s", sstr.GetData(), pos->second->GetHelp()); 1097 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", 1098 translation_and_help.GetData(), max_len); 1099 } 1100 result.AppendMessage(""); 1101 } 1102 1103 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) 1104 { 1105 result.AppendMessage ("The following is a list of your current user-defined commands:"); 1106 result.AppendMessage(""); 1107 max_len = FindLongestCommandWord (m_user_dict); 1108 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 1109 { 1110 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1111 max_len); 1112 } 1113 result.AppendMessage(""); 1114 } 1115 1116 result.AppendMessage("For more information on any particular command, try 'help <command-name>'."); 1117 } 1118 1119 CommandObject * 1120 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) 1121 { 1122 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will 1123 // eventually be invoked by the given command line. 1124 1125 CommandObject *cmd_obj = NULL; 1126 std::string white_space (" \t\v"); 1127 size_t start = command_string.find_first_not_of (white_space); 1128 size_t end = 0; 1129 bool done = false; 1130 while (!done) 1131 { 1132 if (start != std::string::npos) 1133 { 1134 // Get the next word from command_string. 1135 end = command_string.find_first_of (white_space, start); 1136 if (end == std::string::npos) 1137 end = command_string.size(); 1138 std::string cmd_word = command_string.substr (start, end - start); 1139 1140 if (cmd_obj == NULL) 1141 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid 1142 // command or alias. 1143 cmd_obj = GetCommandObject (cmd_word.c_str()); 1144 else if (cmd_obj->IsMultiwordObject ()) 1145 { 1146 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object. 1147 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str()); 1148 if (sub_cmd_obj) 1149 cmd_obj = sub_cmd_obj; 1150 else // cmd_word was not a valid sub-command word, so we are donee 1151 done = true; 1152 } 1153 else 1154 // We have a cmd_obj and it is not a multi-word object, so we are done. 1155 done = true; 1156 1157 // If we didn't find a valid command object, or our command object is not a multi-word object, or 1158 // we are at the end of the command_string, then we are done. Otherwise, find the start of the 1159 // next word. 1160 1161 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) 1162 done = true; 1163 else 1164 start = command_string.find_first_not_of (white_space, end); 1165 } 1166 else 1167 // Unable to find any more words. 1168 done = true; 1169 } 1170 1171 if (end == command_string.size()) 1172 command_string.clear(); 1173 else 1174 command_string = command_string.substr(end); 1175 1176 return cmd_obj; 1177 } 1178 1179 static const char *k_white_space = " \t\v"; 1180 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; 1181 static void 1182 StripLeadingSpaces (std::string &s) 1183 { 1184 if (!s.empty()) 1185 { 1186 size_t pos = s.find_first_not_of (k_white_space); 1187 if (pos == std::string::npos) 1188 s.clear(); 1189 else if (pos == 0) 1190 return; 1191 s.erase (0, pos); 1192 } 1193 } 1194 1195 static size_t 1196 FindArgumentTerminator (const std::string &s) 1197 { 1198 const size_t s_len = s.size(); 1199 size_t offset = 0; 1200 while (offset < s_len) 1201 { 1202 size_t pos = s.find ("--", offset); 1203 if (pos == std::string::npos) 1204 break; 1205 if (pos > 0) 1206 { 1207 if (isspace(s[pos-1])) 1208 { 1209 // Check if the string ends "\s--" (where \s is a space character) 1210 // or if we have "\s--\s". 1211 if ((pos + 2 >= s_len) || isspace(s[pos+2])) 1212 { 1213 return pos; 1214 } 1215 } 1216 } 1217 offset = pos + 2; 1218 } 1219 return std::string::npos; 1220 } 1221 1222 static bool 1223 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char) 1224 { 1225 command.clear(); 1226 suffix.clear(); 1227 StripLeadingSpaces (command_string); 1228 1229 bool result = false; 1230 quote_char = '\0'; 1231 1232 if (!command_string.empty()) 1233 { 1234 const char first_char = command_string[0]; 1235 if (first_char == '\'' || first_char == '"') 1236 { 1237 quote_char = first_char; 1238 const size_t end_quote_pos = command_string.find (quote_char, 1); 1239 if (end_quote_pos == std::string::npos) 1240 { 1241 command.swap (command_string); 1242 command_string.erase (); 1243 } 1244 else 1245 { 1246 command.assign (command_string, 1, end_quote_pos - 1); 1247 if (end_quote_pos + 1 < command_string.size()) 1248 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1)); 1249 else 1250 command_string.erase (); 1251 } 1252 } 1253 else 1254 { 1255 const size_t first_space_pos = command_string.find_first_of (k_white_space); 1256 if (first_space_pos == std::string::npos) 1257 { 1258 command.swap (command_string); 1259 command_string.erase(); 1260 } 1261 else 1262 { 1263 command.assign (command_string, 0, first_space_pos); 1264 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos)); 1265 } 1266 } 1267 result = true; 1268 } 1269 1270 1271 if (!command.empty()) 1272 { 1273 // actual commands can't start with '-' or '_' 1274 if (command[0] != '-' && command[0] != '_') 1275 { 1276 size_t pos = command.find_first_not_of(k_valid_command_chars); 1277 if (pos > 0 && pos != std::string::npos) 1278 { 1279 suffix.assign (command.begin() + pos, command.end()); 1280 command.erase (pos); 1281 } 1282 } 1283 } 1284 1285 return result; 1286 } 1287 1288 CommandObject * 1289 CommandInterpreter::BuildAliasResult (const char *alias_name, 1290 std::string &raw_input_string, 1291 std::string &alias_result, 1292 CommandReturnObject &result) 1293 { 1294 CommandObject *alias_cmd_obj = NULL; 1295 Args cmd_args (raw_input_string.c_str()); 1296 alias_cmd_obj = GetCommandObject (alias_name); 1297 StreamString result_str; 1298 1299 if (alias_cmd_obj) 1300 { 1301 std::string alias_name_str = alias_name; 1302 if ((cmd_args.GetArgumentCount() == 0) 1303 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) 1304 cmd_args.Unshift (alias_name); 1305 1306 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); 1307 OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); 1308 1309 if (option_arg_vector_sp.get()) 1310 { 1311 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 1312 1313 for (int i = 0; i < option_arg_vector->size(); ++i) 1314 { 1315 OptionArgPair option_pair = (*option_arg_vector)[i]; 1316 OptionArgValue value_pair = option_pair.second; 1317 int value_type = value_pair.first; 1318 std::string option = option_pair.first; 1319 std::string value = value_pair.second; 1320 if (option.compare ("<argument>") == 0) 1321 result_str.Printf (" %s", value.c_str()); 1322 else 1323 { 1324 result_str.Printf (" %s", option.c_str()); 1325 if (value_type != optional_argument) 1326 result_str.Printf (" "); 1327 if (value.compare ("<no_argument>") != 0) 1328 { 1329 int index = GetOptionArgumentPosition (value.c_str()); 1330 if (index == 0) 1331 result_str.Printf ("%s", value.c_str()); 1332 else if (index >= cmd_args.GetArgumentCount()) 1333 { 1334 1335 result.AppendErrorWithFormat 1336 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 1337 index); 1338 result.SetStatus (eReturnStatusFailed); 1339 return alias_cmd_obj; 1340 } 1341 else 1342 { 1343 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 1344 if (strpos != std::string::npos) 1345 raw_input_string = raw_input_string.erase (strpos, 1346 strlen (cmd_args.GetArgumentAtIndex (index))); 1347 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index)); 1348 } 1349 } 1350 } 1351 } 1352 } 1353 1354 alias_result = result_str.GetData(); 1355 } 1356 return alias_cmd_obj; 1357 } 1358 1359 Error 1360 CommandInterpreter::PreprocessCommand (std::string &command) 1361 { 1362 // The command preprocessor needs to do things to the command 1363 // line before any parsing of arguments or anything else is done. 1364 // The only current stuff that gets proprocessed is anyting enclosed 1365 // in backtick ('`') characters is evaluated as an expression and 1366 // the result of the expression must be a scalar that can be substituted 1367 // into the command. An example would be: 1368 // (lldb) memory read `$rsp + 20` 1369 Error error; // Error for any expressions that might not evaluate 1370 size_t start_backtick; 1371 size_t pos = 0; 1372 while ((start_backtick = command.find ('`', pos)) != std::string::npos) 1373 { 1374 if (start_backtick > 0 && command[start_backtick-1] == '\\') 1375 { 1376 // The backtick was preceeded by a '\' character, remove the slash 1377 // and don't treat the backtick as the start of an expression 1378 command.erase(start_backtick-1, 1); 1379 // No need to add one to start_backtick since we just deleted a char 1380 pos = start_backtick; 1381 } 1382 else 1383 { 1384 const size_t expr_content_start = start_backtick + 1; 1385 const size_t end_backtick = command.find ('`', expr_content_start); 1386 if (end_backtick == std::string::npos) 1387 return error; 1388 else if (end_backtick == expr_content_start) 1389 { 1390 // Empty expression (two backticks in a row) 1391 command.erase (start_backtick, 2); 1392 } 1393 else 1394 { 1395 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start); 1396 1397 ExecutionContext exe_ctx(GetExecutionContext()); 1398 Target *target = exe_ctx.GetTargetPtr(); 1399 // Get a dummy target to allow for calculator mode while processing backticks. 1400 // This also helps break the infinite loop caused when target is null. 1401 if (!target) 1402 target = Host::GetDummyTarget(GetDebugger()).get(); 1403 if (target) 1404 { 1405 ValueObjectSP expr_result_valobj_sp; 1406 1407 EvaluateExpressionOptions options; 1408 options.SetCoerceToId(false) 1409 .SetUnwindOnError(true) 1410 .SetIgnoreBreakpoints(true) 1411 .SetKeepInMemory(false) 1412 .SetRunOthers(true) 1413 .SetTimeoutUsec(0); 1414 1415 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1416 exe_ctx.GetFramePtr(), 1417 expr_result_valobj_sp, 1418 options); 1419 1420 if (expr_result == eExecutionCompleted) 1421 { 1422 Scalar scalar; 1423 if (expr_result_valobj_sp->ResolveValue (scalar)) 1424 { 1425 command.erase (start_backtick, end_backtick - start_backtick + 1); 1426 StreamString value_strm; 1427 const bool show_type = false; 1428 scalar.GetValue (&value_strm, show_type); 1429 size_t value_string_size = value_strm.GetSize(); 1430 if (value_string_size) 1431 { 1432 command.insert (start_backtick, value_strm.GetData(), value_string_size); 1433 pos = start_backtick + value_string_size; 1434 continue; 1435 } 1436 else 1437 { 1438 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1439 } 1440 } 1441 else 1442 { 1443 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1444 } 1445 } 1446 else 1447 { 1448 if (expr_result_valobj_sp) 1449 error = expr_result_valobj_sp->GetError(); 1450 if (error.Success()) 1451 { 1452 1453 switch (expr_result) 1454 { 1455 case eExecutionSetupError: 1456 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str()); 1457 break; 1458 case eExecutionCompleted: 1459 break; 1460 case eExecutionDiscarded: 1461 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str()); 1462 break; 1463 case eExecutionInterrupted: 1464 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str()); 1465 break; 1466 case eExecutionHitBreakpoint: 1467 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str()); 1468 break; 1469 case eExecutionTimedOut: 1470 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str()); 1471 break; 1472 } 1473 } 1474 } 1475 } 1476 } 1477 if (error.Fail()) 1478 break; 1479 } 1480 } 1481 return error; 1482 } 1483 1484 1485 bool 1486 CommandInterpreter::HandleCommand (const char *command_line, 1487 LazyBool lazy_add_to_history, 1488 CommandReturnObject &result, 1489 ExecutionContext *override_context, 1490 bool repeat_on_empty_command, 1491 bool no_context_switching) 1492 1493 { 1494 1495 bool done = false; 1496 CommandObject *cmd_obj = NULL; 1497 bool wants_raw_input = false; 1498 std::string command_string (command_line); 1499 std::string original_command_string (command_line); 1500 1501 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); 1502 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); 1503 1504 // Make a scoped cleanup object that will clear the crash description string 1505 // on exit of this function. 1506 lldb_utility::CleanUp <const char *> crash_description_cleanup(NULL, Host::SetCrashDescription); 1507 1508 if (log) 1509 log->Printf ("Processing command: %s", command_line); 1510 1511 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line); 1512 1513 if (!no_context_switching) 1514 UpdateExecutionContext (override_context); 1515 1516 bool add_to_history; 1517 if (lazy_add_to_history == eLazyBoolCalculate) 1518 add_to_history = (m_command_source_depth == 0); 1519 else 1520 add_to_history = (lazy_add_to_history == eLazyBoolYes); 1521 1522 bool empty_command = false; 1523 bool comment_command = false; 1524 if (command_string.empty()) 1525 empty_command = true; 1526 else 1527 { 1528 const char *k_space_characters = "\t\n\v\f\r "; 1529 1530 size_t non_space = command_string.find_first_not_of (k_space_characters); 1531 // Check for empty line or comment line (lines whose first 1532 // non-space character is the comment character for this interpreter) 1533 if (non_space == std::string::npos) 1534 empty_command = true; 1535 else if (command_string[non_space] == m_comment_char) 1536 comment_command = true; 1537 else if (command_string[non_space] == m_repeat_char) 1538 { 1539 const char *history_string = FindHistoryString (command_string.c_str() + non_space); 1540 if (history_string == NULL) 1541 { 1542 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); 1543 result.SetStatus(eReturnStatusFailed); 1544 return false; 1545 } 1546 add_to_history = false; 1547 command_string = history_string; 1548 original_command_string = history_string; 1549 } 1550 } 1551 1552 if (empty_command) 1553 { 1554 if (repeat_on_empty_command) 1555 { 1556 if (m_command_history.empty()) 1557 { 1558 result.AppendError ("empty command"); 1559 result.SetStatus(eReturnStatusFailed); 1560 return false; 1561 } 1562 else 1563 { 1564 command_line = m_repeat_command.c_str(); 1565 command_string = command_line; 1566 original_command_string = command_line; 1567 if (m_repeat_command.empty()) 1568 { 1569 result.AppendErrorWithFormat("No auto repeat.\n"); 1570 result.SetStatus (eReturnStatusFailed); 1571 return false; 1572 } 1573 } 1574 add_to_history = false; 1575 } 1576 else 1577 { 1578 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1579 return true; 1580 } 1581 } 1582 else if (comment_command) 1583 { 1584 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1585 return true; 1586 } 1587 1588 1589 Error error (PreprocessCommand (command_string)); 1590 1591 if (error.Fail()) 1592 { 1593 result.AppendError (error.AsCString()); 1594 result.SetStatus(eReturnStatusFailed); 1595 return false; 1596 } 1597 // Phase 1. 1598 1599 // Before we do ANY kind of argument processing, etc. we need to figure out what the real/final command object 1600 // is for the specified command, and whether or not it wants raw input. This gets complicated by the fact that 1601 // the user could have specified an alias, and in translating the alias there may also be command options and/or 1602 // even data (including raw text strings) that need to be found and inserted into the command line as part of 1603 // the translation. So this first step is plain look-up & replacement, resulting in three things: 1). the command 1604 // object whose Execute method will actually be called; 2). a revised command string, with all substitutions & 1605 // replacements taken care of; 3). whether or not the Execute function wants raw input or not. 1606 1607 StreamString revised_command_line; 1608 size_t actual_cmd_name_len = 0; 1609 std::string next_word; 1610 StringList matches; 1611 while (!done) 1612 { 1613 char quote_char = '\0'; 1614 std::string suffix; 1615 ExtractCommand (command_string, next_word, suffix, quote_char); 1616 if (cmd_obj == NULL) 1617 { 1618 std::string full_name; 1619 if (GetAliasFullName(next_word.c_str(), full_name)) 1620 { 1621 std::string alias_result; 1622 cmd_obj = BuildAliasResult (full_name.c_str(), command_string, alias_result, result); 1623 revised_command_line.Printf ("%s", alias_result.c_str()); 1624 if (cmd_obj) 1625 { 1626 wants_raw_input = cmd_obj->WantsRawCommandString (); 1627 actual_cmd_name_len = strlen (cmd_obj->GetCommandName()); 1628 } 1629 } 1630 else 1631 { 1632 cmd_obj = GetCommandObject (next_word.c_str(), &matches); 1633 if (cmd_obj) 1634 { 1635 actual_cmd_name_len += next_word.length(); 1636 revised_command_line.Printf ("%s", next_word.c_str()); 1637 wants_raw_input = cmd_obj->WantsRawCommandString (); 1638 } 1639 else 1640 { 1641 revised_command_line.Printf ("%s", next_word.c_str()); 1642 } 1643 } 1644 } 1645 else 1646 { 1647 if (cmd_obj->IsMultiwordObject ()) 1648 { 1649 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (next_word.c_str()); 1650 if (sub_cmd_obj) 1651 { 1652 actual_cmd_name_len += next_word.length() + 1; 1653 revised_command_line.Printf (" %s", next_word.c_str()); 1654 cmd_obj = sub_cmd_obj; 1655 wants_raw_input = cmd_obj->WantsRawCommandString (); 1656 } 1657 else 1658 { 1659 if (quote_char) 1660 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 1661 else 1662 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str()); 1663 done = true; 1664 } 1665 } 1666 else 1667 { 1668 if (quote_char) 1669 revised_command_line.Printf (" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 1670 else 1671 revised_command_line.Printf (" %s%s", next_word.c_str(), suffix.c_str()); 1672 done = true; 1673 } 1674 } 1675 1676 if (cmd_obj == NULL) 1677 { 1678 const size_t num_matches = matches.GetSize(); 1679 if (matches.GetSize() > 1) { 1680 StreamString error_msg; 1681 error_msg.Printf ("Ambiguous command '%s'. Possible matches:\n", next_word.c_str()); 1682 1683 for (uint32_t i = 0; i < num_matches; ++i) { 1684 error_msg.Printf ("\t%s\n", matches.GetStringAtIndex(i)); 1685 } 1686 result.AppendRawError (error_msg.GetString().c_str()); 1687 } else { 1688 // We didn't have only one match, otherwise we wouldn't get here. 1689 assert(num_matches == 0); 1690 result.AppendErrorWithFormat ("'%s' is not a valid command.\n", next_word.c_str()); 1691 } 1692 result.SetStatus (eReturnStatusFailed); 1693 return false; 1694 } 1695 1696 if (cmd_obj->IsMultiwordObject ()) 1697 { 1698 if (!suffix.empty()) 1699 { 1700 1701 result.AppendErrorWithFormat ("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n", 1702 cmd_obj->GetCommandName(), 1703 next_word.empty() ? "" : next_word.c_str(), 1704 next_word.empty() ? " -- " : " ", 1705 suffix.c_str()); 1706 result.SetStatus (eReturnStatusFailed); 1707 return false; 1708 } 1709 } 1710 else 1711 { 1712 // If we found a normal command, we are done 1713 done = true; 1714 if (!suffix.empty()) 1715 { 1716 switch (suffix[0]) 1717 { 1718 case '/': 1719 // GDB format suffixes 1720 { 1721 Options *command_options = cmd_obj->GetOptions(); 1722 if (command_options && command_options->SupportsLongOption("gdb-format")) 1723 { 1724 std::string gdb_format_option ("--gdb-format="); 1725 gdb_format_option += (suffix.c_str() + 1); 1726 1727 bool inserted = false; 1728 std::string &cmd = revised_command_line.GetString(); 1729 size_t arg_terminator_idx = FindArgumentTerminator (cmd); 1730 if (arg_terminator_idx != std::string::npos) 1731 { 1732 // Insert the gdb format option before the "--" that terminates options 1733 gdb_format_option.append(1,' '); 1734 cmd.insert(arg_terminator_idx, gdb_format_option); 1735 inserted = true; 1736 } 1737 1738 if (!inserted) 1739 revised_command_line.Printf (" %s", gdb_format_option.c_str()); 1740 1741 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos) 1742 revised_command_line.PutCString (" --"); 1743 } 1744 else 1745 { 1746 result.AppendErrorWithFormat ("the '%s' command doesn't support the --gdb-format option\n", 1747 cmd_obj->GetCommandName()); 1748 result.SetStatus (eReturnStatusFailed); 1749 return false; 1750 } 1751 } 1752 break; 1753 1754 default: 1755 result.AppendErrorWithFormat ("unknown command shorthand suffix: '%s'\n", 1756 suffix.c_str()); 1757 result.SetStatus (eReturnStatusFailed); 1758 return false; 1759 1760 } 1761 } 1762 } 1763 if (command_string.length() == 0) 1764 done = true; 1765 1766 } 1767 1768 if (!command_string.empty()) 1769 revised_command_line.Printf (" %s", command_string.c_str()); 1770 1771 // End of Phase 1. 1772 // At this point cmd_obj should contain the CommandObject whose Execute method will be called, if the command 1773 // specified was valid; revised_command_line contains the complete command line (including command name(s)), 1774 // fully translated with all substitutions & translations taken care of (still in raw text format); and 1775 // wants_raw_input specifies whether the Execute method expects raw input or not. 1776 1777 1778 if (log) 1779 { 1780 log->Printf ("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); 1781 log->Printf ("HandleCommand, revised_command_line: '%s'", revised_command_line.GetData()); 1782 log->Printf ("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); 1783 } 1784 1785 // Phase 2. 1786 // Take care of things like setting up the history command & calling the appropriate Execute method on the 1787 // CommandObject, with the appropriate arguments. 1788 1789 if (cmd_obj != NULL) 1790 { 1791 if (add_to_history) 1792 { 1793 Args command_args (revised_command_line.GetData()); 1794 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); 1795 if (repeat_command != NULL) 1796 m_repeat_command.assign(repeat_command); 1797 else 1798 m_repeat_command.assign(original_command_string.c_str()); 1799 1800 // Don't keep pushing the same command onto the history... 1801 if (m_command_history.empty() || m_command_history.back() != original_command_string) 1802 m_command_history.push_back (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] == m_repeat_char) 1961 { 1962 const char *history_string = FindHistoryString (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 (int 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 != optional_argument) 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 != optional_argument) 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 != optional_argument) 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 (int 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 (int 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 #%d: '%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 #%d '%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 #%d: '%s' continued the target.\n", 2585 idx + 1, cmd); 2586 else 2587 result.AppendMessageWithFormat ("Command #%d '%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 2882 void 2883 CommandInterpreter::DumpHistory (Stream &stream, uint32_t count) const 2884 { 2885 DumpHistory (stream, 0, count - 1); 2886 } 2887 2888 void 2889 CommandInterpreter::DumpHistory (Stream &stream, uint32_t start, uint32_t end) const 2890 { 2891 const size_t last_idx = std::min<size_t>(m_command_history.size(), end==UINT32_MAX ? UINT32_MAX : end + 1); 2892 for (size_t i = start; i < last_idx; i++) 2893 { 2894 if (!m_command_history[i].empty()) 2895 { 2896 stream.Indent(); 2897 stream.Printf ("%4zu: %s\n", i, m_command_history[i].c_str()); 2898 } 2899 } 2900 } 2901 2902 const char * 2903 CommandInterpreter::FindHistoryString (const char *input_str) const 2904 { 2905 if (input_str[0] != m_repeat_char) 2906 return NULL; 2907 if (input_str[1] == '-') 2908 { 2909 bool success; 2910 size_t idx = Args::StringToUInt32 (input_str+2, 0, 0, &success); 2911 if (!success) 2912 return NULL; 2913 if (idx > m_command_history.size()) 2914 return NULL; 2915 idx = m_command_history.size() - idx; 2916 return m_command_history[idx].c_str(); 2917 2918 } 2919 else if (input_str[1] == m_repeat_char) 2920 { 2921 if (m_command_history.empty()) 2922 return NULL; 2923 else 2924 return m_command_history.back().c_str(); 2925 } 2926 else 2927 { 2928 bool success; 2929 uint32_t idx = Args::StringToUInt32 (input_str+1, 0, 0, &success); 2930 if (!success) 2931 return NULL; 2932 if (idx >= m_command_history.size()) 2933 return NULL; 2934 return m_command_history[idx].c_str(); 2935 } 2936 } 2937