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