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 13836de94cfSTatyana 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 } 159122a4ebdSPavel Labath } 16036de94cfSTatyana Krasnukha 16136de94cfSTatyana 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 = 459a9448872SJonas Devlieghere m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName())) { 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 = 553a9448872SJonas Devlieghere m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName()); 554ebc09c36SJim Ingham if (use_subcommand) 555a9448872SJonas Devlieghere tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName()); 556ca90c47eSCaroline Tice 557ca90c47eSCaroline Tice args.GetCommandString(args_string); 558867b185dSCaroline Tice } 559ebc09c36SJim Ingham 560771ef6d4SMalcolm Parsons if (m_interpreter.AliasExists(alias_command) || 561771ef6d4SMalcolm Parsons m_interpreter.UserCommandExists(alias_command)) { 562b9c1b51eSKate Stone result.AppendWarningWithFormat( 5634574a890SZachary Turner "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 564ebc09c36SJim Ingham } 565ebc09c36SJim Ingham 566b9c1b51eSKate Stone if (CommandAlias *alias = m_interpreter.AddAlias( 5674574a890SZachary Turner alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 568771ef6d4SMalcolm Parsons args_string)) { 56945d0e238SEnrico Granata if (m_command_options.m_help.OptionWasSet()) 57045d0e238SEnrico Granata alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 57145d0e238SEnrico Granata if (m_command_options.m_long_help.OptionWasSet()) 57245d0e238SEnrico Granata alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 573ebc09c36SJim Ingham result.SetStatus(eReturnStatusSuccessFinishNoResult); 574b9c1b51eSKate Stone } else { 575212130acSEnrico Granata result.AppendError("Unable to create requested alias.\n"); 576212130acSEnrico Granata result.SetStatus(eReturnStatusFailed); 577212130acSEnrico Granata return false; 578212130acSEnrico Granata } 579ebc09c36SJim Ingham 580ebc09c36SJim Ingham return result.Succeeded(); 581ebc09c36SJim Ingham } 582ebc09c36SJim Ingham }; 583ebc09c36SJim Ingham 584ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias 585ebc09c36SJim Ingham // CommandObjectCommandsUnalias 586ebc09c36SJim Ingham 587b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed { 588ebc09c36SJim Ingham public: 5897428a18cSKate Stone CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 590b9c1b51eSKate Stone : CommandObjectParsed( 591b9c1b51eSKate Stone interpreter, "command unalias", 592b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command alias'.", 593b9c1b51eSKate Stone nullptr) { 594405fe67fSCaroline Tice CommandArgumentEntry arg; 595405fe67fSCaroline Tice CommandArgumentData alias_arg; 596405fe67fSCaroline Tice 597405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 598405fe67fSCaroline Tice alias_arg.arg_type = eArgTypeAliasName; 599405fe67fSCaroline Tice alias_arg.arg_repetition = eArgRepeatPlain; 600405fe67fSCaroline Tice 601b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 602b9c1b51eSKate Stone // argument entry. 603405fe67fSCaroline Tice arg.push_back(alias_arg); 604405fe67fSCaroline Tice 605405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 606405fe67fSCaroline Tice m_arguments.push_back(arg); 607ebc09c36SJim Ingham } 608ebc09c36SJim Ingham 6096e3d8e7fSEugene Zelenko ~CommandObjectCommandsUnalias() override = default; 610ebc09c36SJim Ingham 61131fd64acSGongyu Deng void 61231fd64acSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 61331fd64acSGongyu Deng OptionElementVector &opt_element_vector) override { 61431fd64acSGongyu Deng if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 61531fd64acSGongyu Deng return; 61631fd64acSGongyu Deng 61731fd64acSGongyu Deng for (const auto &ent : m_interpreter.GetAliases()) { 61831fd64acSGongyu Deng request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp()); 61931fd64acSGongyu Deng } 62031fd64acSGongyu Deng } 62131fd64acSGongyu Deng 6225a988416SJim Ingham protected: 623b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 624ebc09c36SJim Ingham CommandObject::CommandMap::iterator pos; 625ebc09c36SJim Ingham CommandObject *cmd_obj; 626ebc09c36SJim Ingham 62711eb9c64SZachary Turner if (args.empty()) { 62811eb9c64SZachary Turner result.AppendError("must call 'unalias' with a valid alias"); 62911eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 63011eb9c64SZachary Turner return false; 63111eb9c64SZachary Turner } 63211eb9c64SZachary Turner 6330d9a201eSRaphael Isemann auto command_name = args[0].ref(); 634a7015092SGreg Clayton cmd_obj = m_interpreter.GetCommandObject(command_name); 6354574a890SZachary Turner if (!cmd_obj) { 6364574a890SZachary Turner result.AppendErrorWithFormat( 6374574a890SZachary Turner "'%s' is not a known command.\nTry 'help' to see a " 6384574a890SZachary Turner "current list of commands.\n", 639867e7d17SZachary Turner args[0].c_str()); 6404574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 6414574a890SZachary Turner return false; 6424574a890SZachary Turner } 6434574a890SZachary Turner 644b9c1b51eSKate Stone if (m_interpreter.CommandExists(command_name)) { 645b9c1b51eSKate Stone if (cmd_obj->IsRemovable()) { 646b9c1b51eSKate Stone result.AppendErrorWithFormat( 647b9c1b51eSKate Stone "'%s' is not an alias, it is a debugger command which can be " 648b9c1b51eSKate Stone "removed using the 'command delete' command.\n", 649867e7d17SZachary Turner args[0].c_str()); 650b9c1b51eSKate Stone } else { 651b9c1b51eSKate Stone result.AppendErrorWithFormat( 652b9c1b51eSKate Stone "'%s' is a permanent debugger command and cannot be removed.\n", 653867e7d17SZachary Turner args[0].c_str()); 654b547278cSGreg Clayton } 655ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 6564574a890SZachary Turner return false; 6574574a890SZachary Turner } 6584574a890SZachary Turner 659b9c1b51eSKate Stone if (!m_interpreter.RemoveAlias(command_name)) { 660a7015092SGreg Clayton if (m_interpreter.AliasExists(command_name)) 661b9c1b51eSKate Stone result.AppendErrorWithFormat( 662867e7d17SZachary Turner "Error occurred while attempting to unalias '%s'.\n", 663867e7d17SZachary Turner args[0].c_str()); 664ebc09c36SJim Ingham else 665b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 666867e7d17SZachary Turner args[0].c_str()); 667ebc09c36SJim Ingham result.SetStatus(eReturnStatusFailed); 6684574a890SZachary Turner return false; 669ebc09c36SJim Ingham } 670ebc09c36SJim Ingham 6714574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 672ebc09c36SJim Ingham return result.Succeeded(); 673ebc09c36SJim Ingham } 674ebc09c36SJim Ingham }; 675ebc09c36SJim Ingham 676b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete 677b547278cSGreg Clayton // CommandObjectCommandsDelete 678b547278cSGreg Clayton 679b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed { 680b547278cSGreg Clayton public: 6817428a18cSKate Stone CommandObjectCommandsDelete(CommandInterpreter &interpreter) 682b9c1b51eSKate Stone : CommandObjectParsed( 683b9c1b51eSKate Stone interpreter, "command delete", 684b9c1b51eSKate Stone "Delete one or more custom commands defined by 'command regex'.", 685b9c1b51eSKate Stone nullptr) { 686b547278cSGreg Clayton CommandArgumentEntry arg; 687b547278cSGreg Clayton CommandArgumentData alias_arg; 688b547278cSGreg Clayton 689b547278cSGreg Clayton // Define the first (and only) variant of this arg. 690b547278cSGreg Clayton alias_arg.arg_type = eArgTypeCommandName; 691b547278cSGreg Clayton alias_arg.arg_repetition = eArgRepeatPlain; 692b547278cSGreg Clayton 693b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 694b9c1b51eSKate Stone // argument entry. 695b547278cSGreg Clayton arg.push_back(alias_arg); 696b547278cSGreg Clayton 697b547278cSGreg Clayton // Push the data for the first argument into the m_arguments vector. 698b547278cSGreg Clayton m_arguments.push_back(arg); 699b547278cSGreg Clayton } 700b547278cSGreg Clayton 7016e3d8e7fSEugene Zelenko ~CommandObjectCommandsDelete() override = default; 702b547278cSGreg Clayton 70331fd64acSGongyu Deng void 70431fd64acSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 70531fd64acSGongyu Deng OptionElementVector &opt_element_vector) override { 70631fd64acSGongyu Deng if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 70731fd64acSGongyu Deng return; 70831fd64acSGongyu Deng 70931fd64acSGongyu Deng for (const auto &ent : m_interpreter.GetCommands()) { 71031fd64acSGongyu Deng if (ent.second->IsRemovable()) 71131fd64acSGongyu Deng request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp()); 71231fd64acSGongyu Deng } 71331fd64acSGongyu Deng } 71431fd64acSGongyu Deng 715b547278cSGreg Clayton protected: 716b9c1b51eSKate Stone bool DoExecute(Args &args, CommandReturnObject &result) override { 717b547278cSGreg Clayton CommandObject::CommandMap::iterator pos; 718b547278cSGreg Clayton 71911eb9c64SZachary Turner if (args.empty()) { 72011eb9c64SZachary Turner result.AppendErrorWithFormat("must call '%s' with one or more valid user " 72111eb9c64SZachary Turner "defined regular expression command names", 722a449698cSZachary Turner GetCommandName().str().c_str()); 72311eb9c64SZachary Turner result.SetStatus(eReturnStatusFailed); 724d77ea5b2SRaphael Isemann return false; 72511eb9c64SZachary Turner } 72611eb9c64SZachary Turner 7270d9a201eSRaphael Isemann auto command_name = args[0].ref(); 7284574a890SZachary Turner if (!m_interpreter.CommandExists(command_name)) { 72946d4aa21SEnrico Granata StreamString error_msg_stream; 730d5b44036SJonas Devlieghere const bool generate_upropos = true; 73146d4aa21SEnrico Granata const bool generate_type_lookup = false; 732b9c1b51eSKate Stone CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 7334574a890SZachary Turner &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 734d5b44036SJonas Devlieghere generate_upropos, generate_type_lookup); 735c156427dSZachary Turner result.AppendError(error_msg_stream.GetString()); 736b547278cSGreg Clayton result.SetStatus(eReturnStatusFailed); 7374574a890SZachary Turner return false; 738b547278cSGreg Clayton } 739b547278cSGreg Clayton 7404574a890SZachary Turner if (!m_interpreter.RemoveCommand(command_name)) { 7414574a890SZachary Turner result.AppendErrorWithFormat( 7424574a890SZachary Turner "'%s' is a permanent debugger command and cannot be removed.\n", 743867e7d17SZachary Turner args[0].c_str()); 7444574a890SZachary Turner result.SetStatus(eReturnStatusFailed); 7454574a890SZachary Turner return false; 7464574a890SZachary Turner } 7474574a890SZachary Turner 7484574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishNoResult); 7494574a890SZachary Turner return true; 750b547278cSGreg Clayton } 751b547278cSGreg Clayton }; 752b547278cSGreg Clayton 753de164aaaSGreg Clayton // CommandObjectCommandsAddRegex 7541f0f5b5bSZachary Turner 75564becc11SRaphael Isemann #define LLDB_OPTIONS_regex 75664becc11SRaphael Isemann #include "CommandOptions.inc" 7571f0f5b5bSZachary Turner 7585a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex 759de164aaaSGreg Clayton 760b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed, 761b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 762de164aaaSGreg Clayton public: 7637428a18cSKate Stone CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 764b9c1b51eSKate Stone : CommandObjectParsed( 765a925974bSAdrian Prantl interpreter, "command regex", 766a925974bSAdrian Prantl "Define a custom command in terms of " 767b9c1b51eSKate Stone "existing commands by matching " 768b9c1b51eSKate Stone "regular expressions.", 7690e5e5a79SGreg Clayton "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 770b9c1b51eSKate Stone IOHandlerDelegateMultiline("", 771b9c1b51eSKate Stone IOHandlerDelegate::Completion::LLDBCommand), 772b9c1b51eSKate Stone m_options() { 773b9c1b51eSKate Stone SetHelpLong( 774b9c1b51eSKate Stone R"( 775b9c1b51eSKate Stone )" 776b9c1b51eSKate Stone "This command allows the user to create powerful regular expression commands \ 777ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \ 778b9c1b51eSKate Stone using the regular expression substitution format of:" 779b9c1b51eSKate Stone R"( 780ea671fbdSKate Stone 781ea671fbdSKate Stone s/<regex>/<subst>/ 782ea671fbdSKate Stone 783b9c1b51eSKate Stone )" 784b9c1b51eSKate Stone "<regex> is a regular expression that can use parenthesis to capture regular \ 785ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \ 786b9c1b51eSKate Stone for the first match, %2 for the second, and so on." 787b9c1b51eSKate Stone R"( 788ea671fbdSKate Stone 789b9c1b51eSKate Stone )" 790b9c1b51eSKate Stone "The regular expressions can all be specified on the command line if more than \ 791ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \ 792ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \ 793b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition." 794b9c1b51eSKate Stone R"( 795ea671fbdSKate Stone 796ea671fbdSKate Stone EXAMPLES 797ea671fbdSKate Stone 798b9c1b51eSKate Stone )" 799b9c1b51eSKate Stone "The following example will define a regular expression command named 'f' that \ 800ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 801b9c1b51eSKate Stone a number follows 'f':" 802b9c1b51eSKate Stone R"( 803ea671fbdSKate Stone 804b9c1b51eSKate Stone (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 805de164aaaSGreg Clayton } 806de164aaaSGreg Clayton 8076e3d8e7fSEugene Zelenko ~CommandObjectCommandsAddRegex() override = default; 808de164aaaSGreg Clayton 8095a988416SJim Ingham protected: 8100affb582SDave Lee void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 8117ca15ba7SLawrence D'Anna StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 8120affb582SDave Lee if (output_sp && interactive) { 8130affb582SDave Lee output_sp->PutCString("Enter one or more sed substitution commands in " 814b9c1b51eSKate Stone "the form: 's/<regex>/<subst>/'.\nTerminate the " 815b9c1b51eSKate Stone "substitution list with an empty line.\n"); 81644d93782SGreg Clayton output_sp->Flush(); 81744d93782SGreg Clayton } 81844d93782SGreg Clayton } 81944d93782SGreg Clayton 820b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 821b9c1b51eSKate Stone std::string &data) override { 82244d93782SGreg Clayton io_handler.SetIsDone(true); 823d5b44036SJonas Devlieghere if (m_regex_cmd_up) { 82444d93782SGreg Clayton StringList lines; 825b9c1b51eSKate Stone if (lines.SplitIntoLines(data)) { 82644d93782SGreg Clayton bool check_only = false; 8274c78b788SRaphael Isemann for (const std::string &line : lines) { 8284c78b788SRaphael Isemann Status error = AppendRegexSubstitution(line, check_only); 829b9c1b51eSKate Stone if (error.Fail()) { 83057179860SJonas Devlieghere if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) { 83157179860SJonas Devlieghere StreamSP out_stream = GetDebugger().GetAsyncOutputStream(); 83244d93782SGreg Clayton out_stream->Printf("error: %s\n", error.AsCString()); 83344d93782SGreg Clayton } 83444d93782SGreg Clayton } 83544d93782SGreg Clayton } 83644d93782SGreg Clayton } 837d5b44036SJonas Devlieghere if (m_regex_cmd_up->HasRegexEntries()) { 838d5b44036SJonas Devlieghere CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 83944d93782SGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 84044d93782SGreg Clayton } 84144d93782SGreg Clayton } 84244d93782SGreg Clayton } 84344d93782SGreg Clayton 844b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 8455a988416SJim Ingham const size_t argc = command.GetArgumentCount(); 846b9c1b51eSKate Stone if (argc == 0) { 847b9c1b51eSKate Stone result.AppendError("usage: 'command regex <command-name> " 848b9c1b51eSKate Stone "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 8490e5e5a79SGreg Clayton result.SetStatus(eReturnStatusFailed); 85011eb9c64SZachary Turner return false; 85111eb9c64SZachary Turner } 85211eb9c64SZachary Turner 85397206d57SZachary Turner Status error; 8540d9a201eSRaphael Isemann auto name = command[0].ref(); 855a8f3ae7cSJonas Devlieghere m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>( 8564574a890SZachary Turner m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 8574574a890SZachary Turner true); 8580e5e5a79SGreg Clayton 859b9c1b51eSKate Stone if (argc == 1) { 86057179860SJonas Devlieghere Debugger &debugger = GetDebugger(); 861e30f11d9SKate Stone bool color_prompt = debugger.GetUseColor(); 86244d93782SGreg Clayton const bool multiple_lines = true; // Get multiple lines 863b9c1b51eSKate Stone IOHandlerSP io_handler_sp(new IOHandlerEditline( 864b9c1b51eSKate Stone debugger, IOHandler::Type::Other, 86573d80faaSGreg Clayton "lldb-regex", // Name of input reader for history 866514d8cd8SZachary Turner llvm::StringRef("> "), // Prompt 867514d8cd8SZachary Turner llvm::StringRef(), // Continuation prompt 868b9c1b51eSKate Stone multiple_lines, color_prompt, 869f6913cd7SGreg Clayton 0, // Don't show line numbers 870d77c2e09SJonas Devlieghere *this, nullptr)); 87144d93782SGreg Clayton 872b9c1b51eSKate Stone if (io_handler_sp) { 8737ce2de2cSJonas Devlieghere debugger.RunIOHandlerAsync(io_handler_sp); 874de164aaaSGreg Clayton result.SetStatus(eReturnStatusSuccessFinishNoResult); 875de164aaaSGreg Clayton } 876b9c1b51eSKate Stone } else { 87797d2c401SZachary Turner for (auto &entry : command.entries().drop_front()) { 87844d93782SGreg Clayton bool check_only = false; 8790d9a201eSRaphael Isemann error = AppendRegexSubstitution(entry.ref(), check_only); 8800e5e5a79SGreg Clayton if (error.Fail()) 8810e5e5a79SGreg Clayton break; 8820e5e5a79SGreg Clayton } 8830e5e5a79SGreg Clayton 884b9c1b51eSKate Stone if (error.Success()) { 8850e5e5a79SGreg Clayton AddRegexCommandToInterpreter(); 8860e5e5a79SGreg Clayton } 8870e5e5a79SGreg Clayton } 888b9c1b51eSKate Stone if (error.Fail()) { 8890e5e5a79SGreg Clayton result.AppendError(error.AsCString()); 890de164aaaSGreg Clayton result.SetStatus(eReturnStatusFailed); 891de164aaaSGreg Clayton } 8920e5e5a79SGreg Clayton 893de164aaaSGreg Clayton return result.Succeeded(); 894de164aaaSGreg Clayton } 895de164aaaSGreg Clayton 89697206d57SZachary Turner Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 897b9c1b51eSKate Stone bool check_only) { 89897206d57SZachary Turner Status error; 8990e5e5a79SGreg Clayton 900d5b44036SJonas Devlieghere if (!m_regex_cmd_up) { 901b9c1b51eSKate Stone error.SetErrorStringWithFormat( 902b9c1b51eSKate Stone "invalid regular expression command object for: '%.*s'", 903b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9040e5e5a79SGreg Clayton return error; 905de164aaaSGreg Clayton } 9060e5e5a79SGreg Clayton 9070e5e5a79SGreg Clayton size_t regex_sed_size = regex_sed.size(); 9080e5e5a79SGreg Clayton 909b9c1b51eSKate Stone if (regex_sed_size <= 1) { 910b9c1b51eSKate Stone error.SetErrorStringWithFormat( 911b9c1b51eSKate Stone "regular expression substitution string is too short: '%.*s'", 912b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9130e5e5a79SGreg Clayton return error; 9140e5e5a79SGreg Clayton } 9150e5e5a79SGreg Clayton 916b9c1b51eSKate Stone if (regex_sed[0] != 's') { 917b9c1b51eSKate Stone error.SetErrorStringWithFormat("regular expression substitution string " 918b9c1b51eSKate Stone "doesn't start with 's': '%.*s'", 919b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9200e5e5a79SGreg Clayton return error; 9210e5e5a79SGreg Clayton } 9220e5e5a79SGreg Clayton const size_t first_separator_char_pos = 1; 92305097246SAdrian Prantl // use the char that follows 's' as the regex separator character so we can 92405097246SAdrian Prantl // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 9250e5e5a79SGreg Clayton const char separator_char = regex_sed[first_separator_char_pos]; 926b9c1b51eSKate Stone const size_t second_separator_char_pos = 927b9c1b51eSKate Stone regex_sed.find(separator_char, first_separator_char_pos + 1); 9280e5e5a79SGreg Clayton 929b9c1b51eSKate Stone if (second_separator_char_pos == std::string::npos) { 930b9c1b51eSKate Stone error.SetErrorStringWithFormat( 931b9c1b51eSKate Stone "missing second '%c' separator char after '%.*s' in '%.*s'", 9320e5e5a79SGreg Clayton separator_char, 9330e5e5a79SGreg Clayton (int)(regex_sed.size() - first_separator_char_pos - 1), 934ea508635SGreg Clayton regex_sed.data() + (first_separator_char_pos + 1), 935b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9360e5e5a79SGreg Clayton return error; 9370e5e5a79SGreg Clayton } 9380e5e5a79SGreg Clayton 939b9c1b51eSKate Stone const size_t third_separator_char_pos = 940b9c1b51eSKate Stone regex_sed.find(separator_char, second_separator_char_pos + 1); 9410e5e5a79SGreg Clayton 942b9c1b51eSKate Stone if (third_separator_char_pos == std::string::npos) { 943b9c1b51eSKate Stone error.SetErrorStringWithFormat( 944b9c1b51eSKate Stone "missing third '%c' separator char after '%.*s' in '%.*s'", 9450e5e5a79SGreg Clayton separator_char, 9460e5e5a79SGreg Clayton (int)(regex_sed.size() - second_separator_char_pos - 1), 947ea508635SGreg Clayton regex_sed.data() + (second_separator_char_pos + 1), 948b9c1b51eSKate Stone (int)regex_sed.size(), regex_sed.data()); 9490e5e5a79SGreg Clayton return error; 9500e5e5a79SGreg Clayton } 9510e5e5a79SGreg Clayton 952b9c1b51eSKate Stone if (third_separator_char_pos != regex_sed_size - 1) { 95305097246SAdrian Prantl // Make sure that everything that follows the last regex separator char 954b9c1b51eSKate Stone if (regex_sed.find_first_not_of("\t\n\v\f\r ", 955b9c1b51eSKate Stone third_separator_char_pos + 1) != 956b9c1b51eSKate Stone std::string::npos) { 957b9c1b51eSKate Stone error.SetErrorStringWithFormat( 958b9c1b51eSKate Stone "extra data found after the '%.*s' regular expression substitution " 959b9c1b51eSKate Stone "string: '%.*s'", 960b9c1b51eSKate Stone (int)third_separator_char_pos + 1, regex_sed.data(), 9610e5e5a79SGreg Clayton (int)(regex_sed.size() - third_separator_char_pos - 1), 9620e5e5a79SGreg Clayton regex_sed.data() + (third_separator_char_pos + 1)); 9630e5e5a79SGreg Clayton return error; 9640e5e5a79SGreg Clayton } 965b9c1b51eSKate Stone } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 966b9c1b51eSKate Stone error.SetErrorStringWithFormat( 967b9c1b51eSKate Stone "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 968b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 9690e5e5a79SGreg Clayton regex_sed.data()); 9700e5e5a79SGreg Clayton return error; 971b9c1b51eSKate Stone } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 972b9c1b51eSKate Stone error.SetErrorStringWithFormat( 973b9c1b51eSKate Stone "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 974b9c1b51eSKate Stone separator_char, separator_char, separator_char, (int)regex_sed.size(), 9750e5e5a79SGreg Clayton regex_sed.data()); 9760e5e5a79SGreg Clayton return error; 9770e5e5a79SGreg Clayton } 97844d93782SGreg Clayton 979b9c1b51eSKate Stone if (!check_only) { 980adcd0268SBenjamin Kramer std::string regex(std::string(regex_sed.substr( 981adcd0268SBenjamin Kramer first_separator_char_pos + 1, 982adcd0268SBenjamin Kramer second_separator_char_pos - first_separator_char_pos - 1))); 983adcd0268SBenjamin Kramer std::string subst(std::string(regex_sed.substr( 984adcd0268SBenjamin Kramer second_separator_char_pos + 1, 985adcd0268SBenjamin Kramer third_separator_char_pos - second_separator_char_pos - 1))); 98643224195SRaphael Isemann m_regex_cmd_up->AddRegexCommand(regex, subst); 98744d93782SGreg Clayton } 9880e5e5a79SGreg Clayton return error; 989de164aaaSGreg Clayton } 990de164aaaSGreg Clayton 991b9c1b51eSKate Stone void AddRegexCommandToInterpreter() { 992d5b44036SJonas Devlieghere if (m_regex_cmd_up) { 993d5b44036SJonas Devlieghere if (m_regex_cmd_up->HasRegexEntries()) { 994d5b44036SJonas Devlieghere CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 995de164aaaSGreg Clayton m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 996de164aaaSGreg Clayton } 997de164aaaSGreg Clayton } 998de164aaaSGreg Clayton } 999de164aaaSGreg Clayton 1000de164aaaSGreg Clayton private: 1001d5b44036SJonas Devlieghere std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up; 1002de164aaaSGreg Clayton 1003b9c1b51eSKate Stone class CommandOptions : public Options { 1004de164aaaSGreg Clayton public: 1005b9c1b51eSKate Stone CommandOptions() : Options() {} 1006de164aaaSGreg Clayton 10076e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1008de164aaaSGreg Clayton 100997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1010b9c1b51eSKate Stone ExecutionContext *execution_context) override { 101197206d57SZachary Turner Status error; 10123bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1013de164aaaSGreg Clayton 1014b9c1b51eSKate Stone switch (short_option) { 1015de164aaaSGreg Clayton case 'h': 1016adcd0268SBenjamin Kramer m_help.assign(std::string(option_arg)); 1017de164aaaSGreg Clayton break; 1018de164aaaSGreg Clayton case 's': 1019adcd0268SBenjamin Kramer m_syntax.assign(std::string(option_arg)); 1020de164aaaSGreg Clayton break; 1021de164aaaSGreg Clayton default: 102236162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1023de164aaaSGreg Clayton } 1024de164aaaSGreg Clayton 1025de164aaaSGreg Clayton return error; 1026de164aaaSGreg Clayton } 1027de164aaaSGreg Clayton 1028b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 1029de164aaaSGreg Clayton m_help.clear(); 1030de164aaaSGreg Clayton m_syntax.clear(); 1031de164aaaSGreg Clayton } 1032de164aaaSGreg Clayton 10331f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 103470602439SZachary Turner return llvm::makeArrayRef(g_regex_options); 10351f0f5b5bSZachary Turner } 1036de164aaaSGreg Clayton 1037daed98e5SShivam Mittal llvm::StringRef GetHelp() { return m_help; } 10386e3d8e7fSEugene Zelenko 1039daed98e5SShivam Mittal llvm::StringRef GetSyntax() { return m_syntax; } 10406e3d8e7fSEugene Zelenko 1041de164aaaSGreg Clayton protected: 10426e3d8e7fSEugene Zelenko // Instance variables to hold the values for command options. 10436e3d8e7fSEugene Zelenko 1044de164aaaSGreg Clayton std::string m_help; 1045de164aaaSGreg Clayton std::string m_syntax; 1046de164aaaSGreg Clayton }; 1047de164aaaSGreg Clayton 1048b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 1049de164aaaSGreg Clayton 10505a988416SJim Ingham CommandOptions m_options; 1051de164aaaSGreg Clayton }; 1052de164aaaSGreg Clayton 1053b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw { 1054223383edSEnrico Granata public: 1055b9c1b51eSKate Stone CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1056b9c1b51eSKate Stone std::string funct, std::string help, 1057b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1058a925974bSAdrian Prantl : CommandObjectRaw(interpreter, name), m_function_name(funct), 1059a925974bSAdrian Prantl m_synchro(synch), m_fetched_help_long(false) { 1060735152e3SEnrico Granata if (!help.empty()) 1061442f6530SZachary Turner SetHelp(help); 1062b9c1b51eSKate Stone else { 1063735152e3SEnrico Granata StreamString stream; 1064735152e3SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1065c156427dSZachary Turner SetHelp(stream.GetString()); 1066735152e3SEnrico Granata } 1067223383edSEnrico Granata } 1068223383edSEnrico Granata 10696e3d8e7fSEugene Zelenko ~CommandObjectPythonFunction() override = default; 1070223383edSEnrico Granata 1071b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 10725a988416SJim Ingham 1073b9c1b51eSKate Stone const std::string &GetFunctionName() { return m_function_name; } 10745a988416SJim Ingham 1075b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 10765a988416SJim Ingham 1077442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1078442f6530SZachary Turner if (m_fetched_help_long) 1079442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1080442f6530SZachary Turner 10812b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1082442f6530SZachary Turner if (!scripter) 1083442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1084442f6530SZachary Turner 1085fac939e9SEnrico Granata std::string docstring; 1086442f6530SZachary Turner m_fetched_help_long = 1087442f6530SZachary Turner scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1088fac939e9SEnrico Granata if (!docstring.empty()) 1089442f6530SZachary Turner SetHelpLong(docstring); 1090fac939e9SEnrico Granata return CommandObjectRaw::GetHelpLong(); 1091fac939e9SEnrico Granata } 1092fac939e9SEnrico Granata 10935a988416SJim Ingham protected: 10944d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 1095b9c1b51eSKate Stone CommandReturnObject &result) override { 10962b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1097223383edSEnrico Granata 109897206d57SZachary Turner Status error; 1099223383edSEnrico Granata 110070f11f88SJim Ingham result.SetStatus(eReturnStatusInvalid); 110170f11f88SJim Ingham 1102a925974bSAdrian Prantl if (!scripter || !scripter->RunScriptBasedCommand( 1103a925974bSAdrian Prantl m_function_name.c_str(), raw_command_line, m_synchro, 1104a925974bSAdrian Prantl result, error, m_exe_ctx)) { 1105223383edSEnrico Granata result.AppendError(error.AsCString()); 1106223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1107b9c1b51eSKate Stone } else { 110870f11f88SJim Ingham // Don't change the status if the command already set it... 1109b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1110c156427dSZachary Turner if (result.GetOutputData().empty()) 1111223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 111270f11f88SJim Ingham else 111370f11f88SJim Ingham result.SetStatus(eReturnStatusSuccessFinishResult); 111470f11f88SJim Ingham } 111570f11f88SJim Ingham } 1116223383edSEnrico Granata 1117223383edSEnrico Granata return result.Succeeded(); 1118223383edSEnrico Granata } 1119223383edSEnrico Granata 11206e3d8e7fSEugene Zelenko private: 11216e3d8e7fSEugene Zelenko std::string m_function_name; 11226e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 11236e3d8e7fSEugene Zelenko bool m_fetched_help_long; 1124223383edSEnrico Granata }; 1125223383edSEnrico Granata 1126b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw { 11279fe00e52SEnrico Granata public: 11289fe00e52SEnrico Granata CommandObjectScriptingObject(CommandInterpreter &interpreter, 11299fe00e52SEnrico Granata std::string name, 11300641ca1aSZachary Turner StructuredData::GenericSP cmd_obj_sp, 1131b9c1b51eSKate Stone ScriptedCommandSynchronicity synch) 1132a925974bSAdrian Prantl : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp), 1133a925974bSAdrian Prantl m_synchro(synch), m_fetched_help_short(false), 1134b9c1b51eSKate Stone m_fetched_help_long(false) { 11359fe00e52SEnrico Granata StreamString stream; 11369fe00e52SEnrico Granata stream.Printf("For more information run 'help %s'", name.c_str()); 1137c156427dSZachary Turner SetHelp(stream.GetString()); 11382b29b432SJonas Devlieghere if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter()) 1139e87764f2SEnrico Granata GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 11409fe00e52SEnrico Granata } 11419fe00e52SEnrico Granata 11426e3d8e7fSEugene Zelenko ~CommandObjectScriptingObject() override = default; 11439fe00e52SEnrico Granata 1144b9c1b51eSKate Stone bool IsRemovable() const override { return true; } 11459fe00e52SEnrico Granata 1146b9c1b51eSKate Stone ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 11479fe00e52SEnrico Granata 1148442f6530SZachary Turner llvm::StringRef GetHelp() override { 1149442f6530SZachary Turner if (m_fetched_help_short) 1150442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 11512b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1152442f6530SZachary Turner if (!scripter) 1153442f6530SZachary Turner return CommandObjectRaw::GetHelp(); 11546f79bb2dSEnrico Granata std::string docstring; 1155b9c1b51eSKate Stone m_fetched_help_short = 1156b9c1b51eSKate Stone scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 11576f79bb2dSEnrico Granata if (!docstring.empty()) 1158442f6530SZachary Turner SetHelp(docstring); 1159442f6530SZachary Turner 11606f79bb2dSEnrico Granata return CommandObjectRaw::GetHelp(); 11616f79bb2dSEnrico Granata } 11626f79bb2dSEnrico Granata 1163442f6530SZachary Turner llvm::StringRef GetHelpLong() override { 1164442f6530SZachary Turner if (m_fetched_help_long) 1165442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1166442f6530SZachary Turner 11672b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1168442f6530SZachary Turner if (!scripter) 1169442f6530SZachary Turner return CommandObjectRaw::GetHelpLong(); 1170442f6530SZachary Turner 11716f79bb2dSEnrico Granata std::string docstring; 1172b9c1b51eSKate Stone m_fetched_help_long = 1173b9c1b51eSKate Stone scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 11746f79bb2dSEnrico Granata if (!docstring.empty()) 1175442f6530SZachary Turner SetHelpLong(docstring); 11769fe00e52SEnrico Granata return CommandObjectRaw::GetHelpLong(); 11779fe00e52SEnrico Granata } 11789fe00e52SEnrico Granata 11799fe00e52SEnrico Granata protected: 11804d51a902SRaphael Isemann bool DoExecute(llvm::StringRef raw_command_line, 1181b9c1b51eSKate Stone CommandReturnObject &result) override { 11822b29b432SJonas Devlieghere ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 11839fe00e52SEnrico Granata 118497206d57SZachary Turner Status error; 11859fe00e52SEnrico Granata 11869fe00e52SEnrico Granata result.SetStatus(eReturnStatusInvalid); 11879fe00e52SEnrico Granata 1188b9c1b51eSKate Stone if (!scripter || 1189b9c1b51eSKate Stone !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1190b9c1b51eSKate Stone m_synchro, result, error, m_exe_ctx)) { 11919fe00e52SEnrico Granata result.AppendError(error.AsCString()); 11929fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 1193b9c1b51eSKate Stone } else { 11949fe00e52SEnrico Granata // Don't change the status if the command already set it... 1195b9c1b51eSKate Stone if (result.GetStatus() == eReturnStatusInvalid) { 1196c156427dSZachary Turner if (result.GetOutputData().empty()) 11979fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 11989fe00e52SEnrico Granata else 11999fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 12009fe00e52SEnrico Granata } 12019fe00e52SEnrico Granata } 12029fe00e52SEnrico Granata 12039fe00e52SEnrico Granata return result.Succeeded(); 12049fe00e52SEnrico Granata } 12059fe00e52SEnrico Granata 12066e3d8e7fSEugene Zelenko private: 12076e3d8e7fSEugene Zelenko StructuredData::GenericSP m_cmd_obj_sp; 12086e3d8e7fSEugene Zelenko ScriptedCommandSynchronicity m_synchro; 12096e3d8e7fSEugene Zelenko bool m_fetched_help_short : 1; 12106e3d8e7fSEugene Zelenko bool m_fetched_help_long : 1; 12119fe00e52SEnrico Granata }; 12129fe00e52SEnrico Granata 1213a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport 121464becc11SRaphael Isemann #define LLDB_OPTIONS_script_import 121564becc11SRaphael Isemann #include "CommandOptions.inc" 12161f0f5b5bSZachary Turner 1217b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed { 12185a988416SJim Ingham public: 1219b9c1b51eSKate Stone CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1220b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script import", 1221b9c1b51eSKate Stone "Import a scripting module in LLDB.", nullptr), 1222b9c1b51eSKate Stone m_options() { 12235a988416SJim Ingham CommandArgumentEntry arg1; 12245a988416SJim Ingham CommandArgumentData cmd_arg; 12255a988416SJim Ingham 12265a988416SJim Ingham // Define the first (and only) variant of this arg. 12275a988416SJim Ingham cmd_arg.arg_type = eArgTypeFilename; 12283b00e35bSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlus; 12295a988416SJim Ingham 1230b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1231b9c1b51eSKate Stone // argument entry. 12325a988416SJim Ingham arg1.push_back(cmd_arg); 12335a988416SJim Ingham 12345a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 12355a988416SJim Ingham m_arguments.push_back(arg1); 12365a988416SJim Ingham } 12375a988416SJim Ingham 12386e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptImport() override = default; 12395a988416SJim Ingham 1240ae34ed2cSRaphael Isemann void 1241ae34ed2cSRaphael Isemann HandleArgumentCompletion(CompletionRequest &request, 12422443bbd4SRaphael Isemann OptionElementVector &opt_element_vector) override { 1243b9c1b51eSKate Stone CommandCompletions::InvokeCommonCompletionCallbacks( 1244b9c1b51eSKate Stone GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1245a2e76c0bSRaphael Isemann request, nullptr); 12465a988416SJim Ingham } 12475a988416SJim Ingham 1248b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 12495a988416SJim Ingham 12505a988416SJim Ingham protected: 1251b9c1b51eSKate Stone class CommandOptions : public Options { 12520a305db7SEnrico Granata public: 1253b9c1b51eSKate Stone CommandOptions() : Options() {} 12540a305db7SEnrico Granata 12556e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 12560a305db7SEnrico Granata 125797206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1258b9c1b51eSKate Stone ExecutionContext *execution_context) override { 125997206d57SZachary Turner Status error; 12603bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 12610a305db7SEnrico Granata 1262b9c1b51eSKate Stone switch (short_option) { 12630a305db7SEnrico Granata case 'r': 126415625112SJonas Devlieghere // NO-OP 12650a305db7SEnrico Granata break; 126600bb397bSJonas Devlieghere case 'c': 126700bb397bSJonas Devlieghere relative_to_command_file = true; 126800bb397bSJonas Devlieghere break; 12690a305db7SEnrico Granata default: 127036162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 12710a305db7SEnrico Granata } 12720a305db7SEnrico Granata 12730a305db7SEnrico Granata return error; 12740a305db7SEnrico Granata } 12750a305db7SEnrico Granata 1276b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 127700bb397bSJonas Devlieghere relative_to_command_file = false; 12780a305db7SEnrico Granata } 12790a305db7SEnrico Granata 12801f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 128170602439SZachary Turner return llvm::makeArrayRef(g_script_import_options); 12821f0f5b5bSZachary Turner } 128300bb397bSJonas Devlieghere bool relative_to_command_file = false; 12840a305db7SEnrico Granata }; 12850a305db7SEnrico Granata 1286b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 128711eb9c64SZachary Turner if (command.empty()) { 12883b00e35bSEnrico Granata result.AppendError("command script import needs one or more arguments"); 1289a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1290a9dbf432SEnrico Granata return false; 1291a9dbf432SEnrico Granata } 1292a9dbf432SEnrico Granata 129300bb397bSJonas Devlieghere FileSpec source_dir = {}; 129400bb397bSJonas Devlieghere if (m_options.relative_to_command_file) { 129500bb397bSJonas Devlieghere source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir(); 129600bb397bSJonas Devlieghere if (!source_dir) { 129700bb397bSJonas Devlieghere result.AppendError("command script import -c can only be specified " 129800bb397bSJonas Devlieghere "from a command file"); 129900bb397bSJonas Devlieghere result.SetStatus(eReturnStatusFailed); 130000bb397bSJonas Devlieghere return false; 130100bb397bSJonas Devlieghere } 130200bb397bSJonas Devlieghere } 130300bb397bSJonas Devlieghere 130411eb9c64SZachary Turner for (auto &entry : command.entries()) { 130597206d57SZachary Turner Status error; 1306a9dbf432SEnrico Granata 1307c9d645d3SGreg Clayton const bool init_session = true; 1308b9c1b51eSKate Stone // FIXME: this is necessary because CommandObject::CheckRequirements() 130911eb9c64SZachary Turner // assumes that commands won't ever be recursively invoked, but it's 131011eb9c64SZachary Turner // actually possible to craft a Python script that does other "command 131105097246SAdrian Prantl // script imports" in __lldb_init_module the real fix is to have 131205097246SAdrian Prantl // recursive commands possible with a CommandInvocation object separate 131305097246SAdrian Prantl // from the CommandObject itself, so that recursive command invocations 131405097246SAdrian Prantl // won't stomp on each other (wrt to execution contents, options, and 131505097246SAdrian Prantl // more) 1316078551c7SEnrico Granata m_exe_ctx.Clear(); 13172b29b432SJonas Devlieghere if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule( 131800bb397bSJonas Devlieghere entry.c_str(), init_session, error, nullptr, source_dir)) { 1319a9dbf432SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1320b9c1b51eSKate Stone } else { 1321b9c1b51eSKate Stone result.AppendErrorWithFormat("module importing failed: %s", 1322b9c1b51eSKate Stone error.AsCString()); 1323a9dbf432SEnrico Granata result.SetStatus(eReturnStatusFailed); 1324a9dbf432SEnrico Granata } 13253b00e35bSEnrico Granata } 1326a9dbf432SEnrico Granata 1327a9dbf432SEnrico Granata return result.Succeeded(); 1328a9dbf432SEnrico Granata } 13290a305db7SEnrico Granata 13305a988416SJim Ingham CommandOptions m_options; 1331a9dbf432SEnrico Granata }; 1332223383edSEnrico Granata 1333223383edSEnrico Granata // CommandObjectCommandsScriptAdd 13348fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_script_synchro_type[] = { 1335e063ecccSJonas Devlieghere { 1336e063ecccSJonas Devlieghere eScriptedCommandSynchronicitySynchronous, 1337e063ecccSJonas Devlieghere "synchronous", 1338e063ecccSJonas Devlieghere "Run synchronous", 1339e063ecccSJonas Devlieghere }, 1340e063ecccSJonas Devlieghere { 1341e063ecccSJonas Devlieghere eScriptedCommandSynchronicityAsynchronous, 1342e063ecccSJonas Devlieghere "asynchronous", 1343e063ecccSJonas Devlieghere "Run asynchronous", 1344e063ecccSJonas Devlieghere }, 1345e063ecccSJonas Devlieghere { 1346e063ecccSJonas Devlieghere eScriptedCommandSynchronicityCurrentValue, 1347e063ecccSJonas Devlieghere "current", 1348e063ecccSJonas Devlieghere "Do not alter current setting", 1349e063ecccSJonas Devlieghere }, 1350e063ecccSJonas Devlieghere }; 13511f0f5b5bSZachary Turner 13528fe53c49STatyana Krasnukha static constexpr OptionEnumValues ScriptSynchroType() { 13538fe53c49STatyana Krasnukha return OptionEnumValues(g_script_synchro_type); 13548fe53c49STatyana Krasnukha } 13558fe53c49STatyana Krasnukha 135664becc11SRaphael Isemann #define LLDB_OPTIONS_script_add 135764becc11SRaphael Isemann #include "CommandOptions.inc" 13581f0f5b5bSZachary Turner 1359b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1360b9c1b51eSKate Stone public IOHandlerDelegateMultiline { 13615a988416SJim Ingham public: 1362b9c1b51eSKate Stone CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1363b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script add", 13645a988416SJim Ingham "Add a scripted function as an LLDB command.", 13656e3d8e7fSEugene Zelenko nullptr), 1366b9c1b51eSKate Stone IOHandlerDelegateMultiline("DONE"), m_options() { 13675a988416SJim Ingham CommandArgumentEntry arg1; 13685a988416SJim Ingham CommandArgumentData cmd_arg; 13695a988416SJim Ingham 13705a988416SJim Ingham // Define the first (and only) variant of this arg. 13715a988416SJim Ingham cmd_arg.arg_type = eArgTypeCommandName; 13725a988416SJim Ingham cmd_arg.arg_repetition = eArgRepeatPlain; 13735a988416SJim Ingham 1374b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1375b9c1b51eSKate Stone // argument entry. 13765a988416SJim Ingham arg1.push_back(cmd_arg); 13775a988416SJim Ingham 13785a988416SJim Ingham // Push the data for the first argument into the m_arguments vector. 13795a988416SJim Ingham m_arguments.push_back(arg1); 13805a988416SJim Ingham } 13815a988416SJim Ingham 13826e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptAdd() override = default; 13835a988416SJim Ingham 1384b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 13855a988416SJim Ingham 13865a988416SJim Ingham protected: 1387b9c1b51eSKate Stone class CommandOptions : public Options { 1388223383edSEnrico Granata public: 1389b9c1b51eSKate Stone CommandOptions() 1390*9494c510SJonas Devlieghere : Options(), m_class_name(), m_funct_name(), m_short_help() {} 1391223383edSEnrico Granata 13926e3d8e7fSEugene Zelenko ~CommandOptions() override = default; 1393223383edSEnrico Granata 139497206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1395b9c1b51eSKate Stone ExecutionContext *execution_context) override { 139697206d57SZachary Turner Status error; 13973bcdfc0eSGreg Clayton const int short_option = m_getopt_table[option_idx].val; 1398223383edSEnrico Granata 1399b9c1b51eSKate Stone switch (short_option) { 1400223383edSEnrico Granata case 'f': 1401fe11483bSZachary Turner if (!option_arg.empty()) 1402adcd0268SBenjamin Kramer m_funct_name = std::string(option_arg); 1403735152e3SEnrico Granata break; 14049fe00e52SEnrico Granata case 'c': 1405fe11483bSZachary Turner if (!option_arg.empty()) 1406adcd0268SBenjamin Kramer m_class_name = std::string(option_arg); 14079fe00e52SEnrico Granata break; 1408735152e3SEnrico Granata case 'h': 1409fe11483bSZachary Turner if (!option_arg.empty()) 1410adcd0268SBenjamin Kramer m_short_help = std::string(option_arg); 1411223383edSEnrico Granata break; 14120a305db7SEnrico Granata case 's': 1413b9c1b51eSKate Stone m_synchronicity = 141447cbf4a0SPavel Labath (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum( 1415fe11483bSZachary Turner option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 14160a305db7SEnrico Granata if (!error.Success()) 1417b9c1b51eSKate Stone error.SetErrorStringWithFormat( 1418fe11483bSZachary Turner "unrecognized value for synchronicity '%s'", 1419fe11483bSZachary Turner option_arg.str().c_str()); 14200a305db7SEnrico Granata break; 1421223383edSEnrico Granata default: 142236162014SRaphael Isemann llvm_unreachable("Unimplemented option"); 1423223383edSEnrico Granata } 1424223383edSEnrico Granata 1425223383edSEnrico Granata return error; 1426223383edSEnrico Granata } 1427223383edSEnrico Granata 1428b9c1b51eSKate Stone void OptionParsingStarting(ExecutionContext *execution_context) override { 14299fe00e52SEnrico Granata m_class_name.clear(); 1430735152e3SEnrico Granata m_funct_name.clear(); 1431735152e3SEnrico Granata m_short_help.clear(); 143244d93782SGreg Clayton m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1433223383edSEnrico Granata } 1434223383edSEnrico Granata 14351f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 143670602439SZachary Turner return llvm::makeArrayRef(g_script_add_options); 14371f0f5b5bSZachary Turner } 1438223383edSEnrico Granata 1439223383edSEnrico Granata // Instance variables to hold the values for command options. 1440223383edSEnrico Granata 14419fe00e52SEnrico Granata std::string m_class_name; 1442223383edSEnrico Granata std::string m_funct_name; 1443735152e3SEnrico Granata std::string m_short_help; 1444*9494c510SJonas Devlieghere ScriptedCommandSynchronicity m_synchronicity = 1445*9494c510SJonas Devlieghere eScriptedCommandSynchronicitySynchronous; 1446223383edSEnrico Granata }; 1447223383edSEnrico Granata 14480affb582SDave Lee void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 14497ca15ba7SLawrence D'Anna StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); 14500affb582SDave Lee if (output_sp && interactive) { 145144d93782SGreg Clayton output_sp->PutCString(g_python_command_instructions); 145244d93782SGreg Clayton output_sp->Flush(); 1453223383edSEnrico Granata } 1454223383edSEnrico Granata } 1455223383edSEnrico Granata 1456b9c1b51eSKate Stone void IOHandlerInputComplete(IOHandler &io_handler, 1457b9c1b51eSKate Stone std::string &data) override { 14587ca15ba7SLawrence D'Anna StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); 145944d93782SGreg Clayton 14602b29b432SJonas Devlieghere ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1461b9c1b51eSKate Stone if (interpreter) { 146244d93782SGreg Clayton 146344d93782SGreg Clayton StringList lines; 146444d93782SGreg Clayton lines.SplitIntoLines(data); 1465b9c1b51eSKate Stone if (lines.GetSize() > 0) { 1466a73b7df7SEnrico Granata std::string funct_name_str; 1467b9c1b51eSKate Stone if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1468b9c1b51eSKate Stone if (funct_name_str.empty()) { 1469b9c1b51eSKate Stone error_sp->Printf("error: unable to obtain a function name, didn't " 1470b9c1b51eSKate Stone "add python command.\n"); 147144d93782SGreg Clayton error_sp->Flush(); 1472b9c1b51eSKate Stone } else { 1473223383edSEnrico Granata // everything should be fine now, let's add this alias 1474223383edSEnrico Granata 1475b9c1b51eSKate Stone CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1476771ef6d4SMalcolm Parsons m_interpreter, m_cmd_name, funct_name_str, m_short_help, 147744d93782SGreg Clayton m_synchronicity)); 1478223383edSEnrico Granata 1479b9c1b51eSKate Stone if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1480b9c1b51eSKate Stone true)) { 1481b9c1b51eSKate Stone error_sp->Printf("error: unable to add selected command, didn't " 1482b9c1b51eSKate Stone "add python command.\n"); 148344d93782SGreg Clayton error_sp->Flush(); 1484223383edSEnrico Granata } 1485223383edSEnrico Granata } 1486b9c1b51eSKate Stone } else { 1487b9c1b51eSKate Stone error_sp->Printf( 1488b9c1b51eSKate Stone "error: unable to create function, didn't add python command.\n"); 148944d93782SGreg Clayton error_sp->Flush(); 149044d93782SGreg Clayton } 1491b9c1b51eSKate Stone } else { 149244d93782SGreg Clayton error_sp->Printf("error: empty function, didn't add python command.\n"); 149344d93782SGreg Clayton error_sp->Flush(); 149444d93782SGreg Clayton } 1495b9c1b51eSKate Stone } else { 1496b9c1b51eSKate Stone error_sp->Printf( 1497b9c1b51eSKate Stone "error: script interpreter missing, didn't add python command.\n"); 149844d93782SGreg Clayton error_sp->Flush(); 149944d93782SGreg Clayton } 150044d93782SGreg Clayton 150144d93782SGreg Clayton io_handler.SetIsDone(true); 150244d93782SGreg Clayton } 1503223383edSEnrico Granata 1504b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 150557179860SJonas Devlieghere if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { 1506b9c1b51eSKate Stone result.AppendError("only scripting language supported for scripted " 1507b9c1b51eSKate Stone "commands is currently Python"); 150899f0b8f9SEnrico Granata result.SetStatus(eReturnStatusFailed); 150999f0b8f9SEnrico Granata return false; 151099f0b8f9SEnrico Granata } 151199f0b8f9SEnrico Granata 151211eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1513223383edSEnrico Granata result.AppendError("'command script add' requires one argument"); 1514223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1515223383edSEnrico Granata return false; 1516223383edSEnrico Granata } 1517223383edSEnrico Granata 1518735152e3SEnrico Granata // Store the options in case we get multi-line input 1519adcd0268SBenjamin Kramer m_cmd_name = std::string(command[0].ref()); 1520735152e3SEnrico Granata m_short_help.assign(m_options.m_short_help); 152144d93782SGreg Clayton m_synchronicity = m_options.m_synchronicity; 1522223383edSEnrico Granata 1523b9c1b51eSKate Stone if (m_options.m_class_name.empty()) { 1524b9c1b51eSKate Stone if (m_options.m_funct_name.empty()) { 1525b9c1b51eSKate Stone m_interpreter.GetPythonCommandsFromIOHandler( 1526b9c1b51eSKate Stone " ", // Prompt 1527a6faf851SJonas Devlieghere *this); // IOHandlerDelegate 1528b9c1b51eSKate Stone } else { 1529b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1530b9c1b51eSKate Stone m_interpreter, m_cmd_name, m_options.m_funct_name, 1531b9c1b51eSKate Stone m_options.m_short_help, m_synchronicity)); 1532b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1533223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1534b9c1b51eSKate Stone } else { 1535223383edSEnrico Granata result.AppendError("cannot add command"); 1536223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1537223383edSEnrico Granata } 1538223383edSEnrico Granata } 1539b9c1b51eSKate Stone } else { 15402b29b432SJonas Devlieghere ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1541b9c1b51eSKate Stone if (!interpreter) { 15429fe00e52SEnrico Granata result.AppendError("cannot find ScriptInterpreter"); 15439fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 15449fe00e52SEnrico Granata return false; 15459fe00e52SEnrico Granata } 15469fe00e52SEnrico Granata 1547b9c1b51eSKate Stone auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1548b9c1b51eSKate Stone m_options.m_class_name.c_str()); 1549b9c1b51eSKate Stone if (!cmd_obj_sp) { 15509fe00e52SEnrico Granata result.AppendError("cannot create helper object"); 15519fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 15529fe00e52SEnrico Granata return false; 15539fe00e52SEnrico Granata } 15549fe00e52SEnrico Granata 1555b9c1b51eSKate Stone CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1556b9c1b51eSKate Stone m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1557b9c1b51eSKate Stone if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 15589fe00e52SEnrico Granata result.SetStatus(eReturnStatusSuccessFinishNoResult); 1559b9c1b51eSKate Stone } else { 15609fe00e52SEnrico Granata result.AppendError("cannot add command"); 15619fe00e52SEnrico Granata result.SetStatus(eReturnStatusFailed); 15629fe00e52SEnrico Granata } 15639fe00e52SEnrico Granata } 1564223383edSEnrico Granata 1565223383edSEnrico Granata return result.Succeeded(); 1566223383edSEnrico Granata } 15675a988416SJim Ingham 15685a988416SJim Ingham CommandOptions m_options; 156944d93782SGreg Clayton std::string m_cmd_name; 1570735152e3SEnrico Granata std::string m_short_help; 157144d93782SGreg Clayton ScriptedCommandSynchronicity m_synchronicity; 1572223383edSEnrico Granata }; 1573223383edSEnrico Granata 1574223383edSEnrico Granata // CommandObjectCommandsScriptList 1575223383edSEnrico Granata 1576b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed { 1577223383edSEnrico Granata public: 1578b9c1b51eSKate Stone CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1579b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script list", 1580b9c1b51eSKate Stone "List defined scripted commands.", nullptr) {} 1581223383edSEnrico Granata 15826e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptList() override = default; 1583223383edSEnrico Granata 1584b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1585d77ea5b2SRaphael Isemann if (command.GetArgumentCount() != 0) { 1586d77ea5b2SRaphael Isemann result.AppendError("'command script list' doesn't take any arguments"); 1587d77ea5b2SRaphael Isemann result.SetStatus(eReturnStatusFailed); 1588d77ea5b2SRaphael Isemann return false; 1589d77ea5b2SRaphael Isemann } 1590d77ea5b2SRaphael Isemann 1591b9c1b51eSKate Stone m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1592223383edSEnrico Granata 1593223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1594223383edSEnrico Granata 1595223383edSEnrico Granata return true; 1596223383edSEnrico Granata } 1597223383edSEnrico Granata }; 1598223383edSEnrico Granata 1599223383edSEnrico Granata // CommandObjectCommandsScriptClear 1600223383edSEnrico Granata 1601b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1602223383edSEnrico Granata public: 1603b9c1b51eSKate Stone CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1604b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script clear", 1605b9c1b51eSKate Stone "Delete all scripted commands.", nullptr) {} 1606223383edSEnrico Granata 16076e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptClear() override = default; 1608223383edSEnrico Granata 16095a988416SJim Ingham protected: 1610b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1611d77ea5b2SRaphael Isemann if (command.GetArgumentCount() != 0) { 1612d77ea5b2SRaphael Isemann result.AppendError("'command script clear' doesn't take any arguments"); 1613d77ea5b2SRaphael Isemann result.SetStatus(eReturnStatusFailed); 1614d77ea5b2SRaphael Isemann return false; 1615d77ea5b2SRaphael Isemann } 1616d77ea5b2SRaphael Isemann 1617223383edSEnrico Granata m_interpreter.RemoveAllUser(); 1618223383edSEnrico Granata 1619223383edSEnrico Granata result.SetStatus(eReturnStatusSuccessFinishResult); 1620223383edSEnrico Granata 1621223383edSEnrico Granata return true; 1622223383edSEnrico Granata } 1623223383edSEnrico Granata }; 1624223383edSEnrico Granata 1625223383edSEnrico Granata // CommandObjectCommandsScriptDelete 1626223383edSEnrico Granata 1627b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1628223383edSEnrico Granata public: 1629b9c1b51eSKate Stone CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1630b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "command script delete", 1631b9c1b51eSKate Stone "Delete a scripted command.", nullptr) { 1632223383edSEnrico Granata CommandArgumentEntry arg1; 1633223383edSEnrico Granata CommandArgumentData cmd_arg; 1634223383edSEnrico Granata 1635223383edSEnrico Granata // Define the first (and only) variant of this arg. 1636223383edSEnrico Granata cmd_arg.arg_type = eArgTypeCommandName; 1637223383edSEnrico Granata cmd_arg.arg_repetition = eArgRepeatPlain; 1638223383edSEnrico Granata 1639b9c1b51eSKate Stone // There is only one variant this argument could be; put it into the 1640b9c1b51eSKate Stone // argument entry. 1641223383edSEnrico Granata arg1.push_back(cmd_arg); 1642223383edSEnrico Granata 1643223383edSEnrico Granata // Push the data for the first argument into the m_arguments vector. 1644223383edSEnrico Granata m_arguments.push_back(arg1); 1645223383edSEnrico Granata } 1646223383edSEnrico Granata 16476e3d8e7fSEugene Zelenko ~CommandObjectCommandsScriptDelete() override = default; 1648223383edSEnrico Granata 16492e8f304fSGongyu Deng void 16502e8f304fSGongyu Deng HandleArgumentCompletion(CompletionRequest &request, 16512e8f304fSGongyu Deng OptionElementVector &opt_element_vector) override { 16522e8f304fSGongyu Deng if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0) 16532e8f304fSGongyu Deng return; 16542e8f304fSGongyu Deng 16552ebe30c6SRaphael Isemann for (const auto &c : m_interpreter.GetUserCommands()) 16562ebe30c6SRaphael Isemann request.TryCompleteCurrentArg(c.first, c.second->GetHelp()); 16572e8f304fSGongyu Deng } 16582e8f304fSGongyu Deng 16595a988416SJim Ingham protected: 1660b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 1661223383edSEnrico Granata 166211eb9c64SZachary Turner if (command.GetArgumentCount() != 1) { 1663223383edSEnrico Granata result.AppendError("'command script delete' requires one argument"); 1664223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 1665223383edSEnrico Granata return false; 1666223383edSEnrico Granata } 1667223383edSEnrico Granata 16680d9a201eSRaphael Isemann auto cmd_name = command[0].ref(); 1669223383edSEnrico Granata 16704574a890SZachary Turner if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 16714574a890SZachary Turner !m_interpreter.UserCommandExists(cmd_name)) { 1672867e7d17SZachary Turner result.AppendErrorWithFormat("command %s not found", command[0].c_str()); 1673223383edSEnrico Granata result.SetStatus(eReturnStatusFailed); 16744574a890SZachary Turner return false; 1675223383edSEnrico Granata } 1676223383edSEnrico Granata 16774574a890SZachary Turner m_interpreter.RemoveUser(cmd_name); 16784574a890SZachary Turner result.SetStatus(eReturnStatusSuccessFinishResult); 16794574a890SZachary Turner return true; 1680223383edSEnrico Granata } 1681223383edSEnrico Granata }; 1682223383edSEnrico Granata 1683223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript 1684223383edSEnrico Granata 1685223383edSEnrico Granata // CommandObjectMultiwordCommandsScript 1686223383edSEnrico Granata 1687b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1688223383edSEnrico Granata public: 16897428a18cSKate Stone CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1690b9c1b51eSKate Stone : CommandObjectMultiword( 1691a925974bSAdrian Prantl interpreter, "command script", 1692a925974bSAdrian Prantl "Commands for managing custom " 1693b9c1b51eSKate Stone "commands implemented by " 1694b9c1b51eSKate Stone "interpreter scripts.", 1695b9c1b51eSKate Stone "command script <subcommand> [<subcommand-options>]") { 1696b9c1b51eSKate Stone LoadSubCommand("add", CommandObjectSP( 1697b9c1b51eSKate Stone new CommandObjectCommandsScriptAdd(interpreter))); 1698b9c1b51eSKate Stone LoadSubCommand( 1699b9c1b51eSKate Stone "delete", 1700b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1701b9c1b51eSKate Stone LoadSubCommand( 1702b9c1b51eSKate Stone "clear", 1703b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1704b9c1b51eSKate Stone LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1705b9c1b51eSKate Stone interpreter))); 1706b9c1b51eSKate Stone LoadSubCommand( 1707b9c1b51eSKate Stone "import", 1708b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1709223383edSEnrico Granata } 1710223383edSEnrico Granata 17116e3d8e7fSEugene Zelenko ~CommandObjectMultiwordCommandsScript() override = default; 1712223383edSEnrico Granata }; 1713223383edSEnrico Granata 1714ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands 1715ebc09c36SJim Ingham 1716ebc09c36SJim Ingham // CommandObjectMultiwordCommands 1717ebc09c36SJim Ingham 1718b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1719b9c1b51eSKate Stone CommandInterpreter &interpreter) 1720b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "command", 1721b9c1b51eSKate Stone "Commands for managing custom LLDB commands.", 1722b9c1b51eSKate Stone "command <subcommand> [<subcommand-options>]") { 1723b9c1b51eSKate Stone LoadSubCommand("source", 1724b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1725b9c1b51eSKate Stone LoadSubCommand("alias", 1726b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1727b9c1b51eSKate Stone LoadSubCommand("unalias", CommandObjectSP( 1728b9c1b51eSKate Stone new CommandObjectCommandsUnalias(interpreter))); 1729b9c1b51eSKate Stone LoadSubCommand("delete", 1730b9c1b51eSKate Stone CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1731b9c1b51eSKate Stone LoadSubCommand( 1732b9c1b51eSKate Stone "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1733b9c1b51eSKate Stone LoadSubCommand( 1734b9c1b51eSKate Stone "script", 1735b9c1b51eSKate Stone CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1736ebc09c36SJim Ingham } 1737ebc09c36SJim Ingham 17386e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1739