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