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