180814287SRaphael Isemann //===-- CommandObjectCommands.cpp -----------------------------------------===// 2ebc09c36SJim Ingham // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ebc09c36SJim Ingham // 7ebc09c36SJim Ingham //===----------------------------------------------------------------------===// 8ebc09c36SJim Ingham 96e3d8e7fSEugene Zelenko #include "CommandObjectCommands.h" 1046d4aa21SEnrico Granata #include "CommandObjectHelp.h" 119390b346SJonas Devlieghere #include "CommandObjectRegexCommand.h" 12ebc09c36SJim Ingham #include "lldb/Core/Debugger.h" 1344d93782SGreg Clayton #include "lldb/Core/IOHandler.h" 147594f14fSEnrico Granata #include "lldb/Interpreter/CommandHistory.h" 15ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h" 16ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h" 1747cbf4a0SPavel Labath #include "lldb/Interpreter/OptionArgParser.h" 18012d4fcaSEnrico Granata #include "lldb/Interpreter/OptionValueBoolean.h" 1945d0e238SEnrico Granata #include "lldb/Interpreter/OptionValueString.h" 207594f14fSEnrico Granata #include "lldb/Interpreter/OptionValueUInt64.h" 21ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h" 2299f0b8f9SEnrico Granata #include "lldb/Interpreter/ScriptInterpreter.h" 23145d95c9SPavel Labath #include "lldb/Utility/Args.h" 24573ab909SZachary Turner #include "lldb/Utility/StringList.h" 259390b346SJonas Devlieghere #include "llvm/ADT/StringRef.h" 26ebc09c36SJim Ingham 27ebc09c36SJim Ingham using namespace lldb; 28ebc09c36SJim Ingham using namespace lldb_private; 29ebc09c36SJim Ingham 30ebc09c36SJim Ingham // CommandObjectCommandsSource 31ebc09c36SJim Ingham 3264becc11SRaphael Isemann #define LLDB_OPTIONS_source 3364becc11SRaphael Isemann #include "CommandOptions.inc" 341f0f5b5bSZachary Turner 35b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed { 365a988416SJim Ingham public: 377428a18cSKate Stone CommandObjectCommandsSource(CommandInterpreter &interpreter) 38b9c1b51eSKate Stone : CommandObjectParsed( 39b9c1b51eSKate Stone interpreter, "command source", 40b9c1b51eSKate Stone "Read and execute LLDB commands from the file <filename>.", 416e3d8e7fSEugene Zelenko nullptr), 42b9c1b51eSKate Stone m_options() { 435a988416SJim Ingham CommandArgumentEntry arg; 445a988416SJim Ingham CommandArgumentData file_arg; 455a988416SJim Ingham 465a988416SJim Ingham // Define the first (and only) variant of this arg. 475a988416SJim Ingham file_arg.arg_type = eArgTypeFilename; 485a988416SJim Ingham file_arg.arg_repetition = eArgRepeatPlain; 495a988416SJim Ingham 50b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 51b9c1b51eSKate Stone // argument entry. 525a988416SJim Ingham arg.push_back(file_arg); 535a988416SJim Ingham 545a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 555a988416SJim Ingham m_arguments.push_back(arg); 565a988416SJim Ingham } 575a988416SJim Ingham 586e3d8e7fSEugene Zelenko ~CommandObjectCommandsSource() override = default; 595a988416SJim Ingham 60b9c1b51eSKate Stone const char *GetRepeatCommand(Args ¤t_command_args, 61b9c1b51eSKate Stone uint32_t index) override { 625a988416SJim Ingham return ""; 635a988416SJim Ingham } 645a988416SJim Ingham 65ae34ed2cSRaphael Isemann void 66ae34ed2cSRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 672443bbd4SRaphael Isemann OptionElementVector &opt_element_vector) override { 68b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 69b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 70a2e76c0bSRaphael Isemann request, nullptr); 715a988416SJim Ingham } 725a988416SJim Ingham 73b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 745a988416SJim Ingham 755a988416SJim Ingham protected: 76b9c1b51eSKate Stone class CommandOptions : public Options { 77e16c50a1SJim Ingham public: 78b9c1b51eSKate Stone CommandOptions() 79b9c1b51eSKate Stone : Options(), m_stop_on_error(true), m_silent_run(false), 80b9c1b51eSKate Stone m_stop_on_continue(true) {} 81e16c50a1SJim Ingham 826e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 83e16c50a1SJim Ingham 8497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 85b9c1b51eSKate Stone ExecutionContext *execution_context) override { 8697206d57SZachary Turner Status error; 873bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 88e16c50a1SJim Ingham 89b9c1b51eSKate Stone switch (short_option) { 90e16c50a1SJim Ingham case 'e': 91fe11483bSZachary Turner error = m_stop_on_error.SetValueFromString(option_arg); 92e16c50a1SJim Ingham break; 93340b0309SGreg Clayton 94e16c50a1SJim Ingham case 'c': 95fe11483bSZachary Turner error = m_stop_on_continue.SetValueFromString(option_arg); 96e16c50a1SJim Ingham break; 97340b0309SGreg Clayton 9860986174SMichael Sartain case 's': 99fe11483bSZachary Turner error = m_silent_run.SetValueFromString(option_arg); 10060986174SMichael Sartain break; 101340b0309SGreg Clayton 102e16c50a1SJim Ingham default: 10336162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 104e16c50a1SJim Ingham } 105e16c50a1SJim Ingham 106e16c50a1SJim Ingham return error; 107e16c50a1SJim Ingham } 108e16c50a1SJim Ingham 109b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 110012d4fcaSEnrico Granata m_stop_on_error.Clear(); 111340b0309SGreg Clayton m_silent_run.Clear(); 112340b0309SGreg Clayton m_stop_on_continue.Clear(); 113e16c50a1SJim Ingham } 114e16c50a1SJim Ingham 1151f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 11670602439SZachary Turner return llvm::makeArrayRef(g_source_options); 1171f0f5b5bSZachary Turner } 118e16c50a1SJim Ingham 119e16c50a1SJim Ingham // Instance variables to hold the values for command options. 120e16c50a1SJim Ingham 121012d4fcaSEnrico Granata OptionValueBoolean m_stop_on_error; 122340b0309SGreg Clayton OptionValueBoolean m_silent_run; 123340b0309SGreg Clayton OptionValueBoolean m_stop_on_continue; 124e16c50a1SJim Ingham }; 125e16c50a1SJim Ingham 126b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1274574a890SZachary Turner if (command.GetArgumentCount() != 1) { 1284574a890SZachary Turner result.AppendErrorWithFormat( 1294574a890SZachary Turner "'%s' takes exactly one executable filename argument.\n", 1304574a890SZachary Turner GetCommandName().str().c_str()); 1314574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 1324574a890SZachary Turner return false; 1334574a890SZachary Turner } 134ebc09c36SJim Ingham 1350d9a201eSRaphael Isemann FileSpec cmd_file(command[0].ref()); 1368f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(cmd_file); 137ebc09c36SJim Ingham 138*a01b26fbSTatyana Krasnukha CommandInterpreterRunOptions options; 139340b0309SGreg Clayton // If any options were set, then use them 140340b0309SGreg Clayton if (m_options.m_stop_on_error.OptionWasSet() || 141340b0309SGreg Clayton m_options.m_silent_run.OptionWasSet() || 142b9c1b51eSKate Stone m_options.m_stop_on_continue.OptionWasSet()) { 1431c19b74cSJonas Devlieghere if (m_options.m_stop_on_continue.OptionWasSet()) 1441c19b74cSJonas Devlieghere options.SetStopOnContinue( 1451c19b74cSJonas Devlieghere m_options.m_stop_on_continue.GetCurrentValue()); 1461c19b74cSJonas Devlieghere 1471c19b74cSJonas Devlieghere if (m_options.m_stop_on_error.OptionWasSet()) 14826c7bf93SJim Ingham options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 149c678ed77SStefan Granitz 150c678ed77SStefan Granitz // Individual silent setting is override for global command echo settings. 151c678ed77SStefan Granitz if (m_options.m_silent_run.GetCurrentValue()) { 152c678ed77SStefan Granitz options.SetSilent(true); 153c678ed77SStefan Granitz } else { 154c678ed77SStefan Granitz options.SetPrintResults(true); 155c0b48ab6SJonas Devlieghere options.SetPrintErrors(true); 156c678ed77SStefan Granitz options.SetEchoCommands(m_interpreter.GetEchoCommands()); 157c678ed77SStefan Granitz options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands()); 158c678ed77SStefan Granitz } 159ebc09c36SJim Ingham } 160*a01b26fbSTatyana Krasnukha 161*a01b26fbSTatyana Krasnukha m_interpreter.HandleCommandsFromFile(cmd_file, options, result); 162ebc09c36SJim Ingham return result.Succeeded(); 163ebc09c36SJim Ingham } 1646e3d8e7fSEugene Zelenko 1655a988416SJim Ingham CommandOptions m_options; 166ebc09c36SJim Ingham }; 167ebc09c36SJim Ingham 168ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias 169ebc09c36SJim Ingham // CommandObjectCommandsAlias 170ebc09c36SJim Ingham 17164becc11SRaphael Isemann #define LLDB_OPTIONS_alias 17264becc11SRaphael Isemann #include "CommandOptions.inc" 1731f0f5b5bSZachary Turner 174b9c1b51eSKate Stone static const char *g_python_command_instructions = 175b9c1b51eSKate Stone "Enter your Python command(s). Type 'DONE' to end.\n" 176be93a35aSEnrico Granata "You must define a Python function with this signature:\n" 17744d93782SGreg Clayton "def my_command_impl(debugger, args, result, internal_dict):\n"; 178be93a35aSEnrico Granata 179b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw { 18045d0e238SEnrico Granata protected: 181b9c1b51eSKate Stone class CommandOptions : public OptionGroup { 182ebc09c36SJim Ingham public: 183b9c1b51eSKate Stone CommandOptions() : OptionGroup(), m_help(), m_long_help() {} 18445d0e238SEnrico Granata 18545d0e238SEnrico Granata ~CommandOptions() override = default; 18645d0e238SEnrico Granata 1871f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 18870602439SZachary Turner return llvm::makeArrayRef(g_alias_options); 1891f0f5b5bSZachary Turner } 19045d0e238SEnrico Granata 19197206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 192b9c1b51eSKate Stone ExecutionContext *execution_context) override { 19397206d57SZachary Turner Status error; 19445d0e238SEnrico Granata 1951f0f5b5bSZachary Turner const int short_option = GetDefinitions()[option_idx].short_option; 1968cef4b0bSZachary Turner std::string option_str(option_value); 19745d0e238SEnrico Granata 198b9c1b51eSKate Stone switch (short_option) { 19945d0e238SEnrico Granata case 'h': 2008cef4b0bSZachary Turner m_help.SetCurrentValue(option_str); 20145d0e238SEnrico Granata m_help.SetOptionWasSet(); 20245d0e238SEnrico Granata break; 20345d0e238SEnrico Granata 20445d0e238SEnrico Granata case 'H': 2058cef4b0bSZachary Turner m_long_help.SetCurrentValue(option_str); 20645d0e238SEnrico Granata m_long_help.SetOptionWasSet(); 20745d0e238SEnrico Granata break; 20845d0e238SEnrico Granata 20945d0e238SEnrico Granata default: 21036162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 21145d0e238SEnrico Granata } 21245d0e238SEnrico Granata 21345d0e238SEnrico Granata return error; 21445d0e238SEnrico Granata } 21545d0e238SEnrico Granata 216b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 21745d0e238SEnrico Granata m_help.Clear(); 21845d0e238SEnrico Granata m_long_help.Clear(); 21945d0e238SEnrico Granata } 22045d0e238SEnrico Granata 22145d0e238SEnrico Granata OptionValueString m_help; 22245d0e238SEnrico Granata OptionValueString m_long_help; 22345d0e238SEnrico Granata }; 22445d0e238SEnrico Granata 22545d0e238SEnrico Granata OptionGroupOptions m_option_group; 22645d0e238SEnrico Granata CommandOptions m_command_options; 22745d0e238SEnrico Granata 22845d0e238SEnrico Granata public: 229b9c1b51eSKate Stone Options *GetOptions() override { return &m_option_group; } 23045d0e238SEnrico Granata 2317428a18cSKate Stone CommandObjectCommandsAlias(CommandInterpreter &interpreter) 232b9c1b51eSKate Stone : CommandObjectRaw( 233b9c1b51eSKate Stone interpreter, "command alias", 234a449698cSZachary Turner "Define a custom command in terms of an existing command."), 235b9c1b51eSKate Stone m_option_group(), m_command_options() { 23645d0e238SEnrico Granata m_option_group.Append(&m_command_options); 23745d0e238SEnrico Granata m_option_group.Finalize(); 23845d0e238SEnrico Granata 239ebc09c36SJim Ingham SetHelpLong( 240ea671fbdSKate Stone "'alias' allows the user to create a short-cut or abbreviation for long \ 241ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options. \ 242b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:" 243b9c1b51eSKate Stone R"( 244ea671fbdSKate Stone 245ea671fbdSKate Stone (lldb) command alias sc script 246ea671fbdSKate Stone 247ea671fbdSKate Stone Creates the abbreviation 'sc' for the 'script' command. 248ea671fbdSKate Stone 249ea671fbdSKate Stone (lldb) command alias bp breakpoint 250ea671fbdSKate Stone 251b9c1b51eSKate Stone )" 252b9c1b51eSKate Stone " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 253ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \ 254b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 255b9c1b51eSKate Stone R"( 256ea671fbdSKate Stone 257ea671fbdSKate Stone (lldb) command alias bpl breakpoint list 258ea671fbdSKate Stone 259ea671fbdSKate Stone Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 260ea671fbdSKate Stone 261b9c1b51eSKate Stone )" 262b9c1b51eSKate Stone "An alias can include some options for the command, with the values either \ 263ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \ 264ea671fbdSKate Stone arguments, to be filled in when the alias is invoked. The following example \ 265b9c1b51eSKate Stone shows how to create aliases with options:" 266b9c1b51eSKate Stone R"( 267ea671fbdSKate Stone 268ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 269ea671fbdSKate Stone 270b9c1b51eSKate Stone )" 271b9c1b51eSKate Stone " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 272ea671fbdSKate Stone options already part of the alias. So if the user wants to set a breakpoint \ 273ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \ 274ea671fbdSKate Stone user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 275ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used. \ 276ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \ 277ea671fbdSKate Stone occupies when the alias is used. All the occurrences of '%1' in the alias \ 278ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \ 279ea671fbdSKate Stone alias will be replaced with the second argument, and so on. This also allows \ 280ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \ 281b9c1b51eSKate Stone launch' example below)." 282b9c1b51eSKate Stone R"( 283ea671fbdSKate Stone 284b9c1b51eSKate Stone )" 285b9c1b51eSKate Stone "Note: the positional arguments must substitute as whole words in the resultant \ 286ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \ 287b9c1b51eSKate Stone \".cpp\":" 288b9c1b51eSKate Stone R"( 289ea671fbdSKate Stone 290ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 291ea671fbdSKate Stone 292b9c1b51eSKate Stone )" 293b9c1b51eSKate Stone "For more complex aliasing, use the \"command regex\" command instead. In the \ 294ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \ 295ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \ 296b9c1b51eSKate Stone argument. The user would use this alias as follows:" 297b9c1b51eSKate Stone R"( 298ea671fbdSKate Stone 299ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2 300ea671fbdSKate Stone (lldb) bfl my-file.c 137 301ea671fbdSKate Stone 302ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 303ea671fbdSKate Stone 304ea671fbdSKate Stone Another example: 305ea671fbdSKate Stone 306ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1 307ea671fbdSKate Stone (lldb) pltty /dev/tty0 308ea671fbdSKate Stone 309ea671fbdSKate Stone Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 310ea671fbdSKate Stone 311b9c1b51eSKate Stone )" 312b9c1b51eSKate Stone "If the user always wanted to pass the same value to a particular option, the \ 313ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \ 314b9c1b51eSKate Stone rather than using a positional placeholder:" 315b9c1b51eSKate Stone R"( 316ea671fbdSKate Stone 317ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3 318ea671fbdSKate Stone 319b9c1b51eSKate Stone Always sets a breakpoint on line 3 of whatever file is indicated.)"); 320ebc09c36SJim Ingham 321405fe67fSCaroline Tice CommandArgumentEntry arg1; 322405fe67fSCaroline Tice CommandArgumentEntry arg2; 323405fe67fSCaroline Tice CommandArgumentEntry arg3; 324405fe67fSCaroline Tice CommandArgumentData alias_arg; 325405fe67fSCaroline Tice CommandArgumentData cmd_arg; 326405fe67fSCaroline Tice CommandArgumentData options_arg; 327405fe67fSCaroline Tice 328405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 329405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 330405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 331405fe67fSCaroline Tice 332b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 333b9c1b51eSKate Stone // argument entry. 334405fe67fSCaroline Tice arg1.push_back(alias_arg); 335405fe67fSCaroline Tice 336405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 337405fe67fSCaroline Tice cmd_arg.arg_type = eArgTypeCommandName; 338405fe67fSCaroline Tice cmd_arg.arg_repetition = eArgRepeatPlain; 339405fe67fSCaroline Tice 340b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 341b9c1b51eSKate Stone // argument entry. 342405fe67fSCaroline Tice arg2.push_back(cmd_arg); 343405fe67fSCaroline Tice 344405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 345405fe67fSCaroline Tice options_arg.arg_type = eArgTypeAliasOptions; 346405fe67fSCaroline Tice options_arg.arg_repetition = eArgRepeatOptional; 347405fe67fSCaroline Tice 348b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 349b9c1b51eSKate Stone // argument entry. 350405fe67fSCaroline Tice arg3.push_back(options_arg); 351405fe67fSCaroline Tice 352405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 353405fe67fSCaroline Tice m_arguments.push_back(arg1); 354405fe67fSCaroline Tice m_arguments.push_back(arg2); 355405fe67fSCaroline Tice m_arguments.push_back(arg3); 356ebc09c36SJim Ingham } 357ebc09c36SJim Ingham 3586e3d8e7fSEugene Zelenko ~CommandObjectCommandsAlias() override = default; 359ebc09c36SJim Ingham 3605a988416SJim Ingham protected: 3614d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 362b9c1b51eSKate Stone CommandReturnObject &result) override { 3634d51a902SRaphael Isemann if (raw_command_line.empty()) { 364d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 36545d0e238SEnrico Granata return false; 36645d0e238SEnrico Granata } 36745d0e238SEnrico Granata 368e1cfbc79STodd Fiala ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 369e1cfbc79STodd Fiala m_option_group.NotifyOptionParsingStarting(&exe_ctx); 37045d0e238SEnrico Granata 3713a0e1270SRaphael Isemann OptionsWithRaw args_with_suffix(raw_command_line); 37245d0e238SEnrico Granata 3733a0e1270SRaphael Isemann if (args_with_suffix.HasArgs()) 3743a0e1270SRaphael Isemann if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result, 3753a0e1270SRaphael Isemann m_option_group, exe_ctx)) 37645d0e238SEnrico Granata return false; 37745d0e238SEnrico Granata 378daed98e5SShivam Mittal llvm::StringRef raw_command_string = args_with_suffix.GetRawPart(); 379a01bccdbSZachary Turner Args args(raw_command_string); 380844d2303SCaroline Tice 38111eb9c64SZachary Turner if (args.GetArgumentCount() < 2) { 382d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 383844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 384844d2303SCaroline Tice return false; 385844d2303SCaroline Tice } 386844d2303SCaroline Tice 387844d2303SCaroline Tice // Get the alias command. 388844d2303SCaroline Tice 3890d9a201eSRaphael Isemann auto alias_command = args[0].ref(); 3904574a890SZachary Turner if (alias_command.startswith("-")) { 391d72e412fSEnrico Granata result.AppendError("aliases starting with a dash are not supported"); 392b9c1b51eSKate Stone if (alias_command == "--help" || alias_command == "--long-help") { 393b9c1b51eSKate Stone result.AppendWarning("if trying to pass options to 'command alias' add " 394b9c1b51eSKate Stone "a -- at the end of the options"); 395d72e412fSEnrico Granata } 396d72e412fSEnrico Granata result.SetStatus(eReturnStatusFailed); 397d72e412fSEnrico Granata return false; 398d72e412fSEnrico Granata } 399844d2303SCaroline Tice 400b9c1b51eSKate Stone // Strip the new alias name off 'raw_command_string' (leave it on args, 40105097246SAdrian Prantl // which gets passed to 'Execute', which does the stripping itself. 402844d2303SCaroline Tice size_t pos = raw_command_string.find(alias_command); 403b9c1b51eSKate Stone if (pos == 0) { 404844d2303SCaroline Tice raw_command_string = raw_command_string.substr(alias_command.size()); 405844d2303SCaroline Tice pos = raw_command_string.find_first_not_of(' '); 406844d2303SCaroline Tice if ((pos != std::string::npos) && (pos > 0)) 407844d2303SCaroline Tice raw_command_string = raw_command_string.substr(pos); 408b9c1b51eSKate Stone } else { 409844d2303SCaroline Tice result.AppendError("Error parsing command string. No alias created."); 410844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 411844d2303SCaroline Tice return false; 412844d2303SCaroline Tice } 413844d2303SCaroline Tice 414844d2303SCaroline Tice // Verify that the command is alias-able. 415771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 416b9c1b51eSKate Stone result.AppendErrorWithFormat( 417b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 4184574a890SZachary Turner args[0].c_str()); 419844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 420844d2303SCaroline Tice return false; 421844d2303SCaroline Tice } 422844d2303SCaroline Tice 423b9c1b51eSKate Stone // Get CommandObject that is being aliased. The command name is read from 424a01bccdbSZachary Turner // the front of raw_command_string. raw_command_string is returned with the 425a01bccdbSZachary Turner // name of the command object stripped off the front. 426a01bccdbSZachary Turner llvm::StringRef original_raw_command_string = raw_command_string; 427b9c1b51eSKate Stone CommandObject *cmd_obj = 428b9c1b51eSKate Stone m_interpreter.GetCommandObjectForCommand(raw_command_string); 429844d2303SCaroline Tice 430b9c1b51eSKate Stone if (!cmd_obj) { 431b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid command given to 'command alias'. " 432b9c1b51eSKate Stone "'%s' does not begin with a valid command." 433b9c1b51eSKate Stone " No alias created.", 434a01bccdbSZachary Turner original_raw_command_string.str().c_str()); 435844d2303SCaroline Tice result.SetStatus(eReturnStatusFailed); 436844d2303SCaroline Tice return false; 437b9c1b51eSKate Stone } else if (!cmd_obj->WantsRawCommandString()) { 438b9c1b51eSKate Stone // Note that args was initialized with the original command, and has not 43905097246SAdrian Prantl // been updated to this point. Therefore can we pass it to the version of 44005097246SAdrian Prantl // Execute that does not need/expect raw input in the alias. 4415a988416SJim Ingham return HandleAliasingNormalCommand(args, result); 442b9c1b51eSKate Stone } else { 443b9c1b51eSKate Stone return HandleAliasingRawCommand(alias_command, raw_command_string, 444b9c1b51eSKate Stone *cmd_obj, result); 4455a988416SJim Ingham } 4465a988416SJim Ingham return result.Succeeded(); 4475a988416SJim Ingham } 4485a988416SJim Ingham 449a01bccdbSZachary Turner bool HandleAliasingRawCommand(llvm::StringRef alias_command, 450a01bccdbSZachary Turner llvm::StringRef raw_command_string, 451b9c1b51eSKate Stone CommandObject &cmd_obj, 452b9c1b51eSKate Stone CommandReturnObject &result) { 453844d2303SCaroline Tice // Verify & handle any options/arguments passed to the alias command 454844d2303SCaroline Tice 455b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 456b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 457844d2303SCaroline Tice 458b9c1b51eSKate Stone if (CommandObjectSP cmd_obj_sp = 459b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { 460a01bccdbSZachary Turner if (m_interpreter.AliasExists(alias_command) || 461a01bccdbSZachary Turner m_interpreter.UserCommandExists(alias_command)) { 462b9c1b51eSKate Stone result.AppendWarningWithFormat( 463b9c1b51eSKate Stone "Overwriting existing definition for '%s'.\n", 464a01bccdbSZachary Turner alias_command.str().c_str()); 465844d2303SCaroline Tice } 466b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 467a01bccdbSZachary Turner alias_command, cmd_obj_sp, raw_command_string)) { 46845d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 46945d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 47045d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 47145d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 472844d2303SCaroline Tice result.SetStatus(eReturnStatusSuccessFinishNoResult); 473b9c1b51eSKate Stone } else { 474472362e6SCaroline Tice result.AppendError("Unable to create requested alias.\n"); 475472362e6SCaroline Tice result.SetStatus(eReturnStatusFailed); 476472362e6SCaroline Tice } 477212130acSEnrico Granata 478b9c1b51eSKate Stone } else { 479212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 480212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 481212130acSEnrico Granata } 482212130acSEnrico Granata 483844d2303SCaroline Tice return result.Succeeded(); 484844d2303SCaroline Tice } 485ebc09c36SJim Ingham 486b9c1b51eSKate Stone bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 487867b185dSCaroline Tice size_t argc = args.GetArgumentCount(); 488ebc09c36SJim Ingham 489b9c1b51eSKate Stone if (argc < 2) { 490d72e412fSEnrico Granata result.AppendError("'command alias' requires at least two arguments"); 491ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 492ebc09c36SJim Ingham return false; 493ebc09c36SJim Ingham } 494ebc09c36SJim Ingham 4954574a890SZachary Turner // Save these in std::strings since we're going to shift them off. 496adcd0268SBenjamin Kramer const std::string alias_command(std::string(args[0].ref())); 497adcd0268SBenjamin Kramer const std::string actual_command(std::string(args[1].ref())); 498ebc09c36SJim Ingham 499ebc09c36SJim Ingham args.Shift(); // Shift the alias command word off the argument vector. 500ebc09c36SJim Ingham args.Shift(); // Shift the old command word off the argument vector. 501ebc09c36SJim Ingham 502b9c1b51eSKate Stone // Verify that the command is alias'able, and get the appropriate command 503b9c1b51eSKate Stone // object. 504ebc09c36SJim Ingham 505771ef6d4SMalcolm Parsons if (m_interpreter.CommandExists(alias_command)) { 506b9c1b51eSKate Stone result.AppendErrorWithFormat( 507b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be redefined.\n", 508ebc09c36SJim Ingham alias_command.c_str()); 509ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 5104574a890SZachary Turner return false; 5114574a890SZachary Turner } 5124574a890SZachary Turner 513b9c1b51eSKate Stone CommandObjectSP command_obj_sp( 514a449698cSZachary Turner m_interpreter.GetCommandSPExact(actual_command, true)); 515ebc09c36SJim Ingham CommandObjectSP subcommand_obj_sp; 516ebc09c36SJim Ingham bool use_subcommand = false; 5174574a890SZachary Turner if (!command_obj_sp) { 5184574a890SZachary Turner result.AppendErrorWithFormat("'%s' is not an existing command.\n", 5194574a890SZachary Turner actual_command.c_str()); 5204574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 5214574a890SZachary Turner return false; 5224574a890SZachary Turner } 523ebc09c36SJim Ingham CommandObject *cmd_obj = command_obj_sp.get(); 5246e3d8e7fSEugene Zelenko CommandObject *sub_cmd_obj = nullptr; 525b9c1b51eSKate Stone OptionArgVectorSP option_arg_vector_sp = 526b9c1b51eSKate Stone OptionArgVectorSP(new OptionArgVector); 527ebc09c36SJim Ingham 52811eb9c64SZachary Turner while (cmd_obj->IsMultiwordObject() && !args.empty()) { 5290d9a201eSRaphael Isemann auto sub_command = args[0].ref(); 53011eb9c64SZachary Turner assert(!sub_command.empty()); 5314574a890SZachary Turner subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 5324574a890SZachary Turner if (!subcommand_obj_sp) { 533b9c1b51eSKate Stone result.AppendErrorWithFormat( 534b9c1b51eSKate Stone "'%s' is not a valid sub-command of '%s'. " 535f415eeb4SCaroline Tice "Unable to create alias.\n", 5364574a890SZachary Turner args[0].c_str(), actual_command.c_str()); 537ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 538ebc09c36SJim Ingham return false; 539ebc09c36SJim Ingham } 5404574a890SZachary Turner 5414574a890SZachary Turner sub_cmd_obj = subcommand_obj_sp.get(); 5424574a890SZachary Turner use_subcommand = true; 5434574a890SZachary Turner args.Shift(); // Shift the sub_command word off the argument vector. 5444574a890SZachary Turner cmd_obj = sub_cmd_obj; 545ebc09c36SJim Ingham } 546ebc09c36SJim Ingham 547ebc09c36SJim Ingham // Verify & handle any options/arguments passed to the alias command 548ebc09c36SJim Ingham 549212130acSEnrico Granata std::string args_string; 550212130acSEnrico Granata 55111eb9c64SZachary Turner if (!args.empty()) { 552b9c1b51eSKate Stone CommandObjectSP tmp_sp = 553b9c1b51eSKate Stone m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); 554ebc09c36SJim Ingham if (use_subcommand) 5554574a890SZachary Turner tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(), 5564574a890SZachary Turner false); 557ca90c47eSCaroline Tice 558ca90c47eSCaroline Tice args.GetCommandString(args_string); 559867b185dSCaroline Tice } 560ebc09c36SJim Ingham 561771ef6d4SMalcolm Parsons if (m_interpreter.AliasExists(alias_command) || 562771ef6d4SMalcolm Parsons m_interpreter.UserCommandExists(alias_command)) { 563b9c1b51eSKate Stone result.AppendWarningWithFormat( 5644574a890SZachary Turner "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 565ebc09c36SJim Ingham } 566ebc09c36SJim Ingham 567b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 5684574a890SZachary Turner alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 569771ef6d4SMalcolm Parsons args_string)) { 57045d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 57145d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 57245d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 57345d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 574ebc09c36SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 575b9c1b51eSKate Stone } else { 576212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 577212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 578212130acSEnrico Granata return false; 579212130acSEnrico Granata } 580ebc09c36SJim Ingham 581ebc09c36SJim Ingham return result.Succeeded(); 582ebc09c36SJim Ingham } 583ebc09c36SJim Ingham }; 584ebc09c36SJim Ingham 585ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 586ebc09c36SJim Ingham // CommandObjectCommandsUnalias 587ebc09c36SJim Ingham 588b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed { 589ebc09c36SJim Ingham public: 5907428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 591b9c1b51eSKate Stone : CommandObjectParsed( 592b9c1b51eSKate Stone interpreter, "command unalias", 593b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command alias'.", 594b9c1b51eSKate Stone nullptr) { 595405fe67fSCaroline Tice CommandArgumentEntry arg; 596405fe67fSCaroline Tice CommandArgumentData alias_arg; 597405fe67fSCaroline Tice 598405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 599405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 600405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 601405fe67fSCaroline Tice 602b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 603b9c1b51eSKate Stone // argument entry. 604405fe67fSCaroline Tice arg.push_back(alias_arg); 605405fe67fSCaroline Tice 606405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 607405fe67fSCaroline Tice m_arguments.push_back(arg); 608ebc09c36SJim Ingham } 609ebc09c36SJim Ingham 6106e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 611ebc09c36SJim Ingham 61231fd64acSGongyu Deng void 61331fd64acSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 61431fd64acSGongyu Deng OptionElementVector &opt_element_vector) override { 61531fd64acSGongyu Deng if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 61631fd64acSGongyu Deng return; 61731fd64acSGongyu Deng 61831fd64acSGongyu Deng for (const auto &ent : m_interpreter.GetAliases()) { 61931fd64acSGongyu Deng request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp()); 62031fd64acSGongyu Deng } 62131fd64acSGongyu Deng } 62231fd64acSGongyu Deng 6235a988416SJim Ingham protected: 624b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 625ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 626ebc09c36SJim Ingham CommandObject *cmd_obj; 627ebc09c36SJim Ingham 62811eb9c64SZachary Turner if (args.empty()) { 62911eb9c64SZachary Turner result.AppendError("must call 'unalias' with a valid alias"); 63011eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 63111eb9c64SZachary Turner return false; 63211eb9c64SZachary Turner } 63311eb9c64SZachary Turner 6340d9a201eSRaphael Isemann auto command_name = args[0].ref(); 635a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 6364574a890SZachary Turner if (!cmd_obj) { 6374574a890SZachary Turner result.AppendErrorWithFormat( 6384574a890SZachary Turner "'%s' is not a known command.\nTry 'help' to see a " 6394574a890SZachary Turner "current list of commands.\n", 640867e7d17SZachary Turner args[0].c_str()); 6414574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 6424574a890SZachary Turner return false; 6434574a890SZachary Turner } 6444574a890SZachary Turner 645b9c1b51eSKate Stone if (m_interpreter.CommandExists(command_name)) { 646b9c1b51eSKate Stone if (cmd_obj->IsRemovable()) { 647b9c1b51eSKate Stone result.AppendErrorWithFormat( 648b9c1b51eSKate Stone "'%s' is not an alias, it is a debugger command which can be " 649b9c1b51eSKate Stone "removed using the 'command delete' command.\n", 650867e7d17SZachary Turner args[0].c_str()); 651b9c1b51eSKate Stone } else { 652b9c1b51eSKate Stone result.AppendErrorWithFormat( 653b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be removed.\n", 654867e7d17SZachary Turner args[0].c_str()); 655b547278cSGreg Clayton } 656ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 6574574a890SZachary Turner return false; 6584574a890SZachary Turner } 6594574a890SZachary Turner 660b9c1b51eSKate Stone if (!m_interpreter.RemoveAlias(command_name)) { 661a7015092SGreg Clayton if (m_interpreter.AliasExists(command_name)) 662b9c1b51eSKate Stone result.AppendErrorWithFormat( 663867e7d17SZachary Turner "Error occurred while attempting to unalias '%s'.\n", 664867e7d17SZachary Turner args[0].c_str()); 665ebc09c36SJim Ingham else 666b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 667867e7d17SZachary Turner args[0].c_str()); 668ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 6694574a890SZachary Turner return false; 670ebc09c36SJim Ingham } 671ebc09c36SJim Ingham 6724574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 673ebc09c36SJim Ingham return result.Succeeded(); 674ebc09c36SJim Ingham } 675ebc09c36SJim Ingham }; 676ebc09c36SJim Ingham 677b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 678b547278cSGreg Clayton // CommandObjectCommandsDelete 679b547278cSGreg Clayton 680b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed { 681b547278cSGreg Clayton public: 6827428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 683b9c1b51eSKate Stone : CommandObjectParsed( 684b9c1b51eSKate Stone interpreter, "command delete", 685b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command regex'.", 686b9c1b51eSKate Stone nullptr) { 687b547278cSGreg Clayton CommandArgumentEntry arg; 688b547278cSGreg Clayton CommandArgumentData alias_arg; 689b547278cSGreg Clayton 690b547278cSGreg Clayton // Define the first (and only) variant of this arg. 691b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 692b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 693b547278cSGreg Clayton 694b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 695b9c1b51eSKate Stone // argument entry. 696b547278cSGreg Clayton arg.push_back(alias_arg); 697b547278cSGreg Clayton 698b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 699b547278cSGreg Clayton m_arguments.push_back(arg); 700b547278cSGreg Clayton } 701b547278cSGreg Clayton 7026e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 703b547278cSGreg Clayton 70431fd64acSGongyu Deng void 70531fd64acSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 70631fd64acSGongyu Deng OptionElementVector &opt_element_vector) override { 70731fd64acSGongyu Deng if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 70831fd64acSGongyu Deng return; 70931fd64acSGongyu Deng 71031fd64acSGongyu Deng for (const auto &ent : m_interpreter.GetCommands()) { 71131fd64acSGongyu Deng if (ent.second->IsRemovable()) 71231fd64acSGongyu Deng request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp()); 71331fd64acSGongyu Deng } 71431fd64acSGongyu Deng } 71531fd64acSGongyu Deng 716b547278cSGreg Clayton protected: 717b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 718b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 719b547278cSGreg Clayton 72011eb9c64SZachary Turner if (args.empty()) { 72111eb9c64SZachary Turner result.AppendErrorWithFormat("must call '%s' with one or more valid user " 72211eb9c64SZachary Turner "defined regular expression command names", 723a449698cSZachary Turner GetCommandName().str().c_str()); 72411eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 725d77ea5b2SRaphael Isemann return false; 72611eb9c64SZachary Turner } 72711eb9c64SZachary Turner 7280d9a201eSRaphael Isemann auto command_name = args[0].ref(); 7294574a890SZachary Turner if (!m_interpreter.CommandExists(command_name)) { 73046d4aa21SEnrico Granata StreamString error_msg_stream; 731d5b44036SJonas Devlieghere const bool generate_upropos = true; 73246d4aa21SEnrico Granata const bool generate_type_lookup = false; 733b9c1b51eSKate Stone CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 7344574a890SZachary Turner &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 735d5b44036SJonas Devlieghere generate_upropos, generate_type_lookup); 736c156427dSZachary Turner result.AppendError(error_msg_stream.GetString()); 737b547278cSGreg Clayton result.SetStatus(eReturnStatusFailed); 7384574a890SZachary Turner return false; 739b547278cSGreg Clayton } 740b547278cSGreg Clayton 7414574a890SZachary Turner if (!m_interpreter.RemoveCommand(command_name)) { 7424574a890SZachary Turner result.AppendErrorWithFormat( 7434574a890SZachary Turner "'%s' is a permanent debugger command and cannot be removed.\n", 744867e7d17SZachary Turner args[0].c_str()); 7454574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 7464574a890SZachary Turner return false; 7474574a890SZachary Turner } 7484574a890SZachary Turner 7494574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 7504574a890SZachary Turner return true; 751b547278cSGreg Clayton } 752b547278cSGreg Clayton }; 753b547278cSGreg Clayton 754de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 7551f0f5b5bSZachary Turner 75664becc11SRaphael Isemann #define LLDB_OPTIONS_regex 75764becc11SRaphael Isemann #include "CommandOptions.inc" 7581f0f5b5bSZachary Turner 7595a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 760de164aaaSGreg Clayton 761b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed, 762b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 763de164aaaSGreg Clayton public: 7647428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 765b9c1b51eSKate Stone : CommandObjectParsed( 766a925974bSAdrian Prantl interpreter, "command regex", 767a925974bSAdrian Prantl "Define a custom command in terms of " 768b9c1b51eSKate Stone "existing commands by matching " 769b9c1b51eSKate Stone "regular expressions.", 7700e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 771b9c1b51eSKate Stone IOHandlerDelegateMultiline("", 772b9c1b51eSKate Stone IOHandlerDelegate::Completion::LLDBCommand), 773b9c1b51eSKate Stone m_options() { 774b9c1b51eSKate Stone SetHelpLong( 775b9c1b51eSKate Stone R"( 776b9c1b51eSKate Stone )" 777b9c1b51eSKate Stone "This command allows the user to create powerful regular expression commands \ 778ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 779b9c1b51eSKate Stone using the regular expression substitution format of:" 780b9c1b51eSKate Stone R"( 781ea671fbdSKate Stone 782ea671fbdSKate Stone s/<regex>/<subst>/ 783ea671fbdSKate Stone 784b9c1b51eSKate Stone )" 785b9c1b51eSKate Stone "<regex> is a regular expression that can use parenthesis to capture regular \ 786ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 787b9c1b51eSKate Stone for the first match, %2 for the second, and so on." 788b9c1b51eSKate Stone R"( 789ea671fbdSKate Stone 790b9c1b51eSKate Stone )" 791b9c1b51eSKate Stone "The regular expressions can all be specified on the command line if more than \ 792ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 793ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 794b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition." 795b9c1b51eSKate Stone R"( 796ea671fbdSKate Stone 797ea671fbdSKate Stone EXAMPLES 798ea671fbdSKate Stone 799b9c1b51eSKate Stone )" 800b9c1b51eSKate Stone "The following example will define a regular expression command named 'f' that \ 801ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 802b9c1b51eSKate Stone a number follows 'f':" 803b9c1b51eSKate Stone R"( 804ea671fbdSKate Stone 805b9c1b51eSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 806de164aaaSGreg Clayton } 807de164aaaSGreg Clayton 8086e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 809de164aaaSGreg Clayton 8105a988416SJim Ingham protected: 8110affb582SDave Lee void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 8127ca15ba7SLawrence D'Anna StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 8130affb582SDave Lee if (output_sp && interactive) { 8140affb582SDave Lee output_sp->PutCString("Enter one or more sed substitution commands in " 815b9c1b51eSKate Stone "the form: 's/<regex>/<subst>/'.\nTerminate the " 816b9c1b51eSKate Stone "substitution list with an empty line.\n"); 81744d93782SGreg Clayton output_sp->Flush(); 81844d93782SGreg Clayton } 81944d93782SGreg Clayton } 82044d93782SGreg Clayton 821b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 822b9c1b51eSKate Stone std::string &data) override { 82344d93782SGreg Clayton io_handler.SetIsDone(true); 824d5b44036SJonas Devlieghere if (m_regex_cmd_up) { 82544d93782SGreg Clayton StringList lines; 826b9c1b51eSKate Stone if (lines.SplitIntoLines(data)) { 82744d93782SGreg Clayton bool check_only = false; 8284c78b788SRaphael Isemann for (const std::string &line : lines) { 8294c78b788SRaphael Isemann Status error = AppendRegexSubstitution(line, check_only); 830b9c1b51eSKate Stone if (error.Fail()) { 83157179860SJonas Devlieghere if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) { 83257179860SJonas Devlieghere StreamSP out_stream = GetDebugger().GetAsyncOutputStream(); 83344d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 83444d93782SGreg Clayton } 83544d93782SGreg Clayton } 83644d93782SGreg Clayton } 83744d93782SGreg Clayton } 838d5b44036SJonas Devlieghere if (m_regex_cmd_up->HasRegexEntries()) { 839d5b44036SJonas Devlieghere CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 84044d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 84144d93782SGreg Clayton } 84244d93782SGreg Clayton } 84344d93782SGreg Clayton } 84444d93782SGreg Clayton 845b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 8465a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 847b9c1b51eSKate Stone if (argc == 0) { 848b9c1b51eSKate Stone result.AppendError("usage: 'command regex <command-name> " 849b9c1b51eSKate Stone "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 8500e5e5a79SGreg Clayton result.SetStatus(eReturnStatusFailed); 85111eb9c64SZachary Turner return false; 85211eb9c64SZachary Turner } 85311eb9c64SZachary Turner 85497206d57SZachary Turner Status error; 8550d9a201eSRaphael Isemann auto name = command[0].ref(); 856a8f3ae7cSJonas Devlieghere m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>( 8574574a890SZachary Turner m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 8584574a890SZachary Turner true); 8590e5e5a79SGreg Clayton 860b9c1b51eSKate Stone if (argc == 1) { 86157179860SJonas Devlieghere Debugger &debugger = GetDebugger(); 862e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 86344d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 864b9c1b51eSKate Stone IOHandlerSP io_handler_sp(new IOHandlerEditline( 865b9c1b51eSKate Stone debugger, IOHandler::Type::Other, 86673d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 867514d8cd8SZachary Turner llvm::StringRef("> "), // Prompt 868514d8cd8SZachary Turner llvm::StringRef(), // Continuation prompt 869b9c1b51eSKate Stone multiple_lines, color_prompt, 870f6913cd7SGreg Clayton 0, // Don't show line numbers 871d77c2e09SJonas Devlieghere *this, nullptr)); 87244d93782SGreg Clayton 873b9c1b51eSKate Stone if (io_handler_sp) { 8747ce2de2cSJonas Devlieghere debugger.RunIOHandlerAsync(io_handler_sp); 875de164aaaSGreg Clayton result.SetStatus(eReturnStatusSuccessFinishNoResult); 876de164aaaSGreg Clayton } 877b9c1b51eSKate Stone } else { 87897d2c401SZachary Turner for (auto &entry : command.entries().drop_front()) { 87944d93782SGreg Clayton bool check_only = false; 8800d9a201eSRaphael Isemann error = AppendRegexSubstitution(entry.ref(), check_only); 8810e5e5a79SGreg Clayton if (error.Fail()) 8820e5e5a79SGreg Clayton break; 8830e5e5a79SGreg Clayton } 8840e5e5a79SGreg Clayton 885b9c1b51eSKate Stone if (error.Success()) { 8860e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 8870e5e5a79SGreg Clayton } 8880e5e5a79SGreg Clayton } 889b9c1b51eSKate Stone if (error.Fail()) { 8900e5e5a79SGreg Clayton result.AppendError(error.AsCString()); 891de164aaaSGreg Clayton result.SetStatus(eReturnStatusFailed); 892de164aaaSGreg Clayton } 8930e5e5a79SGreg Clayton 894de164aaaSGreg Clayton return result.Succeeded(); 895de164aaaSGreg Clayton } 896de164aaaSGreg Clayton 89797206d57SZachary Turner Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 898b9c1b51eSKate Stone bool check_only) { 89997206d57SZachary Turner Status error; 9000e5e5a79SGreg Clayton 901d5b44036SJonas Devlieghere if (!m_regex_cmd_up) { 902b9c1b51eSKate Stone error.SetErrorStringWithFormat( 903b9c1b51eSKate Stone "invalid regular expression command object for: '%.*s'", 904b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9050e5e5a79SGreg Clayton return error; 906de164aaaSGreg Clayton } 9070e5e5a79SGreg Clayton 9080e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 9090e5e5a79SGreg Clayton 910b9c1b51eSKate Stone if (regex_sed_size <= 1) { 911b9c1b51eSKate Stone error.SetErrorStringWithFormat( 912b9c1b51eSKate Stone "regular expression substitution string is too short: '%.*s'", 913b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9140e5e5a79SGreg Clayton return error; 9150e5e5a79SGreg Clayton } 9160e5e5a79SGreg Clayton 917b9c1b51eSKate Stone if (regex_sed[0] != 's') { 918b9c1b51eSKate Stone error.SetErrorStringWithFormat("regular expression substitution string " 919b9c1b51eSKate Stone "doesn't start with 's': '%.*s'", 920b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9210e5e5a79SGreg Clayton return error; 9220e5e5a79SGreg Clayton } 9230e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 92405097246SAdrian Prantl // use the char that follows 's' as the regex separator character so we can 92505097246SAdrian Prantl // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 9260e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 927b9c1b51eSKate Stone const size_t second_separator_char_pos = 928b9c1b51eSKate Stone regex_sed.find(separator_char, first_separator_char_pos + 1); 9290e5e5a79SGreg Clayton 930b9c1b51eSKate Stone if (second_separator_char_pos == std::string::npos) { 931b9c1b51eSKate Stone error.SetErrorStringWithFormat( 932b9c1b51eSKate Stone "missing second '%c' separator char after '%.*s' in '%.*s'", 9330e5e5a79SGreg Clayton separator_char, 9340e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 935ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 936b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9370e5e5a79SGreg Clayton return error; 9380e5e5a79SGreg Clayton } 9390e5e5a79SGreg Clayton 940b9c1b51eSKate Stone const size_t third_separator_char_pos = 941b9c1b51eSKate Stone regex_sed.find(separator_char, second_separator_char_pos + 1); 9420e5e5a79SGreg Clayton 943b9c1b51eSKate Stone if (third_separator_char_pos == std::string::npos) { 944b9c1b51eSKate Stone error.SetErrorStringWithFormat( 945b9c1b51eSKate Stone "missing third '%c' separator char after '%.*s' in '%.*s'", 9460e5e5a79SGreg Clayton separator_char, 9470e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 948ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 949b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9500e5e5a79SGreg Clayton return error; 9510e5e5a79SGreg Clayton } 9520e5e5a79SGreg Clayton 953b9c1b51eSKate Stone if (third_separator_char_pos != regex_sed_size - 1) { 95405097246SAdrian Prantl // Make sure that everything that follows the last regex separator char 955b9c1b51eSKate Stone if (regex_sed.find_first_not_of("\t\n\v\f\r ", 956b9c1b51eSKate Stone third_separator_char_pos + 1) != 957b9c1b51eSKate Stone std::string::npos) { 958b9c1b51eSKate Stone error.SetErrorStringWithFormat( 959b9c1b51eSKate Stone "extra data found after the '%.*s' regular expression substitution " 960b9c1b51eSKate Stone "string: '%.*s'", 961b9c1b51eSKate Stone (int)third_separator_char_pos + 1, regex_sed.data(), 9620e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 9630e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 9640e5e5a79SGreg Clayton return error; 9650e5e5a79SGreg Clayton } 966b9c1b51eSKate Stone } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 967b9c1b51eSKate Stone error.SetErrorStringWithFormat( 968b9c1b51eSKate Stone "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 969b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 9700e5e5a79SGreg Clayton regex_sed.data()); 9710e5e5a79SGreg Clayton return error; 972b9c1b51eSKate Stone } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 973b9c1b51eSKate Stone error.SetErrorStringWithFormat( 974b9c1b51eSKate Stone "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 975b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 9760e5e5a79SGreg Clayton regex_sed.data()); 9770e5e5a79SGreg Clayton return error; 9780e5e5a79SGreg Clayton } 97944d93782SGreg Clayton 980b9c1b51eSKate Stone if (!check_only) { 981adcd0268SBenjamin Kramer std::string regex(std::string(regex_sed.substr( 982adcd0268SBenjamin Kramer first_separator_char_pos + 1, 983adcd0268SBenjamin Kramer second_separator_char_pos - first_separator_char_pos - 1))); 984adcd0268SBenjamin Kramer std::string subst(std::string(regex_sed.substr( 985adcd0268SBenjamin Kramer second_separator_char_pos + 1, 986adcd0268SBenjamin Kramer third_separator_char_pos - second_separator_char_pos - 1))); 98743224195SRaphael Isemann m_regex_cmd_up->AddRegexCommand(regex, subst); 98844d93782SGreg Clayton } 9890e5e5a79SGreg Clayton return error; 990de164aaaSGreg Clayton } 991de164aaaSGreg Clayton 992b9c1b51eSKate Stone void AddRegexCommandToInterpreter() { 993d5b44036SJonas Devlieghere if (m_regex_cmd_up) { 994d5b44036SJonas Devlieghere if (m_regex_cmd_up->HasRegexEntries()) { 995d5b44036SJonas Devlieghere CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 996de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 997de164aaaSGreg Clayton } 998de164aaaSGreg Clayton } 999de164aaaSGreg Clayton } 1000de164aaaSGreg Clayton 1001de164aaaSGreg Clayton private: 1002d5b44036SJonas Devlieghere std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up; 1003de164aaaSGreg Clayton 1004b9c1b51eSKate Stone class CommandOptions : public Options { 1005de164aaaSGreg Clayton public: 1006b9c1b51eSKate Stone CommandOptions() : Options() {} 1007de164aaaSGreg Clayton 10086e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1009de164aaaSGreg Clayton 101097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1011b9c1b51eSKate Stone ExecutionContext *execution_context) override { 101297206d57SZachary Turner Status error; 10133bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1014de164aaaSGreg Clayton 1015b9c1b51eSKate Stone switch (short_option) { 1016de164aaaSGreg Clayton case 'h': 1017adcd0268SBenjamin Kramer m_help.assign(std::string(option_arg)); 1018de164aaaSGreg Clayton break; 1019de164aaaSGreg Clayton case 's': 1020adcd0268SBenjamin Kramer m_syntax.assign(std::string(option_arg)); 1021de164aaaSGreg Clayton break; 1022de164aaaSGreg Clayton default: 102336162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1024de164aaaSGreg Clayton } 1025de164aaaSGreg Clayton 1026de164aaaSGreg Clayton return error; 1027de164aaaSGreg Clayton } 1028de164aaaSGreg Clayton 1029b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1030de164aaaSGreg Clayton m_help.clear(); 1031de164aaaSGreg Clayton m_syntax.clear(); 1032de164aaaSGreg Clayton } 1033de164aaaSGreg Clayton 10341f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 103570602439SZachary Turner return llvm::makeArrayRef(g_regex_options); 10361f0f5b5bSZachary Turner } 1037de164aaaSGreg Clayton 1038daed98e5SShivam Mittal llvm::StringRef GetHelp() { return m_help; } 10396e3d8e7fSEugene Zelenko 1040daed98e5SShivam Mittal llvm::StringRef GetSyntax() { return m_syntax; } 10416e3d8e7fSEugene Zelenko 1042de164aaaSGreg Clayton protected: 10436e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 10446e3d8e7fSEugene Zelenko 1045de164aaaSGreg Clayton std::string m_help; 1046de164aaaSGreg Clayton std::string m_syntax; 1047de164aaaSGreg Clayton }; 1048de164aaaSGreg Clayton 1049b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1050de164aaaSGreg Clayton 10515a988416SJim Ingham CommandOptions m_options; 1052de164aaaSGreg Clayton }; 1053de164aaaSGreg Clayton 1054b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw { 1055223383edSEnrico Granata public: 1056b9c1b51eSKate Stone CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1057b9c1b51eSKate Stone std::string funct, std::string help, 1058b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1059a925974bSAdrian Prantl : CommandObjectRaw(interpreter, name), m_function_name(funct), 1060a925974bSAdrian Prantl m_synchro(synch), m_fetched_help_long(false) { 1061735152e3SEnrico Granata if (!help.empty()) 1062442f6530SZachary Turner SetHelp(help); 1063b9c1b51eSKate Stone else { 1064735152e3SEnrico Granata StreamString stream; 1065735152e3SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1066c156427dSZachary Turner SetHelp(stream.GetString()); 1067735152e3SEnrico Granata } 1068223383edSEnrico Granata } 1069223383edSEnrico Granata 10706e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1071223383edSEnrico Granata 1072b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 10735a988416SJim Ingham 1074b9c1b51eSKate Stone const std::string &GetFunctionName() { return m_function_name; } 10755a988416SJim Ingham 1076b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 10775a988416SJim Ingham 1078442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1079442f6530SZachary Turner if (m_fetched_help_long) 1080442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1081442f6530SZachary Turner 10822b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1083442f6530SZachary Turner if (!scripter) 1084442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1085442f6530SZachary Turner 1086fac939e9SEnrico Granata std::string docstring; 1087442f6530SZachary Turner m_fetched_help_long = 1088442f6530SZachary Turner scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1089fac939e9SEnrico Granata if (!docstring.empty()) 1090442f6530SZachary Turner SetHelpLong(docstring); 1091fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1092fac939e9SEnrico Granata } 1093fac939e9SEnrico Granata 10945a988416SJim Ingham protected: 10954d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 1096b9c1b51eSKate Stone CommandReturnObject &result) override { 10972b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1098223383edSEnrico Granata 109997206d57SZachary Turner Status error; 1100223383edSEnrico Granata 110170f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 110270f11f88SJim Ingham 1103a925974bSAdrian Prantl if (!scripter || !scripter->RunScriptBasedCommand( 1104a925974bSAdrian Prantl m_function_name.c_str(), raw_command_line, m_synchro, 1105a925974bSAdrian Prantl result, error, m_exe_ctx)) { 1106223383edSEnrico Granata result.AppendError(error.AsCString()); 1107223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1108b9c1b51eSKate Stone } else { 110970f11f88SJim Ingham // Don't change the status if the command already set it... 1110b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1111c156427dSZachary Turner if (result.GetOutputData().empty()) 1112223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 111370f11f88SJim Ingham else 111470f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 111570f11f88SJim Ingham } 111670f11f88SJim Ingham } 1117223383edSEnrico Granata 1118223383edSEnrico Granata return result.Succeeded(); 1119223383edSEnrico Granata } 1120223383edSEnrico Granata 11216e3d8e7fSEugene Zelenko private: 11226e3d8e7fSEugene Zelenko std::string m_function_name; 11236e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 11246e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1125223383edSEnrico Granata }; 1126223383edSEnrico Granata 1127b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw { 11289fe00e52SEnrico Granata public: 11299fe00e52SEnrico Granata CommandObjectScriptingObject(CommandInterpreter &interpreter, 11309fe00e52SEnrico Granata std::string name, 11310641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 1132b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1133a925974bSAdrian Prantl : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp), 1134a925974bSAdrian Prantl m_synchro(synch), m_fetched_help_short(false), 1135b9c1b51eSKate Stone m_fetched_help_long(false) { 11369fe00e52SEnrico Granata StreamString stream; 11379fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1138c156427dSZachary Turner SetHelp(stream.GetString()); 11392b29b432SJonas Devlieghere if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter()) 1140e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 11419fe00e52SEnrico Granata } 11429fe00e52SEnrico Granata 11436e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 11449fe00e52SEnrico Granata 1145b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 11469fe00e52SEnrico Granata 1147b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 11489fe00e52SEnrico Granata 1149442f6530SZachary Turner llvm::StringRef GetHelp() override { 1150442f6530SZachary Turner if (m_fetched_help_short) 1151442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 11522b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1153442f6530SZachary Turner if (!scripter) 1154442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 11556f79bb2dSEnrico Granata std::string docstring; 1156b9c1b51eSKate Stone m_fetched_help_short = 1157b9c1b51eSKate Stone scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 11586f79bb2dSEnrico Granata if (!docstring.empty()) 1159442f6530SZachary Turner SetHelp(docstring); 1160442f6530SZachary Turner 11616f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 11626f79bb2dSEnrico Granata } 11636f79bb2dSEnrico Granata 1164442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1165442f6530SZachary Turner if (m_fetched_help_long) 1166442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1167442f6530SZachary Turner 11682b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1169442f6530SZachary Turner if (!scripter) 1170442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1171442f6530SZachary Turner 11726f79bb2dSEnrico Granata std::string docstring; 1173b9c1b51eSKate Stone m_fetched_help_long = 1174b9c1b51eSKate Stone scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 11756f79bb2dSEnrico Granata if (!docstring.empty()) 1176442f6530SZachary Turner SetHelpLong(docstring); 11779fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 11789fe00e52SEnrico Granata } 11799fe00e52SEnrico Granata 11809fe00e52SEnrico Granata protected: 11814d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 1182b9c1b51eSKate Stone CommandReturnObject &result) override { 11832b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 11849fe00e52SEnrico Granata 118597206d57SZachary Turner Status error; 11869fe00e52SEnrico Granata 11879fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 11889fe00e52SEnrico Granata 1189b9c1b51eSKate Stone if (!scripter || 1190b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1191b9c1b51eSKate Stone m_synchro, result, error, m_exe_ctx)) { 11929fe00e52SEnrico Granata result.AppendError(error.AsCString()); 11939fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 1194b9c1b51eSKate Stone } else { 11959fe00e52SEnrico Granata // Don't change the status if the command already set it... 1196b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1197c156427dSZachary Turner if (result.GetOutputData().empty()) 11989fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 11999fe00e52SEnrico Granata else 12009fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 12019fe00e52SEnrico Granata } 12029fe00e52SEnrico Granata } 12039fe00e52SEnrico Granata 12049fe00e52SEnrico Granata return result.Succeeded(); 12059fe00e52SEnrico Granata } 12069fe00e52SEnrico Granata 12076e3d8e7fSEugene Zelenko private: 12086e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 12096e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 12106e3d8e7fSEugene Zelenko bool m_fetched_help_short : 1; 12116e3d8e7fSEugene Zelenko bool m_fetched_help_long : 1; 12129fe00e52SEnrico Granata }; 12139fe00e52SEnrico Granata 1214a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 121564becc11SRaphael Isemann #define LLDB_OPTIONS_script_import 121664becc11SRaphael Isemann #include "CommandOptions.inc" 12171f0f5b5bSZachary Turner 1218b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed { 12195a988416SJim Ingham public: 1220b9c1b51eSKate Stone CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1221b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script import", 1222b9c1b51eSKate Stone "Import a scripting module in LLDB.", nullptr), 1223b9c1b51eSKate Stone m_options() { 12245a988416SJim Ingham CommandArgumentEntry arg1; 12255a988416SJim Ingham CommandArgumentData cmd_arg; 12265a988416SJim Ingham 12275a988416SJim Ingham // Define the first (and only) variant of this arg. 12285a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 12293b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 12305a988416SJim Ingham 1231b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1232b9c1b51eSKate Stone // argument entry. 12335a988416SJim Ingham arg1.push_back(cmd_arg); 12345a988416SJim Ingham 12355a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 12365a988416SJim Ingham m_arguments.push_back(arg1); 12375a988416SJim Ingham } 12385a988416SJim Ingham 12396e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 12405a988416SJim Ingham 1241ae34ed2cSRaphael Isemann void 1242ae34ed2cSRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 12432443bbd4SRaphael Isemann OptionElementVector &opt_element_vector) override { 1244b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 1245b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1246a2e76c0bSRaphael Isemann request, nullptr); 12475a988416SJim Ingham } 12485a988416SJim Ingham 1249b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12505a988416SJim Ingham 12515a988416SJim Ingham protected: 1252b9c1b51eSKate Stone class CommandOptions : public Options { 12530a305db7SEnrico Granata public: 1254b9c1b51eSKate Stone CommandOptions() : Options() {} 12550a305db7SEnrico Granata 12566e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 12570a305db7SEnrico Granata 125897206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1259b9c1b51eSKate Stone ExecutionContext *execution_context) override { 126097206d57SZachary Turner Status error; 12613bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12620a305db7SEnrico Granata 1263b9c1b51eSKate Stone switch (short_option) { 12640a305db7SEnrico Granata case 'r': 126515625112SJonas Devlieghere // NO-OP 12660a305db7SEnrico Granata break; 126700bb397bSJonas Devlieghere case 'c': 126800bb397bSJonas Devlieghere relative_to_command_file = true; 126900bb397bSJonas Devlieghere break; 12700a305db7SEnrico Granata default: 127136162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12720a305db7SEnrico Granata } 12730a305db7SEnrico Granata 12740a305db7SEnrico Granata return error; 12750a305db7SEnrico Granata } 12760a305db7SEnrico Granata 1277b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 127800bb397bSJonas Devlieghere relative_to_command_file = false; 12790a305db7SEnrico Granata } 12800a305db7SEnrico Granata 12811f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 128270602439SZachary Turner return llvm::makeArrayRef(g_script_import_options); 12831f0f5b5bSZachary Turner } 128400bb397bSJonas Devlieghere bool relative_to_command_file = false; 12850a305db7SEnrico Granata }; 12860a305db7SEnrico Granata 1287b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 128811eb9c64SZachary Turner if (command.empty()) { 12893b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1290a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1291a9dbf432SEnrico Granata return false; 1292a9dbf432SEnrico Granata } 1293a9dbf432SEnrico Granata 129400bb397bSJonas Devlieghere FileSpec source_dir = {}; 129500bb397bSJonas Devlieghere if (m_options.relative_to_command_file) { 129600bb397bSJonas Devlieghere source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir(); 129700bb397bSJonas Devlieghere if (!source_dir) { 129800bb397bSJonas Devlieghere result.AppendError("command script import -c can only be specified " 129900bb397bSJonas Devlieghere "from a command file"); 130000bb397bSJonas Devlieghere result.SetStatus(eReturnStatusFailed); 130100bb397bSJonas Devlieghere return false; 130200bb397bSJonas Devlieghere } 130300bb397bSJonas Devlieghere } 130400bb397bSJonas Devlieghere 130511eb9c64SZachary Turner for (auto &entry : command.entries()) { 130697206d57SZachary Turner Status error; 1307a9dbf432SEnrico Granata 1308c9d645d3SGreg Clayton const bool init_session = true; 1309b9c1b51eSKate Stone // FIXME: this is necessary because CommandObject::CheckRequirements() 131011eb9c64SZachary Turner // assumes that commands won't ever be recursively invoked, but it's 131111eb9c64SZachary Turner // actually possible to craft a Python script that does other "command 131205097246SAdrian Prantl // script imports" in __lldb_init_module the real fix is to have 131305097246SAdrian Prantl // recursive commands possible with a CommandInvocation object separate 131405097246SAdrian Prantl // from the CommandObject itself, so that recursive command invocations 131505097246SAdrian Prantl // won't stomp on each other (wrt to execution contents, options, and 131605097246SAdrian Prantl // more) 1317078551c7SEnrico Granata m_exe_ctx.Clear(); 13182b29b432SJonas Devlieghere if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule( 131900bb397bSJonas Devlieghere entry.c_str(), init_session, error, nullptr, source_dir)) { 1320a9dbf432SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1321b9c1b51eSKate Stone } else { 1322b9c1b51eSKate Stone result.AppendErrorWithFormat("module importing failed: %s", 1323b9c1b51eSKate Stone error.AsCString()); 1324a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1325a9dbf432SEnrico Granata } 13263b00e35bSEnrico Granata } 1327a9dbf432SEnrico Granata 1328a9dbf432SEnrico Granata return result.Succeeded(); 1329a9dbf432SEnrico Granata } 13300a305db7SEnrico Granata 13315a988416SJim Ingham CommandOptions m_options; 1332a9dbf432SEnrico Granata }; 1333223383edSEnrico Granata 1334223383edSEnrico Granata // CommandObjectCommandsScriptAdd 13358fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_script_synchro_type[] = { 1336e063ecccSJonas Devlieghere { 1337e063ecccSJonas Devlieghere eScriptedCommandSynchronicitySynchronous, 1338e063ecccSJonas Devlieghere "synchronous", 1339e063ecccSJonas Devlieghere "Run synchronous", 1340e063ecccSJonas Devlieghere }, 1341e063ecccSJonas Devlieghere { 1342e063ecccSJonas Devlieghere eScriptedCommandSynchronicityAsynchronous, 1343e063ecccSJonas Devlieghere "asynchronous", 1344e063ecccSJonas Devlieghere "Run asynchronous", 1345e063ecccSJonas Devlieghere }, 1346e063ecccSJonas Devlieghere { 1347e063ecccSJonas Devlieghere eScriptedCommandSynchronicityCurrentValue, 1348e063ecccSJonas Devlieghere "current", 1349e063ecccSJonas Devlieghere "Do not alter current setting", 1350e063ecccSJonas Devlieghere }, 1351e063ecccSJonas Devlieghere }; 13521f0f5b5bSZachary Turner 13538fe53c49STatyana Krasnukha static constexpr OptionEnumValues ScriptSynchroType() { 13548fe53c49STatyana Krasnukha return OptionEnumValues(g_script_synchro_type); 13558fe53c49STatyana Krasnukha } 13568fe53c49STatyana Krasnukha 135764becc11SRaphael Isemann #define LLDB_OPTIONS_script_add 135864becc11SRaphael Isemann #include "CommandOptions.inc" 13591f0f5b5bSZachary Turner 1360b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1361b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 13625a988416SJim Ingham public: 1363b9c1b51eSKate Stone CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1364b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script add", 13655a988416SJim Ingham "Add a scripted function as an LLDB command.", 13666e3d8e7fSEugene Zelenko nullptr), 1367b9c1b51eSKate Stone IOHandlerDelegateMultiline("DONE"), m_options() { 13685a988416SJim Ingham CommandArgumentEntry arg1; 13695a988416SJim Ingham CommandArgumentData cmd_arg; 13705a988416SJim Ingham 13715a988416SJim Ingham // Define the first (and only) variant of this arg. 13725a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 13735a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 13745a988416SJim Ingham 1375b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1376b9c1b51eSKate Stone // argument entry. 13775a988416SJim Ingham arg1.push_back(cmd_arg); 13785a988416SJim Ingham 13795a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 13805a988416SJim Ingham m_arguments.push_back(arg1); 13815a988416SJim Ingham } 13825a988416SJim Ingham 13836e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 13845a988416SJim Ingham 1385b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 13865a988416SJim Ingham 13875a988416SJim Ingham protected: 1388b9c1b51eSKate Stone class CommandOptions : public Options { 1389223383edSEnrico Granata public: 1390b9c1b51eSKate Stone CommandOptions() 1391b9c1b51eSKate Stone : Options(), m_class_name(), m_funct_name(), m_short_help(), 1392b9c1b51eSKate Stone m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} 1393223383edSEnrico Granata 13946e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1395223383edSEnrico Granata 139697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1397b9c1b51eSKate Stone ExecutionContext *execution_context) override { 139897206d57SZachary Turner Status error; 13993bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1400223383edSEnrico Granata 1401b9c1b51eSKate Stone switch (short_option) { 1402223383edSEnrico Granata case 'f': 1403fe11483bSZachary Turner if (!option_arg.empty()) 1404adcd0268SBenjamin Kramer m_funct_name = std::string(option_arg); 1405735152e3SEnrico Granata break; 14069fe00e52SEnrico Granata case 'c': 1407fe11483bSZachary Turner if (!option_arg.empty()) 1408adcd0268SBenjamin Kramer m_class_name = std::string(option_arg); 14099fe00e52SEnrico Granata break; 1410735152e3SEnrico Granata case 'h': 1411fe11483bSZachary Turner if (!option_arg.empty()) 1412adcd0268SBenjamin Kramer m_short_help = std::string(option_arg); 1413223383edSEnrico Granata break; 14140a305db7SEnrico Granata case 's': 1415b9c1b51eSKate Stone m_synchronicity = 141647cbf4a0SPavel Labath (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum( 1417fe11483bSZachary Turner option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 14180a305db7SEnrico Granata if (!error.Success()) 1419b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1420fe11483bSZachary Turner "unrecognized value for synchronicity '%s'", 1421fe11483bSZachary Turner option_arg.str().c_str()); 14220a305db7SEnrico Granata break; 1423223383edSEnrico Granata default: 142436162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1425223383edSEnrico Granata } 1426223383edSEnrico Granata 1427223383edSEnrico Granata return error; 1428223383edSEnrico Granata } 1429223383edSEnrico Granata 1430b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 14319fe00e52SEnrico Granata m_class_name.clear(); 1432735152e3SEnrico Granata m_funct_name.clear(); 1433735152e3SEnrico Granata m_short_help.clear(); 143444d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1435223383edSEnrico Granata } 1436223383edSEnrico Granata 14371f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 143870602439SZachary Turner return llvm::makeArrayRef(g_script_add_options); 14391f0f5b5bSZachary Turner } 1440223383edSEnrico Granata 1441223383edSEnrico Granata // Instance variables to hold the values for command options. 1442223383edSEnrico Granata 14439fe00e52SEnrico Granata std::string m_class_name; 1444223383edSEnrico Granata std::string m_funct_name; 1445735152e3SEnrico Granata std::string m_short_help; 144644d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1447223383edSEnrico Granata }; 1448223383edSEnrico Granata 14490affb582SDave Lee void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 14507ca15ba7SLawrence D'Anna StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 14510affb582SDave Lee if (output_sp && interactive) { 145244d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 145344d93782SGreg Clayton output_sp->Flush(); 1454223383edSEnrico Granata } 1455223383edSEnrico Granata } 1456223383edSEnrico Granata 1457b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1458b9c1b51eSKate Stone std::string &data) override { 14597ca15ba7SLawrence D'Anna StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 146044d93782SGreg Clayton 14612b29b432SJonas Devlieghere ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1462b9c1b51eSKate Stone if (interpreter) { 146344d93782SGreg Clayton 146444d93782SGreg Clayton StringList lines; 146544d93782SGreg Clayton lines.SplitIntoLines(data); 1466b9c1b51eSKate Stone if (lines.GetSize() > 0) { 1467a73b7df7SEnrico Granata std::string funct_name_str; 1468b9c1b51eSKate Stone if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1469b9c1b51eSKate Stone if (funct_name_str.empty()) { 1470b9c1b51eSKate Stone error_sp->Printf("error: unable to obtain a function name, didn't " 1471b9c1b51eSKate Stone "add python command.\n"); 147244d93782SGreg Clayton error_sp->Flush(); 1473b9c1b51eSKate Stone } else { 1474223383edSEnrico Granata // everything should be fine now, let's add this alias 1475223383edSEnrico Granata 1476b9c1b51eSKate Stone CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1477771ef6d4SMalcolm Parsons m_interpreter, m_cmd_name, funct_name_str, m_short_help, 147844d93782SGreg Clayton m_synchronicity)); 1479223383edSEnrico Granata 1480b9c1b51eSKate Stone if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1481b9c1b51eSKate Stone true)) { 1482b9c1b51eSKate Stone error_sp->Printf("error: unable to add selected command, didn't " 1483b9c1b51eSKate Stone "add python command.\n"); 148444d93782SGreg Clayton error_sp->Flush(); 1485223383edSEnrico Granata } 1486223383edSEnrico Granata } 1487b9c1b51eSKate Stone } else { 1488b9c1b51eSKate Stone error_sp->Printf( 1489b9c1b51eSKate Stone "error: unable to create function, didn't add python command.\n"); 149044d93782SGreg Clayton error_sp->Flush(); 149144d93782SGreg Clayton } 1492b9c1b51eSKate Stone } else { 149344d93782SGreg Clayton error_sp->Printf("error: empty function, didn't add python command.\n"); 149444d93782SGreg Clayton error_sp->Flush(); 149544d93782SGreg Clayton } 1496b9c1b51eSKate Stone } else { 1497b9c1b51eSKate Stone error_sp->Printf( 1498b9c1b51eSKate Stone "error: script interpreter missing, didn't add python command.\n"); 149944d93782SGreg Clayton error_sp->Flush(); 150044d93782SGreg Clayton } 150144d93782SGreg Clayton 150244d93782SGreg Clayton io_handler.SetIsDone(true); 150344d93782SGreg Clayton } 1504223383edSEnrico Granata 1505b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 150657179860SJonas Devlieghere if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { 1507b9c1b51eSKate Stone result.AppendError("only scripting language supported for scripted " 1508b9c1b51eSKate Stone "commands is currently Python"); 150999f0b8f9SEnrico Granata result.SetStatus(eReturnStatusFailed); 151099f0b8f9SEnrico Granata return false; 151199f0b8f9SEnrico Granata } 151299f0b8f9SEnrico Granata 151311eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1514223383edSEnrico Granata result.AppendError("'command script add' requires one argument"); 1515223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1516223383edSEnrico Granata return false; 1517223383edSEnrico Granata } 1518223383edSEnrico Granata 1519735152e3SEnrico Granata // Store the options in case we get multi-line input 1520adcd0268SBenjamin Kramer m_cmd_name = std::string(command[0].ref()); 1521735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 152244d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 1523223383edSEnrico Granata 1524b9c1b51eSKate Stone if (m_options.m_class_name.empty()) { 1525b9c1b51eSKate Stone if (m_options.m_funct_name.empty()) { 1526b9c1b51eSKate Stone m_interpreter.GetPythonCommandsFromIOHandler( 1527b9c1b51eSKate Stone " ", // Prompt 1528a6faf851SJonas Devlieghere *this); // IOHandlerDelegate 1529b9c1b51eSKate Stone } else { 1530b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1531b9c1b51eSKate Stone m_interpreter, m_cmd_name, m_options.m_funct_name, 1532b9c1b51eSKate Stone m_options.m_short_help, m_synchronicity)); 1533b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1534223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1535b9c1b51eSKate Stone } else { 1536223383edSEnrico Granata result.AppendError("cannot add command"); 1537223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1538223383edSEnrico Granata } 1539223383edSEnrico Granata } 1540b9c1b51eSKate Stone } else { 15412b29b432SJonas Devlieghere ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1542b9c1b51eSKate Stone if (!interpreter) { 15439fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 15449fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 15459fe00e52SEnrico Granata return false; 15469fe00e52SEnrico Granata } 15479fe00e52SEnrico Granata 1548b9c1b51eSKate Stone auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1549b9c1b51eSKate Stone m_options.m_class_name.c_str()); 1550b9c1b51eSKate Stone if (!cmd_obj_sp) { 15519fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 15529fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 15539fe00e52SEnrico Granata return false; 15549fe00e52SEnrico Granata } 15559fe00e52SEnrico Granata 1556b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1557b9c1b51eSKate Stone m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1558b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 15599fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1560b9c1b51eSKate Stone } else { 15619fe00e52SEnrico Granata result.AppendError("cannot add command"); 15629fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 15639fe00e52SEnrico Granata } 15649fe00e52SEnrico Granata } 1565223383edSEnrico Granata 1566223383edSEnrico Granata return result.Succeeded(); 1567223383edSEnrico Granata } 15685a988416SJim Ingham 15695a988416SJim Ingham CommandOptions m_options; 157044d93782SGreg Clayton std::string m_cmd_name; 1571735152e3SEnrico Granata std::string m_short_help; 157244d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1573223383edSEnrico Granata }; 1574223383edSEnrico Granata 1575223383edSEnrico Granata // CommandObjectCommandsScriptList 1576223383edSEnrico Granata 1577b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed { 1578223383edSEnrico Granata public: 1579b9c1b51eSKate Stone CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1580b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script list", 1581b9c1b51eSKate Stone "List defined scripted commands.", nullptr) {} 1582223383edSEnrico Granata 15836e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 1584223383edSEnrico Granata 1585b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1586d77ea5b2SRaphael Isemann if (command.GetArgumentCount() != 0) { 1587d77ea5b2SRaphael Isemann result.AppendError("'command script list' doesn't take any arguments"); 1588d77ea5b2SRaphael Isemann result.SetStatus(eReturnStatusFailed); 1589d77ea5b2SRaphael Isemann return false; 1590d77ea5b2SRaphael Isemann } 1591d77ea5b2SRaphael Isemann 1592b9c1b51eSKate Stone m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1593223383edSEnrico Granata 1594223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1595223383edSEnrico Granata 1596223383edSEnrico Granata return true; 1597223383edSEnrico Granata } 1598223383edSEnrico Granata }; 1599223383edSEnrico Granata 1600223383edSEnrico Granata // CommandObjectCommandsScriptClear 1601223383edSEnrico Granata 1602b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1603223383edSEnrico Granata public: 1604b9c1b51eSKate Stone CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1605b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script clear", 1606b9c1b51eSKate Stone "Delete all scripted commands.", nullptr) {} 1607223383edSEnrico Granata 16086e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 1609223383edSEnrico Granata 16105a988416SJim Ingham protected: 1611b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1612d77ea5b2SRaphael Isemann if (command.GetArgumentCount() != 0) { 1613d77ea5b2SRaphael Isemann result.AppendError("'command script clear' doesn't take any arguments"); 1614d77ea5b2SRaphael Isemann result.SetStatus(eReturnStatusFailed); 1615d77ea5b2SRaphael Isemann return false; 1616d77ea5b2SRaphael Isemann } 1617d77ea5b2SRaphael Isemann 1618223383edSEnrico Granata m_interpreter.RemoveAllUser(); 1619223383edSEnrico Granata 1620223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1621223383edSEnrico Granata 1622223383edSEnrico Granata return true; 1623223383edSEnrico Granata } 1624223383edSEnrico Granata }; 1625223383edSEnrico Granata 1626223383edSEnrico Granata // CommandObjectCommandsScriptDelete 1627223383edSEnrico Granata 1628b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1629223383edSEnrico Granata public: 1630b9c1b51eSKate Stone CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1631b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script delete", 1632b9c1b51eSKate Stone "Delete a scripted command.", nullptr) { 1633223383edSEnrico Granata CommandArgumentEntry arg1; 1634223383edSEnrico Granata CommandArgumentData cmd_arg; 1635223383edSEnrico Granata 1636223383edSEnrico Granata // Define the first (and only) variant of this arg. 1637223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 1638223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 1639223383edSEnrico Granata 1640b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1641b9c1b51eSKate Stone // argument entry. 1642223383edSEnrico Granata arg1.push_back(cmd_arg); 1643223383edSEnrico Granata 1644223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 1645223383edSEnrico Granata m_arguments.push_back(arg1); 1646223383edSEnrico Granata } 1647223383edSEnrico Granata 16486e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 1649223383edSEnrico Granata 16502e8f304fSGongyu Deng void 16512e8f304fSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 16522e8f304fSGongyu Deng OptionElementVector &opt_element_vector) override { 16532e8f304fSGongyu Deng if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 16542e8f304fSGongyu Deng return; 16552e8f304fSGongyu Deng 16562ebe30c6SRaphael Isemann for (const auto &c : m_interpreter.GetUserCommands()) 16572ebe30c6SRaphael Isemann request.TryCompleteCurrentArg(c.first, c.second->GetHelp()); 16582e8f304fSGongyu Deng } 16592e8f304fSGongyu Deng 16605a988416SJim Ingham protected: 1661b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1662223383edSEnrico Granata 166311eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1664223383edSEnrico Granata result.AppendError("'command script delete' requires one argument"); 1665223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1666223383edSEnrico Granata return false; 1667223383edSEnrico Granata } 1668223383edSEnrico Granata 16690d9a201eSRaphael Isemann auto cmd_name = command[0].ref(); 1670223383edSEnrico Granata 16714574a890SZachary Turner if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 16724574a890SZachary Turner !m_interpreter.UserCommandExists(cmd_name)) { 1673867e7d17SZachary Turner result.AppendErrorWithFormat("command %s not found", command[0].c_str()); 1674223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 16754574a890SZachary Turner return false; 1676223383edSEnrico Granata } 1677223383edSEnrico Granata 16784574a890SZachary Turner m_interpreter.RemoveUser(cmd_name); 16794574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishResult); 16804574a890SZachary Turner return true; 1681223383edSEnrico Granata } 1682223383edSEnrico Granata }; 1683223383edSEnrico Granata 1684223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 1685223383edSEnrico Granata 1686223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 1687223383edSEnrico Granata 1688b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1689223383edSEnrico Granata public: 16907428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1691b9c1b51eSKate Stone : CommandObjectMultiword( 1692a925974bSAdrian Prantl interpreter, "command script", 1693a925974bSAdrian Prantl "Commands for managing custom " 1694b9c1b51eSKate Stone "commands implemented by " 1695b9c1b51eSKate Stone "interpreter scripts.", 1696b9c1b51eSKate Stone "command script <subcommand> [<subcommand-options>]") { 1697b9c1b51eSKate Stone LoadSubCommand("add", CommandObjectSP( 1698b9c1b51eSKate Stone new CommandObjectCommandsScriptAdd(interpreter))); 1699b9c1b51eSKate Stone LoadSubCommand( 1700b9c1b51eSKate Stone "delete", 1701b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1702b9c1b51eSKate Stone LoadSubCommand( 1703b9c1b51eSKate Stone "clear", 1704b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1705b9c1b51eSKate Stone LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1706b9c1b51eSKate Stone interpreter))); 1707b9c1b51eSKate Stone LoadSubCommand( 1708b9c1b51eSKate Stone "import", 1709b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1710223383edSEnrico Granata } 1711223383edSEnrico Granata 17126e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 1713223383edSEnrico Granata }; 1714223383edSEnrico Granata 1715ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1716ebc09c36SJim Ingham 1717ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1718ebc09c36SJim Ingham 1719b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1720b9c1b51eSKate Stone CommandInterpreter &interpreter) 1721b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "command", 1722b9c1b51eSKate Stone "Commands for managing custom LLDB commands.", 1723b9c1b51eSKate Stone "command <subcommand> [<subcommand-options>]") { 1724b9c1b51eSKate Stone LoadSubCommand("source", 1725b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1726b9c1b51eSKate Stone LoadSubCommand("alias", 1727b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1728b9c1b51eSKate Stone LoadSubCommand("unalias", CommandObjectSP( 1729b9c1b51eSKate Stone new CommandObjectCommandsUnalias(interpreter))); 1730b9c1b51eSKate Stone LoadSubCommand("delete", 1731b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1732b9c1b51eSKate Stone LoadSubCommand( 1733b9c1b51eSKate Stone "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1734b9c1b51eSKate Stone LoadSubCommand( 1735b9c1b51eSKate Stone "script", 1736b9c1b51eSKate Stone CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1737ebc09c36SJim Ingham } 1738ebc09c36SJim Ingham 17396e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1740