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 #include <optional> 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 // CommandObjectCommandsSource 33 34 #define LLDB_OPTIONS_source 35 #include "CommandOptions.inc" 36 37 class CommandObjectCommandsSource : public CommandObjectParsed { 38 public: 39 CommandObjectCommandsSource(CommandInterpreter &interpreter) 40 : CommandObjectParsed( 41 interpreter, "command source", 42 "Read and execute LLDB commands from the file <filename>.", 43 nullptr) { 44 AddSimpleArgumentList(eArgTypeFilename); 45 } 46 47 ~CommandObjectCommandsSource() override = default; 48 49 std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, 50 uint32_t index) override { 51 return std::string(""); 52 } 53 54 Options *GetOptions() override { return &m_options; } 55 56 protected: 57 class CommandOptions : public Options { 58 public: 59 CommandOptions() 60 : m_stop_on_error(true), m_silent_run(false), m_stop_on_continue(true), 61 m_cmd_relative_to_command_file(false) {} 62 63 ~CommandOptions() override = default; 64 65 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 66 ExecutionContext *execution_context) override { 67 Status error; 68 const int short_option = m_getopt_table[option_idx].val; 69 70 switch (short_option) { 71 case 'e': 72 error = m_stop_on_error.SetValueFromString(option_arg); 73 break; 74 75 case 'c': 76 error = m_stop_on_continue.SetValueFromString(option_arg); 77 break; 78 79 case 'C': 80 m_cmd_relative_to_command_file = true; 81 break; 82 83 case 's': 84 error = m_silent_run.SetValueFromString(option_arg); 85 break; 86 87 default: 88 llvm_unreachable("Unimplemented option"); 89 } 90 91 return error; 92 } 93 94 void OptionParsingStarting(ExecutionContext *execution_context) override { 95 m_stop_on_error.Clear(); 96 m_silent_run.Clear(); 97 m_stop_on_continue.Clear(); 98 m_cmd_relative_to_command_file.Clear(); 99 } 100 101 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 102 return llvm::ArrayRef(g_source_options); 103 } 104 105 // Instance variables to hold the values for command options. 106 107 OptionValueBoolean m_stop_on_error; 108 OptionValueBoolean m_silent_run; 109 OptionValueBoolean m_stop_on_continue; 110 OptionValueBoolean m_cmd_relative_to_command_file; 111 }; 112 113 void DoExecute(Args &command, CommandReturnObject &result) override { 114 if (command.GetArgumentCount() != 1) { 115 result.AppendErrorWithFormat( 116 "'%s' takes exactly one executable filename argument.\n", 117 GetCommandName().str().c_str()); 118 return; 119 } 120 121 FileSpec source_dir = {}; 122 if (m_options.m_cmd_relative_to_command_file) { 123 source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir(); 124 if (!source_dir) { 125 result.AppendError("command source -C can only be specified " 126 "from a command file"); 127 result.SetStatus(eReturnStatusFailed); 128 return; 129 } 130 } 131 132 FileSpec cmd_file(command[0].ref()); 133 if (source_dir) { 134 // Prepend the source_dir to the cmd_file path: 135 if (!cmd_file.IsRelative()) { 136 result.AppendError("command source -C can only be used " 137 "with a relative path."); 138 result.SetStatus(eReturnStatusFailed); 139 return; 140 } 141 cmd_file.MakeAbsolute(source_dir); 142 } 143 144 FileSystem::Instance().Resolve(cmd_file); 145 146 CommandInterpreterRunOptions options; 147 // If any options were set, then use them 148 if (m_options.m_stop_on_error.OptionWasSet() || 149 m_options.m_silent_run.OptionWasSet() || 150 m_options.m_stop_on_continue.OptionWasSet()) { 151 if (m_options.m_stop_on_continue.OptionWasSet()) 152 options.SetStopOnContinue( 153 m_options.m_stop_on_continue.GetCurrentValue()); 154 155 if (m_options.m_stop_on_error.OptionWasSet()) 156 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 157 158 // Individual silent setting is override for global command echo settings. 159 if (m_options.m_silent_run.GetCurrentValue()) { 160 options.SetSilent(true); 161 } else { 162 options.SetPrintResults(true); 163 options.SetPrintErrors(true); 164 options.SetEchoCommands(m_interpreter.GetEchoCommands()); 165 options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands()); 166 } 167 } 168 169 m_interpreter.HandleCommandsFromFile(cmd_file, options, result); 170 } 171 172 CommandOptions m_options; 173 }; 174 175 #pragma mark CommandObjectCommandsAlias 176 // CommandObjectCommandsAlias 177 178 #define LLDB_OPTIONS_alias 179 #include "CommandOptions.inc" 180 181 static const char *g_python_command_instructions = 182 "Enter your Python command(s). Type 'DONE' to end.\n" 183 "You must define a Python function with this signature:\n" 184 "def my_command_impl(debugger, args, exe_ctx, result, internal_dict):\n"; 185 186 class CommandObjectCommandsAlias : public CommandObjectRaw { 187 protected: 188 class CommandOptions : public OptionGroup { 189 public: 190 CommandOptions() = default; 191 192 ~CommandOptions() override = default; 193 194 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 195 return llvm::ArrayRef(g_alias_options); 196 } 197 198 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 199 ExecutionContext *execution_context) override { 200 Status error; 201 202 const int short_option = GetDefinitions()[option_idx].short_option; 203 std::string option_str(option_value); 204 205 switch (short_option) { 206 case 'h': 207 m_help.SetCurrentValue(option_str); 208 m_help.SetOptionWasSet(); 209 break; 210 211 case 'H': 212 m_long_help.SetCurrentValue(option_str); 213 m_long_help.SetOptionWasSet(); 214 break; 215 216 default: 217 llvm_unreachable("Unimplemented option"); 218 } 219 220 return error; 221 } 222 223 void OptionParsingStarting(ExecutionContext *execution_context) override { 224 m_help.Clear(); 225 m_long_help.Clear(); 226 } 227 228 OptionValueString m_help; 229 OptionValueString m_long_help; 230 }; 231 232 OptionGroupOptions m_option_group; 233 CommandOptions m_command_options; 234 235 public: 236 Options *GetOptions() override { return &m_option_group; } 237 238 CommandObjectCommandsAlias(CommandInterpreter &interpreter) 239 : CommandObjectRaw( 240 interpreter, "command alias", 241 "Define a custom command in terms of an existing command.") { 242 m_option_group.Append(&m_command_options); 243 m_option_group.Finalize(); 244 245 SetHelpLong( 246 "'alias' allows the user to create a short-cut or abbreviation for long \ 247 commands, multi-word commands, and commands that take particular options. \ 248 Below are some simple examples of how one might use the 'alias' command:" 249 R"( 250 251 (lldb) command alias sc script 252 253 Creates the abbreviation 'sc' for the 'script' command. 254 255 (lldb) command alias bp breakpoint 256 257 )" 258 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 259 breakpoint commands are two-word commands, the user would still need to \ 260 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 261 R"( 262 263 (lldb) command alias bpl breakpoint list 264 265 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 266 267 )" 268 "An alias can include some options for the command, with the values either \ 269 filled in at the time the alias is created, or specified as positional \ 270 arguments, to be filled in when the alias is invoked. The following example \ 271 shows how to create aliases with options:" 272 R"( 273 274 (lldb) command alias bfl breakpoint set -f %1 -l %2 275 276 )" 277 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 278 options already part of the alias. So if the user wants to set a breakpoint \ 279 by file and line without explicitly having to use the -f and -l options, the \ 280 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 281 for the actual arguments that will be passed when the alias command is used. \ 282 The number in the placeholder refers to the position/order the actual value \ 283 occupies when the alias is used. All the occurrences of '%1' in the alias \ 284 will be replaced with the first argument, all the occurrences of '%2' in the \ 285 alias will be replaced with the second argument, and so on. This also allows \ 286 actual arguments to be used multiple times within an alias (see 'process \ 287 launch' example below)." 288 R"( 289 290 )" 291 "Note: the positional arguments must substitute as whole words in the resultant \ 292 command, so you can't at present do something like this to append the file extension \ 293 \".cpp\":" 294 R"( 295 296 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 297 298 )" 299 "For more complex aliasing, use the \"command regex\" command instead. In the \ 300 'bfl' case above, the actual file value will be filled in with the first argument \ 301 following 'bfl' and the actual line number value will be filled in with the second \ 302 argument. The user would use this alias as follows:" 303 R"( 304 305 (lldb) command alias bfl breakpoint set -f %1 -l %2 306 (lldb) bfl my-file.c 137 307 308 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 309 310 Another example: 311 312 (lldb) command alias pltty process launch -s -o %1 -e %1 313 (lldb) pltty /dev/tty0 314 315 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 316 317 )" 318 "If the user always wanted to pass the same value to a particular option, the \ 319 alias could be defined with that value directly in the alias as a constant, \ 320 rather than using a positional placeholder:" 321 R"( 322 323 (lldb) command alias bl3 breakpoint set -f %1 -l 3 324 325 Always sets a breakpoint on line 3 of whatever file is indicated.)"); 326 327 CommandArgumentEntry arg1; 328 CommandArgumentEntry arg2; 329 CommandArgumentEntry arg3; 330 CommandArgumentData alias_arg; 331 CommandArgumentData cmd_arg; 332 CommandArgumentData options_arg; 333 334 // Define the first (and only) variant of this arg. 335 alias_arg.arg_type = eArgTypeAliasName; 336 alias_arg.arg_repetition = eArgRepeatPlain; 337 338 // There is only one variant this argument could be; put it into the 339 // argument entry. 340 arg1.push_back(alias_arg); 341 342 // Define the first (and only) variant of this arg. 343 cmd_arg.arg_type = eArgTypeCommandName; 344 cmd_arg.arg_repetition = eArgRepeatPlain; 345 346 // There is only one variant this argument could be; put it into the 347 // argument entry. 348 arg2.push_back(cmd_arg); 349 350 // Define the first (and only) variant of this arg. 351 options_arg.arg_type = eArgTypeAliasOptions; 352 options_arg.arg_repetition = eArgRepeatOptional; 353 354 // There is only one variant this argument could be; put it into the 355 // argument entry. 356 arg3.push_back(options_arg); 357 358 // Push the data for the first argument into the m_arguments vector. 359 m_arguments.push_back(arg1); 360 m_arguments.push_back(arg2); 361 m_arguments.push_back(arg3); 362 } 363 364 ~CommandObjectCommandsAlias() override = default; 365 366 protected: 367 void DoExecute(llvm::StringRef raw_command_line, 368 CommandReturnObject &result) override { 369 if (raw_command_line.empty()) { 370 result.AppendError("'command alias' requires at least two arguments"); 371 return; 372 } 373 374 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 375 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 376 377 OptionsWithRaw args_with_suffix(raw_command_line); 378 379 if (args_with_suffix.HasArgs()) 380 if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result, 381 m_option_group, exe_ctx)) 382 return; 383 384 llvm::StringRef raw_command_string = args_with_suffix.GetRawPart(); 385 Args args(raw_command_string); 386 387 if (args.GetArgumentCount() < 2) { 388 result.AppendError("'command alias' requires at least two arguments"); 389 return; 390 } 391 392 // Get the alias command. 393 394 auto alias_command = args[0].ref(); 395 if (alias_command.starts_with("-")) { 396 result.AppendError("aliases starting with a dash are not supported"); 397 if (alias_command == "--help" || alias_command == "--long-help") { 398 result.AppendWarning("if trying to pass options to 'command alias' add " 399 "a -- at the end of the options"); 400 } 401 return; 402 } 403 404 // Strip the new alias name off 'raw_command_string' (leave it on args, 405 // which gets passed to 'Execute', which does the stripping itself. 406 size_t pos = raw_command_string.find(alias_command); 407 if (pos == 0) { 408 raw_command_string = raw_command_string.substr(alias_command.size()); 409 pos = raw_command_string.find_first_not_of(' '); 410 if ((pos != std::string::npos) && (pos > 0)) 411 raw_command_string = raw_command_string.substr(pos); 412 } else { 413 result.AppendError("Error parsing command string. No alias created."); 414 return; 415 } 416 417 // Verify that the command is alias-able. 418 if (m_interpreter.CommandExists(alias_command)) { 419 result.AppendErrorWithFormat( 420 "'%s' is a permanent debugger command and cannot be redefined.\n", 421 args[0].c_str()); 422 return; 423 } 424 425 if (m_interpreter.UserMultiwordCommandExists(alias_command)) { 426 result.AppendErrorWithFormat( 427 "'%s' is a user container command and cannot be overwritten.\n" 428 "Delete it first with 'command container delete'\n", 429 args[0].c_str()); 430 return; 431 } 432 433 // Get CommandObject that is being aliased. The command name is read from 434 // the front of raw_command_string. raw_command_string is returned with the 435 // name of the command object stripped off the front. 436 llvm::StringRef original_raw_command_string = raw_command_string; 437 CommandObject *cmd_obj = 438 m_interpreter.GetCommandObjectForCommand(raw_command_string); 439 440 if (!cmd_obj) { 441 result.AppendErrorWithFormat("invalid command given to 'command alias'. " 442 "'%s' does not begin with a valid command." 443 " No alias created.", 444 original_raw_command_string.str().c_str()); 445 } else if (!cmd_obj->WantsRawCommandString()) { 446 // Note that args was initialized with the original command, and has not 447 // been updated to this point. Therefore can we pass it to the version of 448 // Execute that does not need/expect raw input in the alias. 449 HandleAliasingNormalCommand(args, result); 450 } else { 451 HandleAliasingRawCommand(alias_command, raw_command_string, *cmd_obj, 452 result); 453 } 454 } 455 456 bool HandleAliasingRawCommand(llvm::StringRef alias_command, 457 llvm::StringRef raw_command_string, 458 CommandObject &cmd_obj, 459 CommandReturnObject &result) { 460 // Verify & handle any options/arguments passed to the alias command 461 462 OptionArgVectorSP option_arg_vector_sp = 463 OptionArgVectorSP(new OptionArgVector); 464 465 const bool include_aliases = true; 466 // Look up the command using command's name first. This is to resolve 467 // aliases when you are making nested aliases. But if you don't find 468 // it that way, then it wasn't an alias and we can just use the object 469 // we were passed in. 470 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact( 471 cmd_obj.GetCommandName(), include_aliases); 472 if (!cmd_obj_sp) 473 cmd_obj_sp = cmd_obj.shared_from_this(); 474 475 if (m_interpreter.AliasExists(alias_command) || 476 m_interpreter.UserCommandExists(alias_command)) { 477 result.AppendWarningWithFormat( 478 "Overwriting existing definition for '%s'.\n", 479 alias_command.str().c_str()); 480 } 481 if (CommandAlias *alias = m_interpreter.AddAlias( 482 alias_command, cmd_obj_sp, raw_command_string)) { 483 if (m_command_options.m_help.OptionWasSet()) 484 alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 485 if (m_command_options.m_long_help.OptionWasSet()) 486 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 487 result.SetStatus(eReturnStatusSuccessFinishNoResult); 488 } else { 489 result.AppendError("Unable to create requested alias.\n"); 490 } 491 return result.Succeeded(); 492 } 493 494 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 495 size_t argc = args.GetArgumentCount(); 496 497 if (argc < 2) { 498 result.AppendError("'command alias' requires at least two arguments"); 499 return false; 500 } 501 502 // Save these in std::strings since we're going to shift them off. 503 const std::string alias_command(std::string(args[0].ref())); 504 const std::string actual_command(std::string(args[1].ref())); 505 506 args.Shift(); // Shift the alias command word off the argument vector. 507 args.Shift(); // Shift the old command word off the argument vector. 508 509 // Verify that the command is alias'able, and get the appropriate command 510 // object. 511 512 if (m_interpreter.CommandExists(alias_command)) { 513 result.AppendErrorWithFormat( 514 "'%s' is a permanent debugger command and cannot be redefined.\n", 515 alias_command.c_str()); 516 return false; 517 } 518 519 if (m_interpreter.UserMultiwordCommandExists(alias_command)) { 520 result.AppendErrorWithFormat( 521 "'%s' is user container command and cannot be overwritten.\n" 522 "Delete it first with 'command container delete'", 523 alias_command.c_str()); 524 return false; 525 } 526 527 CommandObjectSP command_obj_sp( 528 m_interpreter.GetCommandSPExact(actual_command, true)); 529 CommandObjectSP subcommand_obj_sp; 530 bool use_subcommand = false; 531 if (!command_obj_sp) { 532 result.AppendErrorWithFormat("'%s' is not an existing command.\n", 533 actual_command.c_str()); 534 return false; 535 } 536 CommandObject *cmd_obj = command_obj_sp.get(); 537 CommandObject *sub_cmd_obj = nullptr; 538 OptionArgVectorSP option_arg_vector_sp = 539 OptionArgVectorSP(new OptionArgVector); 540 541 while (cmd_obj->IsMultiwordObject() && !args.empty()) { 542 auto sub_command = args[0].ref(); 543 assert(!sub_command.empty()); 544 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 545 if (!subcommand_obj_sp) { 546 result.AppendErrorWithFormat( 547 "'%s' is not a valid sub-command of '%s'. " 548 "Unable to create alias.\n", 549 args[0].c_str(), actual_command.c_str()); 550 return false; 551 } 552 553 sub_cmd_obj = subcommand_obj_sp.get(); 554 use_subcommand = true; 555 args.Shift(); // Shift the sub_command word off the argument vector. 556 cmd_obj = sub_cmd_obj; 557 } 558 559 // Verify & handle any options/arguments passed to the alias command 560 561 std::string args_string; 562 563 if (!args.empty()) { 564 CommandObjectSP tmp_sp = 565 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName()); 566 if (use_subcommand) 567 tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName()); 568 569 args.GetCommandString(args_string); 570 } 571 572 if (m_interpreter.AliasExists(alias_command) || 573 m_interpreter.UserCommandExists(alias_command)) { 574 result.AppendWarningWithFormat( 575 "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 576 } 577 578 if (CommandAlias *alias = m_interpreter.AddAlias( 579 alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 580 args_string)) { 581 if (m_command_options.m_help.OptionWasSet()) 582 alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 583 if (m_command_options.m_long_help.OptionWasSet()) 584 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 585 result.SetStatus(eReturnStatusSuccessFinishNoResult); 586 } else { 587 result.AppendError("Unable to create requested alias.\n"); 588 return false; 589 } 590 591 return result.Succeeded(); 592 } 593 }; 594 595 #pragma mark CommandObjectCommandsUnalias 596 // CommandObjectCommandsUnalias 597 598 class CommandObjectCommandsUnalias : public CommandObjectParsed { 599 public: 600 CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 601 : CommandObjectParsed( 602 interpreter, "command unalias", 603 "Delete one or more custom commands defined by 'command alias'.", 604 nullptr) { 605 AddSimpleArgumentList(eArgTypeAliasName); 606 } 607 608 ~CommandObjectCommandsUnalias() override = default; 609 610 void 611 HandleArgumentCompletion(CompletionRequest &request, 612 OptionElementVector &opt_element_vector) override { 613 if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 614 return; 615 616 for (const auto &ent : m_interpreter.GetAliases()) { 617 request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp()); 618 } 619 } 620 621 protected: 622 void DoExecute(Args &args, CommandReturnObject &result) override { 623 CommandObject::CommandMap::iterator pos; 624 CommandObject *cmd_obj; 625 626 if (args.empty()) { 627 result.AppendError("must call 'unalias' with a valid alias"); 628 return; 629 } 630 631 auto command_name = args[0].ref(); 632 cmd_obj = m_interpreter.GetCommandObject(command_name); 633 if (!cmd_obj) { 634 result.AppendErrorWithFormat( 635 "'%s' is not a known command.\nTry 'help' to see a " 636 "current list of commands.\n", 637 args[0].c_str()); 638 return; 639 } 640 641 if (m_interpreter.CommandExists(command_name)) { 642 if (cmd_obj->IsRemovable()) { 643 result.AppendErrorWithFormat( 644 "'%s' is not an alias, it is a debugger command which can be " 645 "removed using the 'command delete' command.\n", 646 args[0].c_str()); 647 } else { 648 result.AppendErrorWithFormat( 649 "'%s' is a permanent debugger command and cannot be removed.\n", 650 args[0].c_str()); 651 } 652 return; 653 } 654 655 if (!m_interpreter.RemoveAlias(command_name)) { 656 if (m_interpreter.AliasExists(command_name)) 657 result.AppendErrorWithFormat( 658 "Error occurred while attempting to unalias '%s'.\n", 659 args[0].c_str()); 660 else 661 result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 662 args[0].c_str()); 663 return; 664 } 665 666 result.SetStatus(eReturnStatusSuccessFinishNoResult); 667 } 668 }; 669 670 #pragma mark CommandObjectCommandsDelete 671 // CommandObjectCommandsDelete 672 673 class CommandObjectCommandsDelete : public CommandObjectParsed { 674 public: 675 CommandObjectCommandsDelete(CommandInterpreter &interpreter) 676 : CommandObjectParsed( 677 interpreter, "command delete", 678 "Delete one or more custom commands defined by 'command regex'.", 679 nullptr) { 680 AddSimpleArgumentList(eArgTypeCommandName); 681 } 682 683 ~CommandObjectCommandsDelete() override = default; 684 685 void 686 HandleArgumentCompletion(CompletionRequest &request, 687 OptionElementVector &opt_element_vector) override { 688 if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 689 return; 690 691 for (const auto &ent : m_interpreter.GetCommands()) { 692 if (ent.second->IsRemovable()) 693 request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp()); 694 } 695 } 696 697 protected: 698 void DoExecute(Args &args, CommandReturnObject &result) override { 699 CommandObject::CommandMap::iterator pos; 700 701 if (args.empty()) { 702 result.AppendErrorWithFormat("must call '%s' with one or more valid user " 703 "defined regular expression command names", 704 GetCommandName().str().c_str()); 705 return; 706 } 707 708 auto command_name = args[0].ref(); 709 if (!m_interpreter.CommandExists(command_name)) { 710 StreamString error_msg_stream; 711 const bool generate_upropos = true; 712 const bool generate_type_lookup = false; 713 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 714 &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 715 generate_upropos, generate_type_lookup); 716 result.AppendError(error_msg_stream.GetString()); 717 return; 718 } 719 720 if (!m_interpreter.RemoveCommand(command_name)) { 721 result.AppendErrorWithFormat( 722 "'%s' is a permanent debugger command and cannot be removed.\n", 723 args[0].c_str()); 724 return; 725 } 726 727 result.SetStatus(eReturnStatusSuccessFinishNoResult); 728 } 729 }; 730 731 // CommandObjectCommandsAddRegex 732 733 #define LLDB_OPTIONS_regex 734 #include "CommandOptions.inc" 735 736 #pragma mark CommandObjectCommandsAddRegex 737 738 class CommandObjectCommandsAddRegex : public CommandObjectParsed, 739 public IOHandlerDelegateMultiline { 740 public: 741 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 742 : CommandObjectParsed( 743 interpreter, "command regex", 744 "Define a custom command in terms of " 745 "existing commands by matching " 746 "regular expressions.", 747 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 748 IOHandlerDelegateMultiline("", 749 IOHandlerDelegate::Completion::LLDBCommand) { 750 SetHelpLong( 751 R"( 752 )" 753 "This command allows the user to create powerful regular expression commands \ 754 with substitutions. The regular expressions and substitutions are specified \ 755 using the regular expression substitution format of:" 756 R"( 757 758 s/<regex>/<subst>/ 759 760 )" 761 "<regex> is a regular expression that can use parenthesis to capture regular \ 762 expression input and substitute the captured matches in the output using %1 \ 763 for the first match, %2 for the second, and so on." 764 R"( 765 766 )" 767 "The regular expressions can all be specified on the command line if more than \ 768 one argument is provided. If just the command name is provided on the command \ 769 line, then the regular expressions and substitutions can be entered on separate \ 770 lines, followed by an empty line to terminate the command definition." 771 R"( 772 773 EXAMPLES 774 775 )" 776 "The following example will define a regular expression command named 'f' that \ 777 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 778 a number follows 'f':" 779 R"( 780 781 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 782 AddSimpleArgumentList(eArgTypeSEDStylePair, eArgRepeatOptional); 783 } 784 785 ~CommandObjectCommandsAddRegex() override = default; 786 787 protected: 788 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 789 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 790 if (output_sp && interactive) { 791 output_sp->PutCString("Enter one or more sed substitution commands in " 792 "the form: 's/<regex>/<subst>/'.\nTerminate the " 793 "substitution list with an empty line.\n"); 794 output_sp->Flush(); 795 } 796 } 797 798 void IOHandlerInputComplete(IOHandler &io_handler, 799 std::string &data) override { 800 io_handler.SetIsDone(true); 801 if (m_regex_cmd_up) { 802 StringList lines; 803 if (lines.SplitIntoLines(data)) { 804 bool check_only = false; 805 for (const std::string &line : lines) { 806 Status error = AppendRegexSubstitution(line, check_only); 807 if (error.Fail()) { 808 if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) { 809 StreamSP out_stream = GetDebugger().GetAsyncOutputStream(); 810 out_stream->Printf("error: %s\n", error.AsCString()); 811 } 812 } 813 } 814 } 815 if (m_regex_cmd_up->HasRegexEntries()) { 816 CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 817 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 818 } 819 } 820 } 821 822 void DoExecute(Args &command, CommandReturnObject &result) override { 823 const size_t argc = command.GetArgumentCount(); 824 if (argc == 0) { 825 result.AppendError("usage: 'command regex <command-name> " 826 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 827 return; 828 } 829 830 Status error; 831 auto name = command[0].ref(); 832 m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>( 833 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 0, 834 true); 835 836 if (argc == 1) { 837 Debugger &debugger = GetDebugger(); 838 bool color_prompt = debugger.GetUseColor(); 839 const bool multiple_lines = true; // Get multiple lines 840 IOHandlerSP io_handler_sp(new IOHandlerEditline( 841 debugger, IOHandler::Type::Other, 842 "lldb-regex", // Name of input reader for history 843 llvm::StringRef("> "), // Prompt 844 llvm::StringRef(), // Continuation prompt 845 multiple_lines, color_prompt, 846 0, // Don't show line numbers 847 *this)); 848 849 if (io_handler_sp) { 850 debugger.RunIOHandlerAsync(io_handler_sp); 851 result.SetStatus(eReturnStatusSuccessFinishNoResult); 852 } 853 } else { 854 for (auto &entry : command.entries().drop_front()) { 855 bool check_only = false; 856 error = AppendRegexSubstitution(entry.ref(), check_only); 857 if (error.Fail()) 858 break; 859 } 860 861 if (error.Success()) { 862 AddRegexCommandToInterpreter(); 863 } 864 } 865 if (error.Fail()) { 866 result.AppendError(error.AsCString()); 867 } 868 } 869 870 Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 871 bool check_only) { 872 Status error; 873 874 if (!m_regex_cmd_up) { 875 error.SetErrorStringWithFormat( 876 "invalid regular expression command object for: '%.*s'", 877 (int)regex_sed.size(), regex_sed.data()); 878 return error; 879 } 880 881 size_t regex_sed_size = regex_sed.size(); 882 883 if (regex_sed_size <= 1) { 884 error.SetErrorStringWithFormat( 885 "regular expression substitution string is too short: '%.*s'", 886 (int)regex_sed.size(), regex_sed.data()); 887 return error; 888 } 889 890 if (regex_sed[0] != 's') { 891 error.SetErrorStringWithFormat("regular expression substitution string " 892 "doesn't start with 's': '%.*s'", 893 (int)regex_sed.size(), regex_sed.data()); 894 return error; 895 } 896 const size_t first_separator_char_pos = 1; 897 // use the char that follows 's' as the regex separator character so we can 898 // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 899 const char separator_char = regex_sed[first_separator_char_pos]; 900 const size_t second_separator_char_pos = 901 regex_sed.find(separator_char, first_separator_char_pos + 1); 902 903 if (second_separator_char_pos == std::string::npos) { 904 error.SetErrorStringWithFormat( 905 "missing second '%c' separator char after '%.*s' in '%.*s'", 906 separator_char, 907 (int)(regex_sed.size() - first_separator_char_pos - 1), 908 regex_sed.data() + (first_separator_char_pos + 1), 909 (int)regex_sed.size(), regex_sed.data()); 910 return error; 911 } 912 913 const size_t third_separator_char_pos = 914 regex_sed.find(separator_char, second_separator_char_pos + 1); 915 916 if (third_separator_char_pos == std::string::npos) { 917 error.SetErrorStringWithFormat( 918 "missing third '%c' separator char after '%.*s' in '%.*s'", 919 separator_char, 920 (int)(regex_sed.size() - second_separator_char_pos - 1), 921 regex_sed.data() + (second_separator_char_pos + 1), 922 (int)regex_sed.size(), regex_sed.data()); 923 return error; 924 } 925 926 if (third_separator_char_pos != regex_sed_size - 1) { 927 // Make sure that everything that follows the last regex separator char 928 if (regex_sed.find_first_not_of("\t\n\v\f\r ", 929 third_separator_char_pos + 1) != 930 std::string::npos) { 931 error.SetErrorStringWithFormat( 932 "extra data found after the '%.*s' regular expression substitution " 933 "string: '%.*s'", 934 (int)third_separator_char_pos + 1, regex_sed.data(), 935 (int)(regex_sed.size() - third_separator_char_pos - 1), 936 regex_sed.data() + (third_separator_char_pos + 1)); 937 return error; 938 } 939 } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 940 error.SetErrorStringWithFormat( 941 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 942 separator_char, separator_char, separator_char, (int)regex_sed.size(), 943 regex_sed.data()); 944 return error; 945 } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 946 error.SetErrorStringWithFormat( 947 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 948 separator_char, separator_char, separator_char, (int)regex_sed.size(), 949 regex_sed.data()); 950 return error; 951 } 952 953 if (!check_only) { 954 std::string regex(std::string(regex_sed.substr( 955 first_separator_char_pos + 1, 956 second_separator_char_pos - first_separator_char_pos - 1))); 957 std::string subst(std::string(regex_sed.substr( 958 second_separator_char_pos + 1, 959 third_separator_char_pos - second_separator_char_pos - 1))); 960 m_regex_cmd_up->AddRegexCommand(regex, subst); 961 } 962 return error; 963 } 964 965 void AddRegexCommandToInterpreter() { 966 if (m_regex_cmd_up) { 967 if (m_regex_cmd_up->HasRegexEntries()) { 968 CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 969 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 970 } 971 } 972 } 973 974 private: 975 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up; 976 977 class CommandOptions : public Options { 978 public: 979 CommandOptions() = default; 980 981 ~CommandOptions() override = default; 982 983 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 984 ExecutionContext *execution_context) override { 985 Status error; 986 const int short_option = m_getopt_table[option_idx].val; 987 988 switch (short_option) { 989 case 'h': 990 m_help.assign(std::string(option_arg)); 991 break; 992 case 's': 993 m_syntax.assign(std::string(option_arg)); 994 break; 995 default: 996 llvm_unreachable("Unimplemented option"); 997 } 998 999 return error; 1000 } 1001 1002 void OptionParsingStarting(ExecutionContext *execution_context) override { 1003 m_help.clear(); 1004 m_syntax.clear(); 1005 } 1006 1007 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1008 return llvm::ArrayRef(g_regex_options); 1009 } 1010 1011 llvm::StringRef GetHelp() { return m_help; } 1012 1013 llvm::StringRef GetSyntax() { return m_syntax; } 1014 1015 protected: 1016 // Instance variables to hold the values for command options. 1017 1018 std::string m_help; 1019 std::string m_syntax; 1020 }; 1021 1022 Options *GetOptions() override { return &m_options; } 1023 1024 CommandOptions m_options; 1025 }; 1026 1027 class CommandObjectPythonFunction : public CommandObjectRaw { 1028 public: 1029 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1030 std::string funct, std::string help, 1031 ScriptedCommandSynchronicity synch, 1032 CompletionType completion_type) 1033 : CommandObjectRaw(interpreter, name), m_function_name(funct), 1034 m_synchro(synch), m_completion_type(completion_type) { 1035 if (!help.empty()) 1036 SetHelp(help); 1037 else { 1038 StreamString stream; 1039 stream.Printf("For more information run 'help %s'", name.c_str()); 1040 SetHelp(stream.GetString()); 1041 } 1042 } 1043 1044 ~CommandObjectPythonFunction() override = default; 1045 1046 bool IsRemovable() const override { return true; } 1047 1048 const std::string &GetFunctionName() { return m_function_name; } 1049 1050 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 1051 1052 llvm::StringRef GetHelpLong() override { 1053 if (m_fetched_help_long) 1054 return CommandObjectRaw::GetHelpLong(); 1055 1056 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1057 if (!scripter) 1058 return CommandObjectRaw::GetHelpLong(); 1059 1060 std::string docstring; 1061 m_fetched_help_long = 1062 scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1063 if (!docstring.empty()) 1064 SetHelpLong(docstring); 1065 return CommandObjectRaw::GetHelpLong(); 1066 } 1067 1068 void 1069 HandleArgumentCompletion(CompletionRequest &request, 1070 OptionElementVector &opt_element_vector) override { 1071 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 1072 GetCommandInterpreter(), m_completion_type, request, nullptr); 1073 } 1074 1075 bool WantsCompletion() override { return true; } 1076 1077 protected: 1078 void DoExecute(llvm::StringRef raw_command_line, 1079 CommandReturnObject &result) override { 1080 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1081 1082 m_interpreter.IncreaseCommandUsage(*this); 1083 1084 Status error; 1085 1086 result.SetStatus(eReturnStatusInvalid); 1087 1088 if (!scripter || !scripter->RunScriptBasedCommand( 1089 m_function_name.c_str(), raw_command_line, m_synchro, 1090 result, error, m_exe_ctx)) { 1091 result.AppendError(error.AsCString()); 1092 } else { 1093 // Don't change the status if the command already set it... 1094 if (result.GetStatus() == eReturnStatusInvalid) { 1095 if (result.GetOutputData().empty()) 1096 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1097 else 1098 result.SetStatus(eReturnStatusSuccessFinishResult); 1099 } 1100 } 1101 } 1102 1103 private: 1104 std::string m_function_name; 1105 ScriptedCommandSynchronicity m_synchro; 1106 bool m_fetched_help_long = false; 1107 CompletionType m_completion_type = eNoCompletion; 1108 }; 1109 1110 /// This class implements a "raw" scripted command. lldb does no parsing of the 1111 /// command line, instead passing the line unaltered (except for backtick 1112 /// substitution). 1113 class CommandObjectScriptingObjectRaw : public CommandObjectRaw { 1114 public: 1115 CommandObjectScriptingObjectRaw(CommandInterpreter &interpreter, 1116 std::string name, 1117 StructuredData::GenericSP cmd_obj_sp, 1118 ScriptedCommandSynchronicity synch, 1119 CompletionType completion_type) 1120 : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp), 1121 m_synchro(synch), m_fetched_help_short(false), 1122 m_fetched_help_long(false), m_completion_type(completion_type) { 1123 StreamString stream; 1124 stream.Printf("For more information run 'help %s'", name.c_str()); 1125 SetHelp(stream.GetString()); 1126 if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter()) 1127 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 1128 } 1129 1130 ~CommandObjectScriptingObjectRaw() override = default; 1131 1132 void 1133 HandleArgumentCompletion(CompletionRequest &request, 1134 OptionElementVector &opt_element_vector) override { 1135 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 1136 GetCommandInterpreter(), m_completion_type, request, nullptr); 1137 } 1138 1139 bool WantsCompletion() override { return true; } 1140 1141 bool IsRemovable() const override { return true; } 1142 1143 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 1144 1145 std::optional<std::string> GetRepeatCommand(Args &args, 1146 uint32_t index) override { 1147 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1148 if (!scripter) 1149 return std::nullopt; 1150 1151 return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args); 1152 } 1153 1154 llvm::StringRef GetHelp() override { 1155 if (m_fetched_help_short) 1156 return CommandObjectRaw::GetHelp(); 1157 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1158 if (!scripter) 1159 return CommandObjectRaw::GetHelp(); 1160 std::string docstring; 1161 m_fetched_help_short = 1162 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 1163 if (!docstring.empty()) 1164 SetHelp(docstring); 1165 1166 return CommandObjectRaw::GetHelp(); 1167 } 1168 1169 llvm::StringRef GetHelpLong() override { 1170 if (m_fetched_help_long) 1171 return CommandObjectRaw::GetHelpLong(); 1172 1173 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1174 if (!scripter) 1175 return CommandObjectRaw::GetHelpLong(); 1176 1177 std::string docstring; 1178 m_fetched_help_long = 1179 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 1180 if (!docstring.empty()) 1181 SetHelpLong(docstring); 1182 return CommandObjectRaw::GetHelpLong(); 1183 } 1184 1185 protected: 1186 void DoExecute(llvm::StringRef raw_command_line, 1187 CommandReturnObject &result) override { 1188 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1189 1190 Status error; 1191 1192 result.SetStatus(eReturnStatusInvalid); 1193 1194 if (!scripter || 1195 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1196 m_synchro, result, error, m_exe_ctx)) { 1197 result.AppendError(error.AsCString()); 1198 } else { 1199 // Don't change the status if the command already set it... 1200 if (result.GetStatus() == eReturnStatusInvalid) { 1201 if (result.GetOutputData().empty()) 1202 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1203 else 1204 result.SetStatus(eReturnStatusSuccessFinishResult); 1205 } 1206 } 1207 } 1208 1209 private: 1210 StructuredData::GenericSP m_cmd_obj_sp; 1211 ScriptedCommandSynchronicity m_synchro; 1212 bool m_fetched_help_short : 1; 1213 bool m_fetched_help_long : 1; 1214 CompletionType m_completion_type = eNoCompletion; 1215 }; 1216 1217 1218 /// This command implements a lldb parsed scripted command. The command 1219 /// provides a definition of the options and arguments, and a option value 1220 /// setting callback, and then the command's execution function gets passed 1221 /// just the parsed arguments. 1222 /// Note, implementing a command in Python using these base interfaces is a bit 1223 /// of a pain, but it is much easier to export this low level interface, and 1224 /// then make it nicer on the Python side, than to try to do that in a 1225 /// script language neutral way. 1226 /// So I've also added a base class in Python that provides a table-driven 1227 /// way of defining the options and arguments, which automatically fills the 1228 /// option values, making them available as properties in Python. 1229 /// 1230 class CommandObjectScriptingObjectParsed : public CommandObjectParsed { 1231 private: 1232 class CommandOptions : public Options { 1233 public: 1234 CommandOptions(CommandInterpreter &interpreter, 1235 StructuredData::GenericSP cmd_obj_sp) : m_interpreter(interpreter), 1236 m_cmd_obj_sp(cmd_obj_sp) {} 1237 1238 ~CommandOptions() override = default; 1239 1240 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1241 ExecutionContext *execution_context) override { 1242 Status error; 1243 ScriptInterpreter *scripter = 1244 m_interpreter.GetDebugger().GetScriptInterpreter(); 1245 if (!scripter) { 1246 error.SetErrorString("No script interpreter for SetOptionValue."); 1247 return error; 1248 } 1249 if (!m_cmd_obj_sp) { 1250 error.SetErrorString("SetOptionValue called with empty cmd_obj."); 1251 return error; 1252 } 1253 if (!m_options_definition_up) { 1254 error.SetErrorString("SetOptionValue called before options definitions " 1255 "were created."); 1256 return error; 1257 } 1258 // Pass the long option, since you aren't actually required to have a 1259 // short_option, and for those options the index or short option character 1260 // aren't meaningful on the python side. 1261 const char * long_option = 1262 m_options_definition_up.get()[option_idx].long_option; 1263 bool success = scripter->SetOptionValueForCommandObject(m_cmd_obj_sp, 1264 execution_context, long_option, option_arg); 1265 if (!success) 1266 error.SetErrorStringWithFormatv("Error setting option: {0} to {1}", 1267 long_option, option_arg); 1268 return error; 1269 } 1270 1271 void OptionParsingStarting(ExecutionContext *execution_context) override { 1272 ScriptInterpreter *scripter = 1273 m_interpreter.GetDebugger().GetScriptInterpreter(); 1274 if (!scripter || !m_cmd_obj_sp) 1275 return; 1276 1277 scripter->OptionParsingStartedForCommandObject(m_cmd_obj_sp); 1278 } 1279 1280 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1281 if (!m_options_definition_up) 1282 return {}; 1283 return llvm::ArrayRef(m_options_definition_up.get(), m_num_options); 1284 } 1285 1286 static Status ParseUsageMaskFromArray(StructuredData::ObjectSP obj_sp, 1287 size_t counter, uint32_t &usage_mask) { 1288 // If the usage entry is not provided, we use LLDB_OPT_SET_ALL. 1289 // If the usage mask is a UINT, the option belongs to that group. 1290 // If the usage mask is a vector of UINT's, the option belongs to all the 1291 // groups listed. 1292 // If a subelement of the vector is a vector of two ints, then the option 1293 // belongs to the inclusive range from the first to the second element. 1294 Status error; 1295 if (!obj_sp) { 1296 usage_mask = LLDB_OPT_SET_ALL; 1297 return error; 1298 } 1299 1300 usage_mask = 0; 1301 1302 StructuredData::UnsignedInteger *uint_val = 1303 obj_sp->GetAsUnsignedInteger(); 1304 if (uint_val) { 1305 // If this is an integer, then this specifies a single group: 1306 uint32_t value = uint_val->GetValue(); 1307 if (value == 0) { 1308 error.SetErrorStringWithFormatv( 1309 "0 is not a valid group for option {0}", counter); 1310 return error; 1311 } 1312 usage_mask = (1 << (value - 1)); 1313 return error; 1314 } 1315 // Otherwise it has to be an array: 1316 StructuredData::Array *array_val = obj_sp->GetAsArray(); 1317 if (!array_val) { 1318 error.SetErrorStringWithFormatv( 1319 "required field is not a array for option {0}", counter); 1320 return error; 1321 } 1322 // This is the array ForEach for accumulating a group usage mask from 1323 // an array of string descriptions of groups. 1324 auto groups_accumulator 1325 = [counter, &usage_mask, &error] 1326 (StructuredData::Object *obj) -> bool { 1327 StructuredData::UnsignedInteger *int_val = obj->GetAsUnsignedInteger(); 1328 if (int_val) { 1329 uint32_t value = int_val->GetValue(); 1330 if (value == 0) { 1331 error.SetErrorStringWithFormatv( 1332 "0 is not a valid group for element {0}", counter); 1333 return false; 1334 } 1335 usage_mask |= (1 << (value - 1)); 1336 return true; 1337 } 1338 StructuredData::Array *arr_val = obj->GetAsArray(); 1339 if (!arr_val) { 1340 error.SetErrorStringWithFormatv( 1341 "Group element not an int or array of integers for element {0}", 1342 counter); 1343 return false; 1344 } 1345 size_t num_range_elem = arr_val->GetSize(); 1346 if (num_range_elem != 2) { 1347 error.SetErrorStringWithFormatv( 1348 "Subranges of a group not a start and a stop for element {0}", 1349 counter); 1350 return false; 1351 } 1352 int_val = arr_val->GetItemAtIndex(0)->GetAsUnsignedInteger(); 1353 if (!int_val) { 1354 error.SetErrorStringWithFormatv("Start element of a subrange of a " 1355 "group not unsigned int for element {0}", counter); 1356 return false; 1357 } 1358 uint32_t start = int_val->GetValue(); 1359 int_val = arr_val->GetItemAtIndex(1)->GetAsUnsignedInteger(); 1360 if (!int_val) { 1361 error.SetErrorStringWithFormatv("End element of a subrange of a group" 1362 " not unsigned int for element {0}", counter); 1363 return false; 1364 } 1365 uint32_t end = int_val->GetValue(); 1366 if (start == 0 || end == 0 || start > end) { 1367 error.SetErrorStringWithFormatv("Invalid subrange of a group: {0} - " 1368 "{1} for element {2}", start, end, counter); 1369 return false; 1370 } 1371 for (uint32_t i = start; i <= end; i++) { 1372 usage_mask |= (1 << (i - 1)); 1373 } 1374 return true; 1375 }; 1376 array_val->ForEach(groups_accumulator); 1377 return error; 1378 } 1379 1380 1381 Status SetOptionsFromArray(StructuredData::Dictionary &options) { 1382 Status error; 1383 m_num_options = options.GetSize(); 1384 m_options_definition_up.reset(new OptionDefinition[m_num_options]); 1385 // We need to hand out pointers to contents of these vectors; we reserve 1386 // as much as we'll need up front so they don't get freed on resize... 1387 m_usage_container.resize(m_num_options); 1388 m_enum_storage.resize(m_num_options); 1389 m_enum_vector.resize(m_num_options); 1390 1391 size_t counter = 0; 1392 size_t short_opt_counter = 0; 1393 // This is the Array::ForEach function for adding option elements: 1394 auto add_element = [this, &error, &counter, &short_opt_counter] 1395 (llvm::StringRef long_option, StructuredData::Object *object) -> bool { 1396 StructuredData::Dictionary *opt_dict = object->GetAsDictionary(); 1397 if (!opt_dict) { 1398 error.SetErrorString("Value in options dictionary is not a dictionary"); 1399 return false; 1400 } 1401 OptionDefinition &option_def = m_options_definition_up.get()[counter]; 1402 1403 // We aren't exposing the validator yet, set it to null 1404 option_def.validator = nullptr; 1405 // We don't require usage masks, so set it to one group by default: 1406 option_def.usage_mask = 1; 1407 1408 // Now set the fields of the OptionDefinition Array from the dictionary: 1409 // 1410 // Note that I don't check for unknown fields in the option dictionaries 1411 // so a scriptor can add extra elements that are helpful when they go to 1412 // do "set_option_value" 1413 1414 // Usage Mask: 1415 StructuredData::ObjectSP obj_sp = opt_dict->GetValueForKey("groups"); 1416 if (obj_sp) { 1417 error = ParseUsageMaskFromArray(obj_sp, counter, 1418 option_def.usage_mask); 1419 if (error.Fail()) 1420 return false; 1421 } 1422 1423 // Required: 1424 option_def.required = false; 1425 obj_sp = opt_dict->GetValueForKey("required"); 1426 if (obj_sp) { 1427 StructuredData::Boolean *boolean_val = obj_sp->GetAsBoolean(); 1428 if (!boolean_val) { 1429 error.SetErrorStringWithFormatv("'required' field is not a boolean " 1430 "for option {0}", counter); 1431 return false; 1432 } 1433 option_def.required = boolean_val->GetValue(); 1434 } 1435 1436 // Short Option: 1437 int short_option; 1438 obj_sp = opt_dict->GetValueForKey("short_option"); 1439 if (obj_sp) { 1440 // The value is a string, so pull the 1441 llvm::StringRef short_str = obj_sp->GetStringValue(); 1442 if (short_str.empty()) { 1443 error.SetErrorStringWithFormatv("short_option field empty for " 1444 "option {0}", counter); 1445 return false; 1446 } else if (short_str.size() != 1) { 1447 error.SetErrorStringWithFormatv("short_option field has extra " 1448 "characters for option {0}", counter); 1449 return false; 1450 } 1451 short_option = (int) short_str[0]; 1452 } else { 1453 // If the short option is not provided, then we need a unique value 1454 // less than the lowest printable ASCII character. 1455 short_option = short_opt_counter++; 1456 } 1457 option_def.short_option = short_option; 1458 1459 // Long Option is the key from the outer dict: 1460 if (long_option.empty()) { 1461 error.SetErrorStringWithFormatv("empty long_option for option {0}", 1462 counter); 1463 return false; 1464 } 1465 auto inserted = g_string_storer.insert(long_option.str()); 1466 option_def.long_option = ((*(inserted.first)).data()); 1467 1468 // Value Type: 1469 obj_sp = opt_dict->GetValueForKey("value_type"); 1470 if (obj_sp) { 1471 StructuredData::UnsignedInteger *uint_val 1472 = obj_sp->GetAsUnsignedInteger(); 1473 if (!uint_val) { 1474 error.SetErrorStringWithFormatv("Value type must be an unsigned " 1475 "integer"); 1476 return false; 1477 } 1478 uint64_t val_type = uint_val->GetValue(); 1479 if (val_type >= eArgTypeLastArg) { 1480 error.SetErrorStringWithFormatv("Value type {0} beyond the " 1481 "CommandArgumentType bounds", val_type); 1482 return false; 1483 } 1484 option_def.argument_type = (CommandArgumentType) val_type; 1485 option_def.option_has_arg = true; 1486 } else { 1487 option_def.argument_type = eArgTypeNone; 1488 option_def.option_has_arg = false; 1489 } 1490 1491 // Completion Type: 1492 obj_sp = opt_dict->GetValueForKey("completion_type"); 1493 if (obj_sp) { 1494 StructuredData::UnsignedInteger *uint_val = obj_sp->GetAsUnsignedInteger(); 1495 if (!uint_val) { 1496 error.SetErrorStringWithFormatv("Completion type must be an " 1497 "unsigned integer for option {0}", counter); 1498 return false; 1499 } 1500 uint64_t completion_type = uint_val->GetValue(); 1501 if (completion_type > eCustomCompletion) { 1502 error.SetErrorStringWithFormatv("Completion type for option {0} " 1503 "beyond the CompletionType bounds", completion_type); 1504 return false; 1505 } 1506 option_def.completion_type = (CommandArgumentType) completion_type; 1507 } else 1508 option_def.completion_type = eNoCompletion; 1509 1510 // Usage Text: 1511 std::string usage_text; 1512 obj_sp = opt_dict->GetValueForKey("help"); 1513 if (!obj_sp) { 1514 error.SetErrorStringWithFormatv("required usage missing from option " 1515 "{0}", counter); 1516 return false; 1517 } 1518 llvm::StringRef usage_stref; 1519 usage_stref = obj_sp->GetStringValue(); 1520 if (usage_stref.empty()) { 1521 error.SetErrorStringWithFormatv("empty usage text for option {0}", 1522 counter); 1523 return false; 1524 } 1525 m_usage_container[counter] = usage_stref.str().c_str(); 1526 option_def.usage_text = m_usage_container[counter].data(); 1527 1528 // Enum Values: 1529 1530 obj_sp = opt_dict->GetValueForKey("enum_values"); 1531 if (obj_sp) { 1532 StructuredData::Array *array = obj_sp->GetAsArray(); 1533 if (!array) { 1534 error.SetErrorStringWithFormatv("enum values must be an array for " 1535 "option {0}", counter); 1536 return false; 1537 } 1538 size_t num_elem = array->GetSize(); 1539 size_t enum_ctr = 0; 1540 m_enum_storage[counter] = std::vector<EnumValueStorage>(num_elem); 1541 std::vector<EnumValueStorage> &curr_elem = m_enum_storage[counter]; 1542 1543 // This is the Array::ForEach function for adding enum elements: 1544 // Since there are only two fields to specify the enum, use a simple 1545 // two element array with value first, usage second. 1546 // counter is only used for reporting so I pass it by value here. 1547 auto add_enum = [&enum_ctr, &curr_elem, counter, &error] 1548 (StructuredData::Object *object) -> bool { 1549 StructuredData::Array *enum_arr = object->GetAsArray(); 1550 if (!enum_arr) { 1551 error.SetErrorStringWithFormatv("Enum values for option {0} not " 1552 "an array", counter); 1553 return false; 1554 } 1555 size_t num_enum_elements = enum_arr->GetSize(); 1556 if (num_enum_elements != 2) { 1557 error.SetErrorStringWithFormatv("Wrong number of elements: {0} " 1558 "for enum {1} in option {2}", 1559 num_enum_elements, enum_ctr, counter); 1560 return false; 1561 } 1562 // Enum Value: 1563 StructuredData::ObjectSP obj_sp = enum_arr->GetItemAtIndex(0); 1564 llvm::StringRef val_stref = obj_sp->GetStringValue(); 1565 std::string value_cstr_str = val_stref.str().c_str(); 1566 1567 // Enum Usage: 1568 obj_sp = enum_arr->GetItemAtIndex(1); 1569 if (!obj_sp) { 1570 error.SetErrorStringWithFormatv("No usage for enum {0} in option " 1571 "{1}", enum_ctr, counter); 1572 return false; 1573 } 1574 llvm::StringRef usage_stref = obj_sp->GetStringValue(); 1575 std::string usage_cstr_str = usage_stref.str().c_str(); 1576 curr_elem[enum_ctr] = EnumValueStorage(value_cstr_str, 1577 usage_cstr_str, enum_ctr); 1578 1579 enum_ctr++; 1580 return true; 1581 }; // end of add_enum 1582 1583 array->ForEach(add_enum); 1584 if (!error.Success()) 1585 return false; 1586 // We have to have a vector of elements to set in the options, make 1587 // that here: 1588 for (auto &elem : curr_elem) 1589 m_enum_vector[counter].emplace_back(elem.element); 1590 1591 option_def.enum_values = llvm::ArrayRef(m_enum_vector[counter]); 1592 } 1593 counter++; 1594 return true; 1595 }; // end of add_element 1596 1597 options.ForEach(add_element); 1598 return error; 1599 } 1600 1601 size_t GetNumOptions() { return m_num_options; } 1602 1603 private: 1604 struct EnumValueStorage { 1605 EnumValueStorage() { 1606 element.string_value = "value not set"; 1607 element.usage = "usage not set"; 1608 element.value = 0; 1609 } 1610 1611 EnumValueStorage(std::string in_str_val, std::string in_usage, 1612 size_t in_value) : value(std::move(in_str_val)), usage(std::move(in_usage)) { 1613 SetElement(in_value); 1614 } 1615 1616 EnumValueStorage(const EnumValueStorage &in) : value(in.value), 1617 usage(in.usage) { 1618 SetElement(in.element.value); 1619 } 1620 1621 EnumValueStorage &operator=(const EnumValueStorage &in) { 1622 value = in.value; 1623 usage = in.usage; 1624 SetElement(in.element.value); 1625 return *this; 1626 } 1627 1628 void SetElement(size_t in_value) { 1629 element.value = in_value; 1630 element.string_value = value.data(); 1631 element.usage = usage.data(); 1632 } 1633 1634 std::string value; 1635 std::string usage; 1636 OptionEnumValueElement element; 1637 }; 1638 // We have to provide char * values for the long option, usage and enum 1639 // values, that's what the option definitions hold. 1640 // The long option strings are quite likely to be reused in other added 1641 // commands, so those are stored in a global set: g_string_storer. 1642 // But the usages are much less likely to be reused, so those are stored in 1643 // a vector in the command instance. It gets resized to the correct size 1644 // and then filled with null-terminated strings in the std::string, so the 1645 // are valid C-strings that won't move around. 1646 // The enum values and descriptions are treated similarly - these aren't 1647 // all that common so it's not worth the effort to dedup them. 1648 size_t m_num_options = 0; 1649 std::unique_ptr<OptionDefinition> m_options_definition_up; 1650 std::vector<std::vector<EnumValueStorage>> m_enum_storage; 1651 std::vector<std::vector<OptionEnumValueElement>> m_enum_vector; 1652 std::vector<std::string> m_usage_container; 1653 CommandInterpreter &m_interpreter; 1654 StructuredData::GenericSP m_cmd_obj_sp; 1655 static std::unordered_set<std::string> g_string_storer; 1656 }; 1657 1658 public: 1659 static CommandObjectSP Create(CommandInterpreter &interpreter, 1660 std::string name, 1661 StructuredData::GenericSP cmd_obj_sp, 1662 ScriptedCommandSynchronicity synch, 1663 CommandReturnObject &result) { 1664 CommandObjectSP new_cmd_sp(new CommandObjectScriptingObjectParsed( 1665 interpreter, name, cmd_obj_sp, synch)); 1666 1667 CommandObjectScriptingObjectParsed *parsed_cmd 1668 = static_cast<CommandObjectScriptingObjectParsed *>(new_cmd_sp.get()); 1669 // Now check all the failure modes, and report if found. 1670 Status opt_error = parsed_cmd->GetOptionsError(); 1671 Status arg_error = parsed_cmd->GetArgsError(); 1672 1673 if (opt_error.Fail()) 1674 result.AppendErrorWithFormat("failed to parse option definitions: %s", 1675 opt_error.AsCString()); 1676 if (arg_error.Fail()) 1677 result.AppendErrorWithFormat("%sfailed to parse argument definitions: %s", 1678 opt_error.Fail() ? ", also " : "", 1679 arg_error.AsCString()); 1680 1681 if (!result.Succeeded()) 1682 return {}; 1683 1684 return new_cmd_sp; 1685 } 1686 1687 CommandObjectScriptingObjectParsed(CommandInterpreter &interpreter, 1688 std::string name, 1689 StructuredData::GenericSP cmd_obj_sp, 1690 ScriptedCommandSynchronicity synch) 1691 : CommandObjectParsed(interpreter, name.c_str()), 1692 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), 1693 m_options(interpreter, cmd_obj_sp), m_fetched_help_short(false), 1694 m_fetched_help_long(false) { 1695 StreamString stream; 1696 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1697 if (!scripter) { 1698 m_options_error.SetErrorString("No script interpreter"); 1699 return; 1700 } 1701 1702 // Set the flags: 1703 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 1704 1705 // Now set up the options definitions from the options: 1706 StructuredData::ObjectSP options_object_sp 1707 = scripter->GetOptionsForCommandObject(cmd_obj_sp); 1708 // It's okay not to have an options dict. 1709 if (options_object_sp) { 1710 // The options come as a dictionary of dictionaries. The key of the 1711 // outer dict is the long option name (since that's required). The 1712 // value holds all the other option specification bits. 1713 StructuredData::Dictionary *options_dict 1714 = options_object_sp->GetAsDictionary(); 1715 // but if it exists, it has to be an array. 1716 if (options_dict) { 1717 m_options_error = m_options.SetOptionsFromArray(*(options_dict)); 1718 // If we got an error don't bother with the arguments... 1719 if (m_options_error.Fail()) 1720 return; 1721 } else { 1722 m_options_error.SetErrorString("Options array not an array"); 1723 return; 1724 } 1725 } 1726 // Then fetch the args. Since the arguments can have usage masks you need 1727 // an array of arrays. 1728 StructuredData::ObjectSP args_object_sp 1729 = scripter->GetArgumentsForCommandObject(cmd_obj_sp); 1730 if (args_object_sp) { 1731 StructuredData::Array *args_array = args_object_sp->GetAsArray(); 1732 if (!args_array) { 1733 m_args_error.SetErrorString("Argument specification is not an array"); 1734 return; 1735 } 1736 size_t counter = 0; 1737 1738 // This is the Array::ForEach function that handles the 1739 // CommandArgumentEntry arrays one by one: 1740 auto arg_array_adder = [this, &counter] (StructuredData::Object *object) 1741 -> bool { 1742 // This is the Array::ForEach function to add argument entries: 1743 CommandArgumentEntry this_entry; 1744 size_t elem_counter = 0; 1745 auto args_adder = [this, counter, &elem_counter, &this_entry] 1746 (StructuredData::Object *object) -> bool { 1747 // The arguments definition has three fields, the argument type, the 1748 // repeat and the usage mask. 1749 CommandArgumentType arg_type = eArgTypeNone; 1750 ArgumentRepetitionType arg_repetition = eArgRepeatOptional; 1751 uint32_t arg_opt_set_association; 1752 1753 auto report_error = [this, elem_counter, counter] 1754 (const char *err_txt) -> bool { 1755 m_args_error.SetErrorStringWithFormatv("Element {0} of arguments " 1756 "list element {1}: %s.", elem_counter, counter, err_txt); 1757 return false; 1758 }; 1759 1760 StructuredData::Dictionary *arg_dict = object->GetAsDictionary(); 1761 if (!arg_dict) { 1762 report_error("is not a dictionary."); 1763 return false; 1764 } 1765 // Argument Type: 1766 StructuredData::ObjectSP obj_sp 1767 = arg_dict->GetValueForKey("arg_type"); 1768 if (obj_sp) { 1769 StructuredData::UnsignedInteger *uint_val 1770 = obj_sp->GetAsUnsignedInteger(); 1771 if (!uint_val) { 1772 report_error("value type must be an unsigned integer"); 1773 return false; 1774 } 1775 uint64_t arg_type_int = uint_val->GetValue(); 1776 if (arg_type_int >= eArgTypeLastArg) { 1777 report_error("value type beyond ArgumentRepetitionType bounds"); 1778 return false; 1779 } 1780 arg_type = (CommandArgumentType) arg_type_int; 1781 } 1782 // Repeat Value: 1783 obj_sp = arg_dict->GetValueForKey("repeat"); 1784 std::optional<ArgumentRepetitionType> repeat; 1785 if (obj_sp) { 1786 llvm::StringRef repeat_str = obj_sp->GetStringValue(); 1787 if (repeat_str.empty()) { 1788 report_error("repeat value is empty"); 1789 return false; 1790 } 1791 repeat = ArgRepetitionFromString(repeat_str); 1792 if (!repeat) { 1793 report_error("invalid repeat value"); 1794 return false; 1795 } 1796 arg_repetition = *repeat; 1797 } 1798 1799 // Usage Mask: 1800 obj_sp = arg_dict->GetValueForKey("groups"); 1801 m_args_error = CommandOptions::ParseUsageMaskFromArray(obj_sp, 1802 counter, arg_opt_set_association); 1803 this_entry.emplace_back(arg_type, arg_repetition, 1804 arg_opt_set_association); 1805 elem_counter++; 1806 return true; 1807 }; 1808 StructuredData::Array *args_array = object->GetAsArray(); 1809 if (!args_array) { 1810 m_args_error.SetErrorStringWithFormatv("Argument definition element " 1811 "{0} is not an array", counter); 1812 } 1813 1814 args_array->ForEach(args_adder); 1815 if (m_args_error.Fail()) 1816 return false; 1817 if (this_entry.empty()) { 1818 m_args_error.SetErrorStringWithFormatv("Argument definition element " 1819 "{0} is empty", counter); 1820 return false; 1821 } 1822 m_arguments.push_back(this_entry); 1823 counter++; 1824 return true; 1825 }; // end of arg_array_adder 1826 // Here we actually parse the args definition: 1827 args_array->ForEach(arg_array_adder); 1828 } 1829 } 1830 1831 ~CommandObjectScriptingObjectParsed() override = default; 1832 1833 Status GetOptionsError() { return m_options_error; } 1834 Status GetArgsError() { return m_args_error; } 1835 bool WantsCompletion() override { return true; } 1836 1837 bool IsRemovable() const override { return true; } 1838 1839 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 1840 1841 std::optional<std::string> GetRepeatCommand(Args &args, 1842 uint32_t index) override { 1843 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1844 if (!scripter) 1845 return std::nullopt; 1846 1847 return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args); 1848 } 1849 1850 llvm::StringRef GetHelp() override { 1851 if (m_fetched_help_short) 1852 return CommandObjectParsed::GetHelp(); 1853 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1854 if (!scripter) 1855 return CommandObjectParsed::GetHelp(); 1856 std::string docstring; 1857 m_fetched_help_short = 1858 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 1859 if (!docstring.empty()) 1860 SetHelp(docstring); 1861 1862 return CommandObjectParsed::GetHelp(); 1863 } 1864 1865 llvm::StringRef GetHelpLong() override { 1866 if (m_fetched_help_long) 1867 return CommandObjectParsed::GetHelpLong(); 1868 1869 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1870 if (!scripter) 1871 return CommandObjectParsed::GetHelpLong(); 1872 1873 std::string docstring; 1874 m_fetched_help_long = 1875 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 1876 if (!docstring.empty()) 1877 SetHelpLong(docstring); 1878 return CommandObjectParsed::GetHelpLong(); 1879 } 1880 1881 Options *GetOptions() override { 1882 // CommandObjectParsed requires that a command with no options return 1883 // nullptr. 1884 if (m_options.GetNumOptions() == 0) 1885 return nullptr; 1886 return &m_options; 1887 } 1888 1889 protected: 1890 void DoExecute(Args &args, 1891 CommandReturnObject &result) override { 1892 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1893 1894 Status error; 1895 1896 result.SetStatus(eReturnStatusInvalid); 1897 1898 if (!scripter || 1899 !scripter->RunScriptBasedParsedCommand(m_cmd_obj_sp, args, 1900 m_synchro, result, error, m_exe_ctx)) { 1901 result.AppendError(error.AsCString()); 1902 } else { 1903 // Don't change the status if the command already set it... 1904 if (result.GetStatus() == eReturnStatusInvalid) { 1905 if (result.GetOutputData().empty()) 1906 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1907 else 1908 result.SetStatus(eReturnStatusSuccessFinishResult); 1909 } 1910 } 1911 } 1912 1913 private: 1914 StructuredData::GenericSP m_cmd_obj_sp; 1915 ScriptedCommandSynchronicity m_synchro; 1916 CommandOptions m_options; 1917 Status m_options_error; 1918 Status m_args_error; 1919 bool m_fetched_help_short : 1; 1920 bool m_fetched_help_long : 1; 1921 }; 1922 1923 std::unordered_set<std::string> 1924 CommandObjectScriptingObjectParsed::CommandOptions::g_string_storer; 1925 1926 // CommandObjectCommandsScriptImport 1927 #define LLDB_OPTIONS_script_import 1928 #include "CommandOptions.inc" 1929 1930 class CommandObjectCommandsScriptImport : public CommandObjectParsed { 1931 public: 1932 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1933 : CommandObjectParsed(interpreter, "command script import", 1934 "Import a scripting module in LLDB.", nullptr) { 1935 AddSimpleArgumentList(eArgTypeFilename, eArgRepeatPlus); 1936 } 1937 1938 ~CommandObjectCommandsScriptImport() override = default; 1939 1940 Options *GetOptions() override { return &m_options; } 1941 1942 protected: 1943 class CommandOptions : public Options { 1944 public: 1945 CommandOptions() = default; 1946 1947 ~CommandOptions() override = default; 1948 1949 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1950 ExecutionContext *execution_context) override { 1951 Status error; 1952 const int short_option = m_getopt_table[option_idx].val; 1953 1954 switch (short_option) { 1955 case 'r': 1956 // NO-OP 1957 break; 1958 case 'c': 1959 relative_to_command_file = true; 1960 break; 1961 case 's': 1962 silent = true; 1963 break; 1964 default: 1965 llvm_unreachable("Unimplemented option"); 1966 } 1967 1968 return error; 1969 } 1970 1971 void OptionParsingStarting(ExecutionContext *execution_context) override { 1972 relative_to_command_file = false; 1973 } 1974 1975 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1976 return llvm::ArrayRef(g_script_import_options); 1977 } 1978 bool relative_to_command_file = false; 1979 bool silent = false; 1980 }; 1981 1982 void DoExecute(Args &command, CommandReturnObject &result) override { 1983 if (command.empty()) { 1984 result.AppendError("command script import needs one or more arguments"); 1985 return; 1986 } 1987 1988 FileSpec source_dir = {}; 1989 if (m_options.relative_to_command_file) { 1990 source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir(); 1991 if (!source_dir) { 1992 result.AppendError("command script import -c can only be specified " 1993 "from a command file"); 1994 return; 1995 } 1996 } 1997 1998 for (auto &entry : command.entries()) { 1999 Status error; 2000 2001 LoadScriptOptions options; 2002 options.SetInitSession(true); 2003 options.SetSilent(m_options.silent); 2004 2005 // FIXME: this is necessary because CommandObject::CheckRequirements() 2006 // assumes that commands won't ever be recursively invoked, but it's 2007 // actually possible to craft a Python script that does other "command 2008 // script imports" in __lldb_init_module the real fix is to have 2009 // recursive commands possible with a CommandInvocation object separate 2010 // from the CommandObject itself, so that recursive command invocations 2011 // won't stomp on each other (wrt to execution contents, options, and 2012 // more) 2013 m_exe_ctx.Clear(); 2014 if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule( 2015 entry.c_str(), options, error, /*module_sp=*/nullptr, 2016 source_dir)) { 2017 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2018 } else { 2019 result.AppendErrorWithFormat("module importing failed: %s", 2020 error.AsCString()); 2021 } 2022 } 2023 } 2024 2025 CommandOptions m_options; 2026 }; 2027 2028 #define LLDB_OPTIONS_script_add 2029 #include "CommandOptions.inc" 2030 2031 class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 2032 public IOHandlerDelegateMultiline { 2033 public: 2034 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 2035 : CommandObjectParsed(interpreter, "command script add", 2036 "Add a scripted function as an LLDB command.", 2037 "Add a scripted function as an lldb command. " 2038 "If you provide a single argument, the command " 2039 "will be added at the root level of the command " 2040 "hierarchy. If there are more arguments they " 2041 "must be a path to a user-added container " 2042 "command, and the last element will be the new " 2043 "command name."), 2044 IOHandlerDelegateMultiline("DONE") { 2045 AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus); 2046 } 2047 2048 ~CommandObjectCommandsScriptAdd() override = default; 2049 2050 Options *GetOptions() override { return &m_options; } 2051 2052 void 2053 HandleArgumentCompletion(CompletionRequest &request, 2054 OptionElementVector &opt_element_vector) override { 2055 CommandCompletions::CompleteModifiableCmdPathArgs(m_interpreter, request, 2056 opt_element_vector); 2057 } 2058 2059 protected: 2060 class CommandOptions : public Options { 2061 public: 2062 CommandOptions() = default; 2063 2064 ~CommandOptions() override = default; 2065 2066 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2067 ExecutionContext *execution_context) override { 2068 Status error; 2069 const int short_option = m_getopt_table[option_idx].val; 2070 2071 switch (short_option) { 2072 case 'f': 2073 if (!option_arg.empty()) 2074 m_funct_name = std::string(option_arg); 2075 break; 2076 case 'c': 2077 if (!option_arg.empty()) 2078 m_class_name = std::string(option_arg); 2079 break; 2080 case 'h': 2081 if (!option_arg.empty()) 2082 m_short_help = std::string(option_arg); 2083 break; 2084 case 'o': 2085 m_overwrite_lazy = eLazyBoolYes; 2086 break; 2087 case 'p': 2088 m_parsed_command = true; 2089 break; 2090 case 's': 2091 m_synchronicity = 2092 (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum( 2093 option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 2094 if (!error.Success()) 2095 error.SetErrorStringWithFormat( 2096 "unrecognized value for synchronicity '%s'", 2097 option_arg.str().c_str()); 2098 break; 2099 case 'C': { 2100 Status error; 2101 OptionDefinition definition = GetDefinitions()[option_idx]; 2102 lldb::CompletionType completion_type = 2103 static_cast<lldb::CompletionType>(OptionArgParser::ToOptionEnum( 2104 option_arg, definition.enum_values, eNoCompletion, error)); 2105 if (!error.Success()) 2106 error.SetErrorStringWithFormat( 2107 "unrecognized value for command completion type '%s'", 2108 option_arg.str().c_str()); 2109 m_completion_type = completion_type; 2110 } break; 2111 default: 2112 llvm_unreachable("Unimplemented option"); 2113 } 2114 2115 return error; 2116 } 2117 2118 void OptionParsingStarting(ExecutionContext *execution_context) override { 2119 m_class_name.clear(); 2120 m_funct_name.clear(); 2121 m_short_help.clear(); 2122 m_completion_type = eNoCompletion; 2123 m_overwrite_lazy = eLazyBoolCalculate; 2124 m_synchronicity = eScriptedCommandSynchronicitySynchronous; 2125 m_parsed_command = false; 2126 } 2127 2128 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2129 return llvm::ArrayRef(g_script_add_options); 2130 } 2131 2132 // Instance variables to hold the values for command options. 2133 2134 std::string m_class_name; 2135 std::string m_funct_name; 2136 std::string m_short_help; 2137 LazyBool m_overwrite_lazy = eLazyBoolCalculate; 2138 ScriptedCommandSynchronicity m_synchronicity = 2139 eScriptedCommandSynchronicitySynchronous; 2140 CompletionType m_completion_type = eNoCompletion; 2141 bool m_parsed_command = false; 2142 }; 2143 2144 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 2145 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 2146 if (output_sp && interactive) { 2147 output_sp->PutCString(g_python_command_instructions); 2148 output_sp->Flush(); 2149 } 2150 } 2151 2152 void IOHandlerInputComplete(IOHandler &io_handler, 2153 std::string &data) override { 2154 StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 2155 2156 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2157 if (interpreter) { 2158 StringList lines; 2159 lines.SplitIntoLines(data); 2160 if (lines.GetSize() > 0) { 2161 std::string funct_name_str; 2162 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 2163 if (funct_name_str.empty()) { 2164 error_sp->Printf("error: unable to obtain a function name, didn't " 2165 "add python command.\n"); 2166 error_sp->Flush(); 2167 } else { 2168 // everything should be fine now, let's add this alias 2169 2170 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 2171 m_interpreter, m_cmd_name, funct_name_str, m_short_help, 2172 m_synchronicity, m_completion_type)); 2173 if (!m_container) { 2174 Status error = m_interpreter.AddUserCommand( 2175 m_cmd_name, command_obj_sp, m_overwrite); 2176 if (error.Fail()) { 2177 error_sp->Printf("error: unable to add selected command: '%s'", 2178 error.AsCString()); 2179 error_sp->Flush(); 2180 } 2181 } else { 2182 llvm::Error llvm_error = m_container->LoadUserSubcommand( 2183 m_cmd_name, command_obj_sp, m_overwrite); 2184 if (llvm_error) { 2185 error_sp->Printf("error: unable to add selected command: '%s'", 2186 llvm::toString(std::move(llvm_error)).c_str()); 2187 error_sp->Flush(); 2188 } 2189 } 2190 } 2191 } else { 2192 error_sp->Printf( 2193 "error: unable to create function, didn't add python command\n"); 2194 error_sp->Flush(); 2195 } 2196 } else { 2197 error_sp->Printf("error: empty function, didn't add python command\n"); 2198 error_sp->Flush(); 2199 } 2200 } else { 2201 error_sp->Printf( 2202 "error: script interpreter missing, didn't add python command\n"); 2203 error_sp->Flush(); 2204 } 2205 2206 io_handler.SetIsDone(true); 2207 } 2208 2209 void DoExecute(Args &command, CommandReturnObject &result) override { 2210 if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { 2211 result.AppendError("only scripting language supported for scripted " 2212 "commands is currently Python"); 2213 return; 2214 } 2215 2216 if (command.GetArgumentCount() == 0) { 2217 result.AppendError("'command script add' requires at least one argument"); 2218 return; 2219 } 2220 // Store the options in case we get multi-line input, also figure out the 2221 // default if not user supplied: 2222 switch (m_options.m_overwrite_lazy) { 2223 case eLazyBoolCalculate: 2224 m_overwrite = !GetDebugger().GetCommandInterpreter().GetRequireCommandOverwrite(); 2225 break; 2226 case eLazyBoolYes: 2227 m_overwrite = true; 2228 break; 2229 case eLazyBoolNo: 2230 m_overwrite = false; 2231 } 2232 2233 Status path_error; 2234 m_container = GetCommandInterpreter().VerifyUserMultiwordCmdPath( 2235 command, true, path_error); 2236 2237 if (path_error.Fail()) { 2238 result.AppendErrorWithFormat("error in command path: %s", 2239 path_error.AsCString()); 2240 return; 2241 } 2242 2243 if (!m_container) { 2244 // This is getting inserted into the root of the interpreter. 2245 m_cmd_name = std::string(command[0].ref()); 2246 } else { 2247 size_t num_args = command.GetArgumentCount(); 2248 m_cmd_name = std::string(command[num_args - 1].ref()); 2249 } 2250 2251 m_short_help.assign(m_options.m_short_help); 2252 m_synchronicity = m_options.m_synchronicity; 2253 m_completion_type = m_options.m_completion_type; 2254 2255 // Handle the case where we prompt for the script code first: 2256 if (m_options.m_class_name.empty() && m_options.m_funct_name.empty()) { 2257 m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt 2258 *this); // IOHandlerDelegate 2259 return; 2260 } 2261 2262 CommandObjectSP new_cmd_sp; 2263 if (m_options.m_class_name.empty()) { 2264 new_cmd_sp.reset(new CommandObjectPythonFunction( 2265 m_interpreter, m_cmd_name, m_options.m_funct_name, 2266 m_options.m_short_help, m_synchronicity, m_completion_type)); 2267 } else { 2268 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 2269 if (!interpreter) { 2270 result.AppendError("cannot find ScriptInterpreter"); 2271 return; 2272 } 2273 2274 auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 2275 m_options.m_class_name.c_str()); 2276 if (!cmd_obj_sp) { 2277 result.AppendErrorWithFormatv("cannot create helper object for: " 2278 "'{0}'", m_options.m_class_name); 2279 return; 2280 } 2281 2282 if (m_options.m_parsed_command) { 2283 new_cmd_sp = CommandObjectScriptingObjectParsed::Create(m_interpreter, 2284 m_cmd_name, cmd_obj_sp, m_synchronicity, result); 2285 if (!result.Succeeded()) 2286 return; 2287 } else 2288 new_cmd_sp.reset(new CommandObjectScriptingObjectRaw( 2289 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity, 2290 m_completion_type)); 2291 } 2292 2293 // Assume we're going to succeed... 2294 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2295 if (!m_container) { 2296 Status add_error = 2297 m_interpreter.AddUserCommand(m_cmd_name, new_cmd_sp, m_overwrite); 2298 if (add_error.Fail()) 2299 result.AppendErrorWithFormat("cannot add command: %s", 2300 add_error.AsCString()); 2301 } else { 2302 llvm::Error llvm_error = 2303 m_container->LoadUserSubcommand(m_cmd_name, new_cmd_sp, m_overwrite); 2304 if (llvm_error) 2305 result.AppendErrorWithFormat( 2306 "cannot add command: %s", 2307 llvm::toString(std::move(llvm_error)).c_str()); 2308 } 2309 } 2310 2311 CommandOptions m_options; 2312 std::string m_cmd_name; 2313 CommandObjectMultiword *m_container = nullptr; 2314 std::string m_short_help; 2315 bool m_overwrite = false; 2316 ScriptedCommandSynchronicity m_synchronicity = 2317 eScriptedCommandSynchronicitySynchronous; 2318 CompletionType m_completion_type = eNoCompletion; 2319 }; 2320 2321 // CommandObjectCommandsScriptList 2322 2323 class CommandObjectCommandsScriptList : public CommandObjectParsed { 2324 public: 2325 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 2326 : CommandObjectParsed(interpreter, "command script list", 2327 "List defined top-level scripted commands.", 2328 nullptr) {} 2329 2330 ~CommandObjectCommandsScriptList() override = default; 2331 2332 void DoExecute(Args &command, CommandReturnObject &result) override { 2333 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 2334 2335 result.SetStatus(eReturnStatusSuccessFinishResult); 2336 } 2337 }; 2338 2339 // CommandObjectCommandsScriptClear 2340 2341 class CommandObjectCommandsScriptClear : public CommandObjectParsed { 2342 public: 2343 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 2344 : CommandObjectParsed(interpreter, "command script clear", 2345 "Delete all scripted commands.", nullptr) {} 2346 2347 ~CommandObjectCommandsScriptClear() override = default; 2348 2349 protected: 2350 void DoExecute(Args &command, CommandReturnObject &result) override { 2351 m_interpreter.RemoveAllUser(); 2352 2353 result.SetStatus(eReturnStatusSuccessFinishResult); 2354 } 2355 }; 2356 2357 // CommandObjectCommandsScriptDelete 2358 2359 class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 2360 public: 2361 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 2362 : CommandObjectParsed( 2363 interpreter, "command script delete", 2364 "Delete a scripted command by specifying the path to the command.", 2365 nullptr) { 2366 AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus); 2367 } 2368 2369 ~CommandObjectCommandsScriptDelete() override = default; 2370 2371 void 2372 HandleArgumentCompletion(CompletionRequest &request, 2373 OptionElementVector &opt_element_vector) override { 2374 lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs( 2375 m_interpreter, request, opt_element_vector); 2376 } 2377 2378 protected: 2379 void DoExecute(Args &command, CommandReturnObject &result) override { 2380 2381 llvm::StringRef root_cmd = command[0].ref(); 2382 size_t num_args = command.GetArgumentCount(); 2383 2384 if (root_cmd.empty()) { 2385 result.AppendErrorWithFormat("empty root command name"); 2386 return; 2387 } 2388 if (!m_interpreter.HasUserCommands() && 2389 !m_interpreter.HasUserMultiwordCommands()) { 2390 result.AppendErrorWithFormat("can only delete user defined commands, " 2391 "but no user defined commands found"); 2392 return; 2393 } 2394 2395 CommandObjectSP cmd_sp = m_interpreter.GetCommandSPExact(root_cmd); 2396 if (!cmd_sp) { 2397 result.AppendErrorWithFormat("command '%s' not found.", 2398 command[0].c_str()); 2399 return; 2400 } 2401 if (!cmd_sp->IsUserCommand()) { 2402 result.AppendErrorWithFormat("command '%s' is not a user command.", 2403 command[0].c_str()); 2404 return; 2405 } 2406 if (cmd_sp->GetAsMultiwordCommand() && num_args == 1) { 2407 result.AppendErrorWithFormat("command '%s' is a multi-word command.\n " 2408 "Delete with \"command container delete\"", 2409 command[0].c_str()); 2410 return; 2411 } 2412 2413 if (command.GetArgumentCount() == 1) { 2414 m_interpreter.RemoveUser(root_cmd); 2415 result.SetStatus(eReturnStatusSuccessFinishResult); 2416 return; 2417 } 2418 // We're deleting a command from a multiword command. Verify the command 2419 // path: 2420 Status error; 2421 CommandObjectMultiword *container = 2422 GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true, 2423 error); 2424 if (error.Fail()) { 2425 result.AppendErrorWithFormat("could not resolve command path: %s", 2426 error.AsCString()); 2427 return; 2428 } 2429 if (!container) { 2430 // This means that command only had a leaf command, so the container is 2431 // the root. That should have been handled above. 2432 result.AppendErrorWithFormat("could not find a container for '%s'", 2433 command[0].c_str()); 2434 return; 2435 } 2436 const char *leaf_cmd = command[num_args - 1].c_str(); 2437 llvm::Error llvm_error = 2438 container->RemoveUserSubcommand(leaf_cmd, 2439 /* multiword not okay */ false); 2440 if (llvm_error) { 2441 result.AppendErrorWithFormat( 2442 "could not delete command '%s': %s", leaf_cmd, 2443 llvm::toString(std::move(llvm_error)).c_str()); 2444 return; 2445 } 2446 2447 Stream &out_stream = result.GetOutputStream(); 2448 2449 out_stream << "Deleted command:"; 2450 for (size_t idx = 0; idx < num_args; idx++) { 2451 out_stream << ' '; 2452 out_stream << command[idx].c_str(); 2453 } 2454 out_stream << '\n'; 2455 result.SetStatus(eReturnStatusSuccessFinishResult); 2456 } 2457 }; 2458 2459 #pragma mark CommandObjectMultiwordCommandsScript 2460 2461 // CommandObjectMultiwordCommandsScript 2462 2463 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 2464 public: 2465 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 2466 : CommandObjectMultiword( 2467 interpreter, "command script", 2468 "Commands for managing custom " 2469 "commands implemented by " 2470 "interpreter scripts.", 2471 "command script <subcommand> [<subcommand-options>]") { 2472 LoadSubCommand("add", CommandObjectSP( 2473 new CommandObjectCommandsScriptAdd(interpreter))); 2474 LoadSubCommand( 2475 "delete", 2476 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 2477 LoadSubCommand( 2478 "clear", 2479 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 2480 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 2481 interpreter))); 2482 LoadSubCommand( 2483 "import", 2484 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 2485 } 2486 2487 ~CommandObjectMultiwordCommandsScript() override = default; 2488 }; 2489 2490 #pragma mark CommandObjectCommandContainer 2491 #define LLDB_OPTIONS_container_add 2492 #include "CommandOptions.inc" 2493 2494 class CommandObjectCommandsContainerAdd : public CommandObjectParsed { 2495 public: 2496 CommandObjectCommandsContainerAdd(CommandInterpreter &interpreter) 2497 : CommandObjectParsed( 2498 interpreter, "command container add", 2499 "Add a container command to lldb. Adding to built-" 2500 "in container commands is not allowed.", 2501 "command container add [[path1]...] container-name") { 2502 AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus); 2503 } 2504 2505 ~CommandObjectCommandsContainerAdd() override = default; 2506 2507 Options *GetOptions() override { return &m_options; } 2508 2509 void 2510 HandleArgumentCompletion(CompletionRequest &request, 2511 OptionElementVector &opt_element_vector) override { 2512 lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs( 2513 m_interpreter, request, opt_element_vector); 2514 } 2515 2516 protected: 2517 class CommandOptions : public Options { 2518 public: 2519 CommandOptions() = default; 2520 2521 ~CommandOptions() override = default; 2522 2523 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2524 ExecutionContext *execution_context) override { 2525 Status error; 2526 const int short_option = m_getopt_table[option_idx].val; 2527 2528 switch (short_option) { 2529 case 'h': 2530 if (!option_arg.empty()) 2531 m_short_help = std::string(option_arg); 2532 break; 2533 case 'o': 2534 m_overwrite = true; 2535 break; 2536 case 'H': 2537 if (!option_arg.empty()) 2538 m_long_help = std::string(option_arg); 2539 break; 2540 default: 2541 llvm_unreachable("Unimplemented option"); 2542 } 2543 2544 return error; 2545 } 2546 2547 void OptionParsingStarting(ExecutionContext *execution_context) override { 2548 m_short_help.clear(); 2549 m_long_help.clear(); 2550 m_overwrite = false; 2551 } 2552 2553 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2554 return llvm::ArrayRef(g_container_add_options); 2555 } 2556 2557 // Instance variables to hold the values for command options. 2558 2559 std::string m_short_help; 2560 std::string m_long_help; 2561 bool m_overwrite = false; 2562 }; 2563 void DoExecute(Args &command, CommandReturnObject &result) override { 2564 size_t num_args = command.GetArgumentCount(); 2565 2566 if (num_args == 0) { 2567 result.AppendError("no command was specified"); 2568 return; 2569 } 2570 2571 if (num_args == 1) { 2572 // We're adding this as a root command, so use the interpreter. 2573 const char *cmd_name = command.GetArgumentAtIndex(0); 2574 auto cmd_sp = CommandObjectSP(new CommandObjectMultiword( 2575 GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(), 2576 m_options.m_long_help.c_str())); 2577 cmd_sp->GetAsMultiwordCommand()->SetRemovable(true); 2578 Status add_error = GetCommandInterpreter().AddUserCommand( 2579 cmd_name, cmd_sp, m_options.m_overwrite); 2580 if (add_error.Fail()) { 2581 result.AppendErrorWithFormat("error adding command: %s", 2582 add_error.AsCString()); 2583 return; 2584 } 2585 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2586 return; 2587 } 2588 2589 // We're adding this to a subcommand, first find the subcommand: 2590 Status path_error; 2591 CommandObjectMultiword *add_to_me = 2592 GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true, 2593 path_error); 2594 2595 if (!add_to_me) { 2596 result.AppendErrorWithFormat("error adding command: %s", 2597 path_error.AsCString()); 2598 return; 2599 } 2600 2601 const char *cmd_name = command.GetArgumentAtIndex(num_args - 1); 2602 auto cmd_sp = CommandObjectSP(new CommandObjectMultiword( 2603 GetCommandInterpreter(), cmd_name, m_options.m_short_help.c_str(), 2604 m_options.m_long_help.c_str())); 2605 llvm::Error llvm_error = 2606 add_to_me->LoadUserSubcommand(cmd_name, cmd_sp, m_options.m_overwrite); 2607 if (llvm_error) { 2608 result.AppendErrorWithFormat("error adding subcommand: %s", 2609 llvm::toString(std::move(llvm_error)).c_str()); 2610 return; 2611 } 2612 2613 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2614 } 2615 2616 private: 2617 CommandOptions m_options; 2618 }; 2619 2620 #define LLDB_OPTIONS_multiword_delete 2621 #include "CommandOptions.inc" 2622 class CommandObjectCommandsContainerDelete : public CommandObjectParsed { 2623 public: 2624 CommandObjectCommandsContainerDelete(CommandInterpreter &interpreter) 2625 : CommandObjectParsed( 2626 interpreter, "command container delete", 2627 "Delete a container command previously added to " 2628 "lldb.", 2629 "command container delete [[path1] ...] container-cmd") { 2630 AddSimpleArgumentList(eArgTypeCommand, eArgRepeatPlus); 2631 } 2632 2633 ~CommandObjectCommandsContainerDelete() override = default; 2634 2635 void 2636 HandleArgumentCompletion(CompletionRequest &request, 2637 OptionElementVector &opt_element_vector) override { 2638 lldb_private::CommandCompletions::CompleteModifiableCmdPathArgs( 2639 m_interpreter, request, opt_element_vector); 2640 } 2641 2642 protected: 2643 void DoExecute(Args &command, CommandReturnObject &result) override { 2644 size_t num_args = command.GetArgumentCount(); 2645 2646 if (num_args == 0) { 2647 result.AppendError("No command was specified."); 2648 return; 2649 } 2650 2651 if (num_args == 1) { 2652 // We're removing a root command, so we need to delete it from the 2653 // interpreter. 2654 const char *cmd_name = command.GetArgumentAtIndex(0); 2655 // Let's do a little more work here so we can do better error reporting. 2656 CommandInterpreter &interp = GetCommandInterpreter(); 2657 CommandObjectSP cmd_sp = interp.GetCommandSPExact(cmd_name); 2658 if (!cmd_sp) { 2659 result.AppendErrorWithFormat("container command %s doesn't exist.", 2660 cmd_name); 2661 return; 2662 } 2663 if (!cmd_sp->IsUserCommand()) { 2664 result.AppendErrorWithFormat( 2665 "container command %s is not a user command", cmd_name); 2666 return; 2667 } 2668 if (!cmd_sp->GetAsMultiwordCommand()) { 2669 result.AppendErrorWithFormat("command %s is not a container command", 2670 cmd_name); 2671 return; 2672 } 2673 2674 bool did_remove = GetCommandInterpreter().RemoveUserMultiword(cmd_name); 2675 if (!did_remove) { 2676 result.AppendErrorWithFormat("error removing command %s.", cmd_name); 2677 return; 2678 } 2679 2680 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2681 return; 2682 } 2683 2684 // We're removing a subcommand, first find the subcommand's owner: 2685 Status path_error; 2686 CommandObjectMultiword *container = 2687 GetCommandInterpreter().VerifyUserMultiwordCmdPath(command, true, 2688 path_error); 2689 2690 if (!container) { 2691 result.AppendErrorWithFormat("error removing container command: %s", 2692 path_error.AsCString()); 2693 return; 2694 } 2695 const char *leaf = command.GetArgumentAtIndex(num_args - 1); 2696 llvm::Error llvm_error = 2697 container->RemoveUserSubcommand(leaf, /* multiword okay */ true); 2698 if (llvm_error) { 2699 result.AppendErrorWithFormat("error removing container command: %s", 2700 llvm::toString(std::move(llvm_error)).c_str()); 2701 return; 2702 } 2703 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2704 } 2705 }; 2706 2707 class CommandObjectCommandContainer : public CommandObjectMultiword { 2708 public: 2709 CommandObjectCommandContainer(CommandInterpreter &interpreter) 2710 : CommandObjectMultiword( 2711 interpreter, "command container", 2712 "Commands for adding container commands to lldb. " 2713 "Container commands are containers for other commands. You can " 2714 "add nested container commands by specifying a command path, " 2715 "but you can't add commands into the built-in command hierarchy.", 2716 "command container <subcommand> [<subcommand-options>]") { 2717 LoadSubCommand("add", CommandObjectSP(new CommandObjectCommandsContainerAdd( 2718 interpreter))); 2719 LoadSubCommand( 2720 "delete", 2721 CommandObjectSP(new CommandObjectCommandsContainerDelete(interpreter))); 2722 } 2723 2724 ~CommandObjectCommandContainer() override = default; 2725 }; 2726 2727 #pragma mark CommandObjectMultiwordCommands 2728 2729 // CommandObjectMultiwordCommands 2730 2731 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 2732 CommandInterpreter &interpreter) 2733 : CommandObjectMultiword(interpreter, "command", 2734 "Commands for managing custom LLDB commands.", 2735 "command <subcommand> [<subcommand-options>]") { 2736 LoadSubCommand("source", 2737 CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 2738 LoadSubCommand("alias", 2739 CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 2740 LoadSubCommand("unalias", CommandObjectSP( 2741 new CommandObjectCommandsUnalias(interpreter))); 2742 LoadSubCommand("delete", 2743 CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 2744 LoadSubCommand("container", CommandObjectSP(new CommandObjectCommandContainer( 2745 interpreter))); 2746 LoadSubCommand( 2747 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 2748 LoadSubCommand( 2749 "script", 2750 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 2751 } 2752 2753 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 2754