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