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