1 //===-- CommandObjectSource.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 "CommandObjectCommands.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 #include "llvm/ADT/StringRef.h" 16 17 // Project includes 18 #include "lldb/Core/Debugger.h" 19 #include "lldb/Core/InputReader.h" 20 #include "lldb/Core/InputReaderEZ.h" 21 #include "lldb/Core/StringList.h" 22 #include "lldb/Interpreter/Args.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 25 #include "lldb/Interpreter/CommandReturnObject.h" 26 #include "lldb/Interpreter/Options.h" 27 #include "lldb/Interpreter/ScriptInterpreter.h" 28 #include "lldb/Interpreter/ScriptInterpreterPython.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 //------------------------------------------------------------------------- 34 // CommandObjectCommandsSource 35 //------------------------------------------------------------------------- 36 37 class CommandObjectCommandsHistory : public CommandObject 38 { 39 private: 40 41 class CommandOptions : public Options 42 { 43 public: 44 45 CommandOptions (CommandInterpreter &interpreter) : 46 Options (interpreter) 47 { 48 } 49 50 virtual 51 ~CommandOptions (){} 52 53 virtual Error 54 SetOptionValue (uint32_t option_idx, const char *option_arg) 55 { 56 Error error; 57 char short_option = (char) m_getopt_table[option_idx].val; 58 bool success; 59 60 switch (short_option) 61 { 62 case 'c': 63 m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success); 64 if (!success) 65 error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg); 66 if (m_end_idx != 0) 67 m_end_idx--; 68 m_start_idx = 0; 69 break; 70 case 'e': 71 m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success); 72 if (!success) 73 error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg); 74 break; 75 case 's': 76 m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success); 77 if (!success) 78 error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg); 79 break; 80 default: 81 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 82 break; 83 } 84 85 return error; 86 } 87 88 void 89 OptionParsingStarting () 90 { 91 m_start_idx = 0; 92 m_end_idx = UINT_MAX; 93 } 94 95 const OptionDefinition* 96 GetDefinitions () 97 { 98 return g_option_table; 99 } 100 101 // Options table: Required for subclasses of Options. 102 103 static OptionDefinition g_option_table[]; 104 105 // Instance variables to hold the values for command options. 106 107 uint32_t m_start_idx; 108 uint32_t m_end_idx; 109 }; 110 111 CommandOptions m_options; 112 113 virtual Options * 114 GetOptions () 115 { 116 return &m_options; 117 } 118 119 public: 120 CommandObjectCommandsHistory(CommandInterpreter &interpreter) : 121 CommandObject (interpreter, 122 "command history", 123 "Dump the history of commands in this session.", 124 NULL), 125 m_options (interpreter) 126 { 127 } 128 129 ~CommandObjectCommandsHistory () 130 { 131 } 132 133 bool 134 Execute 135 ( 136 Args& args, 137 CommandReturnObject &result 138 ) 139 { 140 141 m_interpreter.DumpHistory (result.GetOutputStream(), 142 m_options.m_start_idx, 143 m_options.m_end_idx); 144 return result.Succeeded(); 145 146 } 147 }; 148 149 OptionDefinition 150 CommandObjectCommandsHistory::CommandOptions::g_option_table[] = 151 { 152 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."}, 153 { LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands."}, 154 { LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."}, 155 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 156 }; 157 158 159 //------------------------------------------------------------------------- 160 // CommandObjectCommandsSource 161 //------------------------------------------------------------------------- 162 163 class CommandObjectCommandsSource : public CommandObject 164 { 165 private: 166 167 class CommandOptions : public Options 168 { 169 public: 170 171 CommandOptions (CommandInterpreter &interpreter) : 172 Options (interpreter) 173 { 174 } 175 176 virtual 177 ~CommandOptions (){} 178 179 virtual Error 180 SetOptionValue (uint32_t option_idx, const char *option_arg) 181 { 182 Error error; 183 char short_option = (char) m_getopt_table[option_idx].val; 184 bool success; 185 186 switch (short_option) 187 { 188 case 'e': 189 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success); 190 if (!success) 191 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg); 192 break; 193 case 'c': 194 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success); 195 if (!success) 196 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg); 197 break; 198 default: 199 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 200 break; 201 } 202 203 return error; 204 } 205 206 void 207 OptionParsingStarting () 208 { 209 m_stop_on_error = true; 210 m_stop_on_continue = true; 211 } 212 213 const OptionDefinition* 214 GetDefinitions () 215 { 216 return g_option_table; 217 } 218 219 // Options table: Required for subclasses of Options. 220 221 static OptionDefinition g_option_table[]; 222 223 // Instance variables to hold the values for command options. 224 225 bool m_stop_on_error; 226 bool m_stop_on_continue; 227 }; 228 229 CommandOptions m_options; 230 231 virtual Options * 232 GetOptions () 233 { 234 return &m_options; 235 } 236 237 public: 238 CommandObjectCommandsSource(CommandInterpreter &interpreter) : 239 CommandObject (interpreter, 240 "command source", 241 "Read in debugger commands from the file <filename> and execute them.", 242 NULL), 243 m_options (interpreter) 244 { 245 CommandArgumentEntry arg; 246 CommandArgumentData file_arg; 247 248 // Define the first (and only) variant of this arg. 249 file_arg.arg_type = eArgTypeFilename; 250 file_arg.arg_repetition = eArgRepeatPlain; 251 252 // There is only one variant this argument could be; put it into the argument entry. 253 arg.push_back (file_arg); 254 255 // Push the data for the first argument into the m_arguments vector. 256 m_arguments.push_back (arg); 257 } 258 259 ~CommandObjectCommandsSource () 260 { 261 } 262 263 bool 264 Execute 265 ( 266 Args& args, 267 CommandReturnObject &result 268 ) 269 { 270 const int argc = args.GetArgumentCount(); 271 if (argc == 1) 272 { 273 const char *filename = args.GetArgumentAtIndex(0); 274 275 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename); 276 277 FileSpec cmd_file (filename, true); 278 ExecutionContext *exe_ctx = NULL; // Just use the default context. 279 bool echo_commands = true; 280 bool print_results = true; 281 282 m_interpreter.HandleCommandsFromFile (cmd_file, 283 exe_ctx, 284 m_options.m_stop_on_continue, 285 m_options.m_stop_on_error, 286 echo_commands, 287 print_results, 288 result); 289 } 290 else 291 { 292 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName()); 293 result.SetStatus (eReturnStatusFailed); 294 } 295 return result.Succeeded(); 296 297 } 298 }; 299 300 OptionDefinition 301 CommandObjectCommandsSource::CommandOptions::g_option_table[] = 302 { 303 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."}, 304 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."}, 305 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 306 }; 307 308 #pragma mark CommandObjectCommandsAlias 309 //------------------------------------------------------------------------- 310 // CommandObjectCommandsAlias 311 //------------------------------------------------------------------------- 312 313 static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" 314 "You must define a Python function with this signature:\n" 315 "def my_command_impl(debugger, args, result, dict):"; 316 317 318 class CommandObjectCommandsAlias : public CommandObject 319 { 320 321 322 public: 323 CommandObjectCommandsAlias (CommandInterpreter &interpreter) : 324 CommandObject (interpreter, 325 "command alias", 326 "Allow users to define their own debugger command abbreviations.", 327 NULL) 328 { 329 SetHelpLong( 330 "'alias' allows the user to create a short-cut or abbreviation for long \n\ 331 commands, multi-word commands, and commands that take particular options. \n\ 332 Below are some simple examples of how one might use the 'alias' command: \n\ 333 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\ 334 // command. \n\ 335 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\ 336 // command. Since breakpoint commands are two-word \n\ 337 // commands, the user will still need to enter the \n\ 338 // second word after 'bp', e.g. 'bp enable' or \n\ 339 // 'bp delete'. \n\ 340 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\ 341 // two-word command 'breakpoint list'. \n\ 342 \nAn alias can include some options for the command, with the values either \n\ 343 filled in at the time the alias is created, or specified as positional \n\ 344 arguments, to be filled in when the alias is invoked. The following example \n\ 345 shows how to create aliases with options: \n\ 346 \n\ 347 'commands alias bfl breakpoint set -f %1 -l %2' \n\ 348 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\ 349 options already part of the alias. So if the user wants to set a breakpoint \n\ 350 by file and line without explicitly having to use the -f and -l options, the \n\ 351 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\ 352 for the actual arguments that will be passed when the alias command is used. \n\ 353 The number in the placeholder refers to the position/order the actual value \n\ 354 occupies when the alias is used. All the occurrences of '%1' in the alias \n\ 355 will be replaced with the first argument, all the occurrences of '%2' in the \n\ 356 alias will be replaced with the second argument, and so on. This also allows \n\ 357 actual arguments to be used multiple times within an alias (see 'process \n\ 358 launch' example below). \n\ 359 Note: the positional arguments must substitute as whole words in the resultant\n\ 360 command, so you can't at present do something like:\n\ 361 \n\ 362 commands alias bcppfl breakpoint set -f %1.cpp -l %2\n\ 363 \n\ 364 to get the file extension \".cpp\" automatically appended. For more complex\n\ 365 aliasing, use the \"command regex\" command instead.\n\ 366 \nSo in the 'bfl' case, the actual file value will be \n\ 367 filled in with the first argument following 'bfl' and the actual line number \n\ 368 value will be filled in with the second argument. The user would use this \n\ 369 alias as follows: \n\ 370 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\ 371 <... some time later ...> \n\ 372 (lldb) bfl my-file.c 137 \n\ 373 \nThis would be the same as if the user had entered \n\ 374 'breakpoint set -f my-file.c -l 137'. \n\ 375 \nAnother example: \n\ 376 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\ 377 (lldb) pltty /dev/tty0 \n\ 378 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\ 379 \nIf the user always wanted to pass the same value to a particular option, the \n\ 380 alias could be defined with that value directly in the alias as a constant, \n\ 381 rather than using a positional placeholder: \n\ 382 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\ 383 // 3 of whatever file is indicated. \n"); 384 385 CommandArgumentEntry arg1; 386 CommandArgumentEntry arg2; 387 CommandArgumentEntry arg3; 388 CommandArgumentData alias_arg; 389 CommandArgumentData cmd_arg; 390 CommandArgumentData options_arg; 391 392 // Define the first (and only) variant of this arg. 393 alias_arg.arg_type = eArgTypeAliasName; 394 alias_arg.arg_repetition = eArgRepeatPlain; 395 396 // There is only one variant this argument could be; put it into the argument entry. 397 arg1.push_back (alias_arg); 398 399 // Define the first (and only) variant of this arg. 400 cmd_arg.arg_type = eArgTypeCommandName; 401 cmd_arg.arg_repetition = eArgRepeatPlain; 402 403 // There is only one variant this argument could be; put it into the argument entry. 404 arg2.push_back (cmd_arg); 405 406 // Define the first (and only) variant of this arg. 407 options_arg.arg_type = eArgTypeAliasOptions; 408 options_arg.arg_repetition = eArgRepeatOptional; 409 410 // There is only one variant this argument could be; put it into the argument entry. 411 arg3.push_back (options_arg); 412 413 // Push the data for the first argument into the m_arguments vector. 414 m_arguments.push_back (arg1); 415 m_arguments.push_back (arg2); 416 m_arguments.push_back (arg3); 417 } 418 419 ~CommandObjectCommandsAlias () 420 { 421 } 422 423 bool 424 WantsRawCommandString () 425 { 426 return true; 427 } 428 429 bool 430 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result) 431 { 432 Args args (raw_command_line); 433 std::string raw_command_string (raw_command_line); 434 435 size_t argc = args.GetArgumentCount(); 436 437 if (argc < 2) 438 { 439 result.AppendError ("'alias' requires at least two arguments"); 440 result.SetStatus (eReturnStatusFailed); 441 return false; 442 } 443 444 // Get the alias command. 445 446 const std::string alias_command = args.GetArgumentAtIndex (0); 447 448 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which 449 // does the stripping itself. 450 size_t pos = raw_command_string.find (alias_command); 451 if (pos == 0) 452 { 453 raw_command_string = raw_command_string.substr (alias_command.size()); 454 pos = raw_command_string.find_first_not_of (' '); 455 if ((pos != std::string::npos) && (pos > 0)) 456 raw_command_string = raw_command_string.substr (pos); 457 } 458 else 459 { 460 result.AppendError ("Error parsing command string. No alias created."); 461 result.SetStatus (eReturnStatusFailed); 462 return false; 463 } 464 465 466 // Verify that the command is alias-able. 467 if (m_interpreter.CommandExists (alias_command.c_str())) 468 { 469 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 470 alias_command.c_str()); 471 result.SetStatus (eReturnStatusFailed); 472 return false; 473 } 474 475 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string. 476 // raw_command_string is returned with the name of the command object stripped off the front. 477 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string); 478 479 if (!cmd_obj) 480 { 481 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command." 482 " No alias created.", raw_command_string.c_str()); 483 result.SetStatus (eReturnStatusFailed); 484 return false; 485 } 486 else if (!cmd_obj->WantsRawCommandString ()) 487 { 488 // Note that args was initialized with the original command, and has not been updated to this point. 489 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias. 490 return Execute (args, result); 491 } 492 else 493 { 494 // Verify & handle any options/arguments passed to the alias command 495 496 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 497 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 498 499 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 500 501 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp)) 502 { 503 result.AppendError ("Unable to create requested alias.\n"); 504 result.SetStatus (eReturnStatusFailed); 505 return false; 506 } 507 508 // Create the alias 509 if (m_interpreter.AliasExists (alias_command.c_str()) 510 || m_interpreter.UserCommandExists (alias_command.c_str())) 511 { 512 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 513 if (temp_option_arg_sp.get()) 514 { 515 if (option_arg_vector->size() == 0) 516 m_interpreter.RemoveAliasOptions (alias_command.c_str()); 517 } 518 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 519 alias_command.c_str()); 520 } 521 522 if (cmd_obj_sp) 523 { 524 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp); 525 if (option_arg_vector->size() > 0) 526 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 527 result.SetStatus (eReturnStatusSuccessFinishNoResult); 528 } 529 else 530 { 531 result.AppendError ("Unable to create requested alias.\n"); 532 result.SetStatus (eReturnStatusFailed); 533 } 534 } 535 return result.Succeeded(); 536 } 537 538 bool 539 Execute 540 ( 541 Args& args, 542 CommandReturnObject &result 543 ) 544 { 545 size_t argc = args.GetArgumentCount(); 546 547 if (argc < 2) 548 { 549 result.AppendError ("'alias' requires at least two arguments"); 550 result.SetStatus (eReturnStatusFailed); 551 return false; 552 } 553 554 const std::string alias_command = args.GetArgumentAtIndex(0); 555 const std::string actual_command = args.GetArgumentAtIndex(1); 556 557 args.Shift(); // Shift the alias command word off the argument vector. 558 args.Shift(); // Shift the old command word off the argument vector. 559 560 // Verify that the command is alias'able, and get the appropriate command object. 561 562 if (m_interpreter.CommandExists (alias_command.c_str())) 563 { 564 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n", 565 alias_command.c_str()); 566 result.SetStatus (eReturnStatusFailed); 567 } 568 else 569 { 570 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true)); 571 CommandObjectSP subcommand_obj_sp; 572 bool use_subcommand = false; 573 if (command_obj_sp.get()) 574 { 575 CommandObject *cmd_obj = command_obj_sp.get(); 576 CommandObject *sub_cmd_obj = NULL; 577 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector); 578 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 579 580 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) 581 { 582 if (argc >= 3) 583 { 584 const std::string sub_command = args.GetArgumentAtIndex(0); 585 assert (sub_command.length() != 0); 586 subcommand_obj_sp = 587 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str())); 588 if (subcommand_obj_sp.get()) 589 { 590 sub_cmd_obj = subcommand_obj_sp.get(); 591 use_subcommand = true; 592 args.Shift(); // Shift the sub_command word off the argument vector. 593 cmd_obj = sub_cmd_obj; 594 } 595 else 596 { 597 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. " 598 "Unable to create alias.\n", 599 sub_command.c_str(), actual_command.c_str()); 600 result.SetStatus (eReturnStatusFailed); 601 return false; 602 } 603 } 604 } 605 606 // Verify & handle any options/arguments passed to the alias command 607 608 if (args.GetArgumentCount () > 0) 609 { 610 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false); 611 if (use_subcommand) 612 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false); 613 614 std::string args_string; 615 args.GetCommandString (args_string); 616 617 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp)) 618 { 619 result.AppendError ("Unable to create requested alias.\n"); 620 result.SetStatus (eReturnStatusFailed); 621 return false; 622 } 623 } 624 625 // Create the alias. 626 627 if (m_interpreter.AliasExists (alias_command.c_str()) 628 || m_interpreter.UserCommandExists (alias_command.c_str())) 629 { 630 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str())); 631 if (tmp_option_arg_sp.get()) 632 { 633 if (option_arg_vector->size() == 0) 634 m_interpreter.RemoveAliasOptions (alias_command.c_str()); 635 } 636 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", 637 alias_command.c_str()); 638 } 639 640 if (use_subcommand) 641 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp); 642 else 643 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp); 644 if (option_arg_vector->size() > 0) 645 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp); 646 result.SetStatus (eReturnStatusSuccessFinishNoResult); 647 } 648 else 649 { 650 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str()); 651 result.SetStatus (eReturnStatusFailed); 652 return false; 653 } 654 } 655 656 return result.Succeeded(); 657 } 658 }; 659 660 #pragma mark CommandObjectCommandsUnalias 661 //------------------------------------------------------------------------- 662 // CommandObjectCommandsUnalias 663 //------------------------------------------------------------------------- 664 665 class CommandObjectCommandsUnalias : public CommandObject 666 { 667 public: 668 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) : 669 CommandObject (interpreter, 670 "command unalias", 671 "Allow the user to remove/delete a user-defined command abbreviation.", 672 NULL) 673 { 674 CommandArgumentEntry arg; 675 CommandArgumentData alias_arg; 676 677 // Define the first (and only) variant of this arg. 678 alias_arg.arg_type = eArgTypeAliasName; 679 alias_arg.arg_repetition = eArgRepeatPlain; 680 681 // There is only one variant this argument could be; put it into the argument entry. 682 arg.push_back (alias_arg); 683 684 // Push the data for the first argument into the m_arguments vector. 685 m_arguments.push_back (arg); 686 } 687 688 ~CommandObjectCommandsUnalias() 689 { 690 } 691 692 693 bool 694 Execute 695 ( 696 Args& args, 697 CommandReturnObject &result 698 ) 699 { 700 CommandObject::CommandMap::iterator pos; 701 CommandObject *cmd_obj; 702 703 if (args.GetArgumentCount() != 0) 704 { 705 const char *command_name = args.GetArgumentAtIndex(0); 706 cmd_obj = m_interpreter.GetCommandObject(command_name); 707 if (cmd_obj) 708 { 709 if (m_interpreter.CommandExists (command_name)) 710 { 711 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n", 712 command_name); 713 result.SetStatus (eReturnStatusFailed); 714 } 715 else 716 { 717 718 if (m_interpreter.RemoveAlias (command_name) == false) 719 { 720 if (m_interpreter.AliasExists (command_name)) 721 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", 722 command_name); 723 else 724 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name); 725 result.SetStatus (eReturnStatusFailed); 726 } 727 else 728 result.SetStatus (eReturnStatusSuccessFinishNoResult); 729 } 730 } 731 else 732 { 733 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a " 734 "current list of commands.\n", 735 command_name); 736 result.SetStatus (eReturnStatusFailed); 737 } 738 } 739 else 740 { 741 result.AppendError ("must call 'unalias' with a valid alias"); 742 result.SetStatus (eReturnStatusFailed); 743 } 744 745 return result.Succeeded(); 746 } 747 }; 748 749 #pragma mark CommandObjectCommandsAddRegex 750 //------------------------------------------------------------------------- 751 // CommandObjectCommandsAddRegex 752 //------------------------------------------------------------------------- 753 754 class CommandObjectCommandsAddRegex : public CommandObject 755 { 756 public: 757 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) : 758 CommandObject (interpreter, 759 "command regex", 760 "Allow the user to create a regular expression command.", 761 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 762 m_options (interpreter) 763 { 764 SetHelpLong( 765 "This command allows the user to create powerful regular expression commands\n" 766 "with substitutions. The regular expressions and substitutions are specified\n" 767 "using the regular exression substitution format of:\n" 768 "\n" 769 " s/<regex>/<subst>/\n" 770 "\n" 771 "<regex> is a regular expression that can use parenthesis to capture regular\n" 772 "expression input and substitute the captured matches in the output using %1\n" 773 "for the first match, %2 for the second, and so on.\n" 774 "\n" 775 "The regular expressions can all be specified on the command line if more than\n" 776 "one argument is provided. If just the command name is provided on the command\n" 777 "line, then the regular expressions and substitutions can be entered on separate\n" 778 " lines, followed by an empty line to terminate the command definition.\n" 779 "\n" 780 "EXAMPLES\n" 781 "\n" 782 "The following example with define a regular expression command named 'f' that\n" 783 "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n" 784 "a number follows 'f':\n" 785 "(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n" 786 ); 787 } 788 789 ~CommandObjectCommandsAddRegex() 790 { 791 } 792 793 794 bool 795 Execute (Args& args, CommandReturnObject &result) 796 { 797 const size_t argc = args.GetArgumentCount(); 798 if (argc == 0) 799 { 800 result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 801 result.SetStatus (eReturnStatusFailed); 802 } 803 else 804 { 805 Error error; 806 const char *name = args.GetArgumentAtIndex(0); 807 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter, 808 name, 809 m_options.GetHelp (), 810 m_options.GetSyntax (), 811 10)); 812 813 if (argc == 1) 814 { 815 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 816 if (reader_sp) 817 { 818 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback, 819 this, // baton 820 eInputReaderGranularityLine, // token size, to pass to callback function 821 NULL, // end token 822 "> ", // prompt 823 true); // echo input 824 if (error.Success()) 825 { 826 m_interpreter.GetDebugger().PushInputReader (reader_sp); 827 result.SetStatus (eReturnStatusSuccessFinishNoResult); 828 return true; 829 } 830 } 831 } 832 else 833 { 834 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) 835 { 836 llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx)); 837 error = AppendRegexSubstitution (arg_strref); 838 if (error.Fail()) 839 break; 840 } 841 842 if (error.Success()) 843 { 844 AddRegexCommandToInterpreter(); 845 } 846 } 847 if (error.Fail()) 848 { 849 result.AppendError (error.AsCString()); 850 result.SetStatus (eReturnStatusFailed); 851 } 852 } 853 854 return result.Succeeded(); 855 } 856 857 Error 858 AppendRegexSubstitution (const llvm::StringRef ®ex_sed) 859 { 860 Error error; 861 862 if (m_regex_cmd_ap.get() == NULL) 863 { 864 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'", 865 (int)regex_sed.size(), 866 regex_sed.data()); 867 return error; 868 } 869 870 size_t regex_sed_size = regex_sed.size(); 871 872 if (regex_sed_size <= 1) 873 { 874 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'", 875 (int)regex_sed.size(), 876 regex_sed.data()); 877 return error; 878 } 879 880 if (regex_sed[0] != 's') 881 { 882 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'", 883 (int)regex_sed.size(), 884 regex_sed.data()); 885 return error; 886 } 887 const size_t first_separator_char_pos = 1; 888 // use the char that follows 's' as the regex separator character 889 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 890 const char separator_char = regex_sed[first_separator_char_pos]; 891 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1); 892 893 if (second_separator_char_pos == std::string::npos) 894 { 895 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'", 896 separator_char, 897 (int)(regex_sed.size() - first_separator_char_pos - 1), 898 regex_sed.data() + (first_separator_char_pos + 1)); 899 return error; 900 } 901 902 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1); 903 904 if (third_separator_char_pos == std::string::npos) 905 { 906 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'", 907 separator_char, 908 (int)(regex_sed.size() - second_separator_char_pos - 1), 909 regex_sed.data() + (second_separator_char_pos + 1)); 910 return error; 911 } 912 913 if (third_separator_char_pos != regex_sed_size - 1) 914 { 915 // Make sure that everything that follows the last regex 916 // separator char 917 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos) 918 { 919 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'", 920 (int)third_separator_char_pos + 1, 921 regex_sed.data(), 922 (int)(regex_sed.size() - third_separator_char_pos - 1), 923 regex_sed.data() + (third_separator_char_pos + 1)); 924 return error; 925 } 926 927 } 928 else if (first_separator_char_pos + 1 == second_separator_char_pos) 929 { 930 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 931 separator_char, 932 separator_char, 933 separator_char, 934 (int)regex_sed.size(), 935 regex_sed.data()); 936 return error; 937 } 938 else if (second_separator_char_pos + 1 == third_separator_char_pos) 939 { 940 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 941 separator_char, 942 separator_char, 943 separator_char, 944 (int)regex_sed.size(), 945 regex_sed.data()); 946 return error; 947 } 948 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1)); 949 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1)); 950 m_regex_cmd_ap->AddRegexCommand (regex.c_str(), 951 subst.c_str()); 952 return error; 953 } 954 955 void 956 AddRegexCommandToInterpreter() 957 { 958 if (m_regex_cmd_ap.get()) 959 { 960 if (m_regex_cmd_ap->HasRegexEntries()) 961 { 962 CommandObjectSP cmd_sp (m_regex_cmd_ap.release()); 963 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 964 } 965 } 966 } 967 968 void 969 InputReaderDidCancel() 970 { 971 m_regex_cmd_ap.reset(); 972 } 973 974 static size_t 975 InputReaderCallback (void *baton, 976 InputReader &reader, 977 lldb::InputReaderAction notification, 978 const char *bytes, 979 size_t bytes_len); 980 private: 981 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap; 982 983 class CommandOptions : public Options 984 { 985 public: 986 987 CommandOptions (CommandInterpreter &interpreter) : 988 Options (interpreter) 989 { 990 } 991 992 virtual 993 ~CommandOptions (){} 994 995 virtual Error 996 SetOptionValue (uint32_t option_idx, const char *option_arg) 997 { 998 Error error; 999 char short_option = (char) m_getopt_table[option_idx].val; 1000 1001 switch (short_option) 1002 { 1003 case 'h': 1004 m_help.assign (option_arg); 1005 break; 1006 case 's': 1007 m_syntax.assign (option_arg); 1008 break; 1009 1010 default: 1011 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 1012 break; 1013 } 1014 1015 return error; 1016 } 1017 1018 void 1019 OptionParsingStarting () 1020 { 1021 m_help.clear(); 1022 m_syntax.clear(); 1023 } 1024 1025 const OptionDefinition* 1026 GetDefinitions () 1027 { 1028 return g_option_table; 1029 } 1030 1031 // Options table: Required for subclasses of Options. 1032 1033 static OptionDefinition g_option_table[]; 1034 1035 const char * 1036 GetHelp () 1037 { 1038 if (m_help.empty()) 1039 return NULL; 1040 return m_help.c_str(); 1041 } 1042 const char * 1043 GetSyntax () 1044 { 1045 if (m_syntax.empty()) 1046 return NULL; 1047 return m_syntax.c_str(); 1048 } 1049 // Instance variables to hold the values for command options. 1050 protected: 1051 std::string m_help; 1052 std::string m_syntax; 1053 }; 1054 1055 CommandOptions m_options; 1056 1057 virtual Options * 1058 GetOptions () 1059 { 1060 return &m_options; 1061 } 1062 1063 }; 1064 1065 size_t 1066 CommandObjectCommandsAddRegex::InputReaderCallback (void *baton, 1067 InputReader &reader, 1068 lldb::InputReaderAction notification, 1069 const char *bytes, 1070 size_t bytes_len) 1071 { 1072 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton; 1073 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode(); 1074 1075 switch (notification) 1076 { 1077 case eInputReaderActivate: 1078 if (!batch_mode) 1079 { 1080 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream (); 1081 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:"); 1082 out_stream->Flush(); 1083 } 1084 break; 1085 case eInputReaderReactivate: 1086 break; 1087 1088 case eInputReaderDeactivate: 1089 break; 1090 1091 case eInputReaderAsynchronousOutputWritten: 1092 break; 1093 1094 case eInputReaderGotToken: 1095 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n')) 1096 --bytes_len; 1097 if (bytes_len == 0) 1098 reader.SetIsDone(true); 1099 else if (bytes) 1100 { 1101 llvm::StringRef bytes_strref (bytes, bytes_len); 1102 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref)); 1103 if (error.Fail()) 1104 { 1105 if (!batch_mode) 1106 { 1107 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); 1108 out_stream->Printf("error: %s\n", error.AsCString()); 1109 out_stream->Flush(); 1110 } 1111 add_regex_cmd->InputReaderDidCancel (); 1112 reader.SetIsDone (true); 1113 } 1114 } 1115 break; 1116 1117 case eInputReaderInterrupt: 1118 { 1119 reader.SetIsDone (true); 1120 if (!batch_mode) 1121 { 1122 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream(); 1123 out_stream->PutCString("Regular expression command creations was cancelled.\n"); 1124 out_stream->Flush(); 1125 } 1126 add_regex_cmd->InputReaderDidCancel (); 1127 } 1128 break; 1129 1130 case eInputReaderEndOfFile: 1131 reader.SetIsDone (true); 1132 break; 1133 1134 case eInputReaderDone: 1135 add_regex_cmd->AddRegexCommandToInterpreter(); 1136 break; 1137 } 1138 1139 return bytes_len; 1140 } 1141 1142 1143 OptionDefinition 1144 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = 1145 { 1146 { LLDB_OPT_SET_1, false, "help" , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."}, 1147 { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."}, 1148 { 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL } 1149 }; 1150 1151 1152 class CommandObjectPythonFunction : public CommandObject 1153 { 1154 private: 1155 std::string m_function_name; 1156 1157 public: 1158 1159 CommandObjectPythonFunction (CommandInterpreter &interpreter, 1160 std::string name, 1161 std::string funct) : 1162 CommandObject (interpreter, 1163 name.c_str(), 1164 (std::string("Run Python function ") + funct).c_str(), 1165 NULL), 1166 m_function_name(funct) 1167 { 1168 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1169 if (scripter) 1170 { 1171 std::string docstring = scripter->GetDocumentationForItem(funct.c_str()); 1172 if (!docstring.empty()) 1173 SetHelpLong(docstring); 1174 } 1175 } 1176 1177 virtual 1178 ~CommandObjectPythonFunction () 1179 { 1180 } 1181 1182 virtual bool 1183 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result) 1184 { 1185 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter(); 1186 1187 Error error; 1188 1189 if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(), 1190 raw_command_line, 1191 result, 1192 error) == false) 1193 { 1194 result.AppendError(error.AsCString()); 1195 result.SetStatus(eReturnStatusFailed); 1196 } 1197 else 1198 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1199 1200 return result.Succeeded(); 1201 } 1202 1203 virtual bool 1204 WantsRawCommandString () 1205 { 1206 return true; 1207 } 1208 1209 bool 1210 Execute (Args& command, 1211 CommandReturnObject &result) 1212 { 1213 std::string cmd_string; 1214 command.GetCommandString(cmd_string); 1215 return ExecuteRawCommandString(cmd_string.c_str(), result); 1216 } 1217 1218 virtual bool 1219 IsRemovable() { return true; } 1220 1221 }; 1222 1223 1224 //------------------------------------------------------------------------- 1225 // CommandObjectCommandsScriptAdd 1226 //------------------------------------------------------------------------- 1227 1228 class CommandObjectCommandsScriptAdd : public CommandObject 1229 { 1230 private: 1231 1232 class CommandOptions : public Options 1233 { 1234 public: 1235 1236 CommandOptions (CommandInterpreter &interpreter) : 1237 Options (interpreter) 1238 { 1239 } 1240 1241 virtual 1242 ~CommandOptions (){} 1243 1244 virtual Error 1245 SetOptionValue (uint32_t option_idx, const char *option_arg) 1246 { 1247 Error error; 1248 char short_option = (char) m_getopt_table[option_idx].val; 1249 1250 switch (short_option) 1251 { 1252 case 'f': 1253 m_funct_name = std::string(option_arg); 1254 break; 1255 default: 1256 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 1257 break; 1258 } 1259 1260 return error; 1261 } 1262 1263 void 1264 OptionParsingStarting () 1265 { 1266 m_funct_name = ""; 1267 } 1268 1269 const OptionDefinition* 1270 GetDefinitions () 1271 { 1272 return g_option_table; 1273 } 1274 1275 // Options table: Required for subclasses of Options. 1276 1277 static OptionDefinition g_option_table[]; 1278 1279 // Instance variables to hold the values for command options. 1280 1281 std::string m_funct_name; 1282 }; 1283 1284 CommandOptions m_options; 1285 1286 virtual Options * 1287 GetOptions () 1288 { 1289 return &m_options; 1290 } 1291 1292 class PythonAliasReader : public InputReaderEZ 1293 { 1294 private: 1295 CommandInterpreter& m_interpreter; 1296 std::string m_cmd_name; 1297 StringList m_user_input; 1298 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader); 1299 public: 1300 PythonAliasReader(Debugger& debugger, 1301 CommandInterpreter& interpreter, 1302 std::string cmd_name) : 1303 InputReaderEZ(debugger), 1304 m_interpreter(interpreter), 1305 m_cmd_name(cmd_name), 1306 m_user_input() 1307 {} 1308 1309 virtual 1310 ~PythonAliasReader() 1311 { 1312 } 1313 1314 virtual void ActivateHandler(HandlerData& data) 1315 { 1316 StreamSP out_stream = data.GetOutStream(); 1317 bool batch_mode = data.GetBatchMode(); 1318 if (!batch_mode) 1319 { 1320 out_stream->Printf ("%s\n", g_python_command_instructions); 1321 if (data.reader.GetPrompt()) 1322 out_stream->Printf ("%s", data.reader.GetPrompt()); 1323 out_stream->Flush(); 1324 } 1325 } 1326 1327 virtual void ReactivateHandler(HandlerData& data) 1328 { 1329 StreamSP out_stream = data.GetOutStream(); 1330 bool batch_mode = data.GetBatchMode(); 1331 if (data.reader.GetPrompt() && !batch_mode) 1332 { 1333 out_stream->Printf ("%s", data.reader.GetPrompt()); 1334 out_stream->Flush(); 1335 } 1336 } 1337 virtual void GotTokenHandler(HandlerData& data) 1338 { 1339 StreamSP out_stream = data.GetOutStream(); 1340 bool batch_mode = data.GetBatchMode(); 1341 if (data.bytes && data.bytes_len) 1342 { 1343 m_user_input.AppendString(data.bytes, data.bytes_len); 1344 } 1345 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode) 1346 { 1347 out_stream->Printf ("%s", data.reader.GetPrompt()); 1348 out_stream->Flush(); 1349 } 1350 } 1351 virtual void InterruptHandler(HandlerData& data) 1352 { 1353 StreamSP out_stream = data.GetOutStream(); 1354 bool batch_mode = data.GetBatchMode(); 1355 data.reader.SetIsDone (true); 1356 if (!batch_mode) 1357 { 1358 out_stream->Printf ("Warning: No command attached to breakpoint.\n"); 1359 out_stream->Flush(); 1360 } 1361 } 1362 virtual void EOFHandler(HandlerData& data) 1363 { 1364 data.reader.SetIsDone (true); 1365 } 1366 virtual void DoneHandler(HandlerData& data) 1367 { 1368 StreamSP out_stream = data.GetOutStream(); 1369 1370 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); 1371 if (!interpreter) 1372 { 1373 out_stream->Printf ("Internal error #1: no script attached.\n"); 1374 out_stream->Flush(); 1375 return; 1376 } 1377 StringList funct_name_sl; 1378 if (!interpreter->GenerateScriptAliasFunction (m_user_input, 1379 funct_name_sl)) 1380 { 1381 out_stream->Printf ("Internal error #2: no script attached.\n"); 1382 out_stream->Flush(); 1383 return; 1384 } 1385 if (funct_name_sl.GetSize() == 0) 1386 { 1387 out_stream->Printf ("Internal error #3: no script attached.\n"); 1388 out_stream->Flush(); 1389 return; 1390 } 1391 const char *funct_name = funct_name_sl.GetStringAtIndex(0); 1392 if (!funct_name || !funct_name[0]) 1393 { 1394 out_stream->Printf ("Internal error #4: no script attached.\n"); 1395 out_stream->Flush(); 1396 return; 1397 } 1398 1399 // everything should be fine now, let's add this alias 1400 1401 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter, 1402 m_cmd_name, 1403 funct_name)); 1404 1405 if (!m_interpreter.AddUserCommand(m_cmd_name.c_str(), command_obj_sp, true)) 1406 { 1407 out_stream->Printf ("Internal error #5: no script attached.\n"); 1408 out_stream->Flush(); 1409 return; 1410 } 1411 } 1412 }; 1413 1414 public: 1415 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) : 1416 CommandObject (interpreter, 1417 "command script add", 1418 "Add a scripted function as an LLDB command.", 1419 NULL), 1420 m_options (interpreter) 1421 { 1422 CommandArgumentEntry arg1; 1423 CommandArgumentData cmd_arg; 1424 1425 // Define the first (and only) variant of this arg. 1426 cmd_arg.arg_type = eArgTypeCommandName; 1427 cmd_arg.arg_repetition = eArgRepeatPlain; 1428 1429 // There is only one variant this argument could be; put it into the argument entry. 1430 arg1.push_back (cmd_arg); 1431 1432 // Push the data for the first argument into the m_arguments vector. 1433 m_arguments.push_back (arg1); 1434 } 1435 1436 ~CommandObjectCommandsScriptAdd () 1437 { 1438 } 1439 1440 bool 1441 Execute 1442 ( 1443 Args& args, 1444 CommandReturnObject &result 1445 ) 1446 { 1447 1448 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) 1449 { 1450 result.AppendError ("only scripting language supported for scripted commands is currently Python"); 1451 result.SetStatus (eReturnStatusFailed); 1452 return false; 1453 } 1454 1455 size_t argc = args.GetArgumentCount(); 1456 1457 if (argc != 1) 1458 { 1459 result.AppendError ("'command script add' requires one argument"); 1460 result.SetStatus (eReturnStatusFailed); 1461 return false; 1462 } 1463 1464 std::string cmd_name = args.GetArgumentAtIndex(0); 1465 1466 if (m_options.m_funct_name.empty()) 1467 { 1468 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(), 1469 m_interpreter, 1470 cmd_name)); 1471 1472 if (reader_sp) 1473 { 1474 1475 InputReaderEZ::InitializationParameters ipr; 1476 1477 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" "))); 1478 if (err.Success()) 1479 { 1480 m_interpreter.GetDebugger().PushInputReader (reader_sp); 1481 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1482 } 1483 else 1484 { 1485 result.AppendError (err.AsCString()); 1486 result.SetStatus (eReturnStatusFailed); 1487 } 1488 } 1489 else 1490 { 1491 result.AppendError("out of memory"); 1492 result.SetStatus (eReturnStatusFailed); 1493 } 1494 } 1495 else 1496 { 1497 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, cmd_name, m_options.m_funct_name)); 1498 if (m_interpreter.AddUserCommand(cmd_name.c_str(), new_cmd, true)) 1499 { 1500 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1501 } 1502 else 1503 { 1504 result.AppendError("cannot add command"); 1505 result.SetStatus (eReturnStatusFailed); 1506 } 1507 } 1508 1509 return result.Succeeded(); 1510 1511 } 1512 }; 1513 1514 OptionDefinition 1515 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = 1516 { 1517 { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."}, 1518 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1519 }; 1520 1521 //------------------------------------------------------------------------- 1522 // CommandObjectCommandsScriptList 1523 //------------------------------------------------------------------------- 1524 1525 class CommandObjectCommandsScriptList : public CommandObject 1526 { 1527 private: 1528 1529 public: 1530 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) : 1531 CommandObject (interpreter, 1532 "command script list", 1533 "List defined scripted commands.", 1534 NULL) 1535 { 1536 } 1537 1538 ~CommandObjectCommandsScriptList () 1539 { 1540 } 1541 1542 bool 1543 Execute 1544 ( 1545 Args& args, 1546 CommandReturnObject &result 1547 ) 1548 { 1549 1550 m_interpreter.GetHelp(result, 1551 CommandInterpreter::eCommandTypesUserDef); 1552 1553 result.SetStatus (eReturnStatusSuccessFinishResult); 1554 1555 return true; 1556 1557 1558 } 1559 }; 1560 1561 //------------------------------------------------------------------------- 1562 // CommandObjectCommandsScriptClear 1563 //------------------------------------------------------------------------- 1564 1565 class CommandObjectCommandsScriptClear : public CommandObject 1566 { 1567 private: 1568 1569 public: 1570 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) : 1571 CommandObject (interpreter, 1572 "command script clear", 1573 "Delete all scripted commands.", 1574 NULL) 1575 { 1576 } 1577 1578 ~CommandObjectCommandsScriptClear () 1579 { 1580 } 1581 1582 bool 1583 Execute 1584 ( 1585 Args& args, 1586 CommandReturnObject &result 1587 ) 1588 { 1589 1590 m_interpreter.RemoveAllUser(); 1591 1592 result.SetStatus (eReturnStatusSuccessFinishResult); 1593 1594 return true; 1595 1596 1597 } 1598 }; 1599 1600 //------------------------------------------------------------------------- 1601 // CommandObjectCommandsScriptDelete 1602 //------------------------------------------------------------------------- 1603 1604 class CommandObjectCommandsScriptDelete : public CommandObject 1605 { 1606 private: 1607 1608 public: 1609 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) : 1610 CommandObject (interpreter, 1611 "command script delete", 1612 "Delete a scripted command.", 1613 NULL) 1614 { 1615 CommandArgumentEntry arg1; 1616 CommandArgumentData cmd_arg; 1617 1618 // Define the first (and only) variant of this arg. 1619 cmd_arg.arg_type = eArgTypeCommandName; 1620 cmd_arg.arg_repetition = eArgRepeatPlain; 1621 1622 // There is only one variant this argument could be; put it into the argument entry. 1623 arg1.push_back (cmd_arg); 1624 1625 // Push the data for the first argument into the m_arguments vector. 1626 m_arguments.push_back (arg1); 1627 } 1628 1629 ~CommandObjectCommandsScriptDelete () 1630 { 1631 } 1632 1633 bool 1634 Execute 1635 ( 1636 Args& args, 1637 CommandReturnObject &result 1638 ) 1639 { 1640 1641 size_t argc = args.GetArgumentCount(); 1642 1643 if (argc != 1) 1644 { 1645 result.AppendError ("'command script delete' requires one argument"); 1646 result.SetStatus (eReturnStatusFailed); 1647 return false; 1648 } 1649 1650 const char* cmd_name = args.GetArgumentAtIndex(0); 1651 1652 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name)) 1653 { 1654 m_interpreter.RemoveUser(cmd_name); 1655 result.SetStatus (eReturnStatusSuccessFinishResult); 1656 } 1657 else 1658 { 1659 result.AppendErrorWithFormat ("command %s not found", cmd_name); 1660 result.SetStatus (eReturnStatusFailed); 1661 } 1662 1663 return result.Succeeded(); 1664 1665 } 1666 }; 1667 1668 #pragma mark CommandObjectMultiwordCommandsScript 1669 1670 //------------------------------------------------------------------------- 1671 // CommandObjectMultiwordCommandsScript 1672 //------------------------------------------------------------------------- 1673 1674 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword 1675 { 1676 public: 1677 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) : 1678 CommandObjectMultiword (interpreter, 1679 "command script", 1680 "A set of commands for managing or customizing script commands.", 1681 "command script <subcommand> [<subcommand-options>]") 1682 { 1683 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter))); 1684 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter))); 1685 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter))); 1686 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter))); 1687 } 1688 1689 ~CommandObjectMultiwordCommandsScript () 1690 { 1691 } 1692 1693 }; 1694 1695 1696 #pragma mark CommandObjectMultiwordCommands 1697 1698 //------------------------------------------------------------------------- 1699 // CommandObjectMultiwordCommands 1700 //------------------------------------------------------------------------- 1701 1702 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) : 1703 CommandObjectMultiword (interpreter, 1704 "command", 1705 "A set of commands for managing or customizing the debugger commands.", 1706 "command <subcommand> [<subcommand-options>]") 1707 { 1708 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter))); 1709 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter))); 1710 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter))); 1711 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter))); 1712 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter))); 1713 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter))); 1714 } 1715 1716 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands () 1717 { 1718 } 1719 1720