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