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