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