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