15ffd83dbSDimitry Andric //===-- CommandObjectCommands.cpp -----------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "CommandObjectCommands.h"
100b57cec5SDimitry Andric #include "CommandObjectHelp.h"
11af732203SDimitry Andric #include "CommandObjectRegexCommand.h"
120b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
130b57cec5SDimitry Andric #include "lldb/Core/IOHandler.h"
140b57cec5SDimitry Andric #include "lldb/Interpreter/CommandHistory.h"
150b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
160b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
170b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueBoolean.h"
190b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueString.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueUInt64.h"
210b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
220b57cec5SDimitry Andric #include "lldb/Interpreter/ScriptInterpreter.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
240b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
25af732203SDimitry Andric #include "llvm/ADT/StringRef.h"
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric using namespace lldb;
280b57cec5SDimitry Andric using namespace lldb_private;
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric // CommandObjectCommandsSource
310b57cec5SDimitry Andric
329dba64beSDimitry Andric #define LLDB_OPTIONS_source
339dba64beSDimitry Andric #include "CommandOptions.inc"
340b57cec5SDimitry Andric
350b57cec5SDimitry Andric class CommandObjectCommandsSource : public CommandObjectParsed {
360b57cec5SDimitry Andric public:
CommandObjectCommandsSource(CommandInterpreter & interpreter)370b57cec5SDimitry Andric CommandObjectCommandsSource(CommandInterpreter &interpreter)
380b57cec5SDimitry Andric : CommandObjectParsed(
390b57cec5SDimitry Andric interpreter, "command source",
400b57cec5SDimitry Andric "Read and execute LLDB commands from the file <filename>.",
410b57cec5SDimitry Andric nullptr),
420b57cec5SDimitry Andric m_options() {
430b57cec5SDimitry Andric CommandArgumentEntry arg;
440b57cec5SDimitry Andric CommandArgumentData file_arg;
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
470b57cec5SDimitry Andric file_arg.arg_type = eArgTypeFilename;
480b57cec5SDimitry Andric file_arg.arg_repetition = eArgRepeatPlain;
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
510b57cec5SDimitry Andric // argument entry.
520b57cec5SDimitry Andric arg.push_back(file_arg);
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
550b57cec5SDimitry Andric m_arguments.push_back(arg);
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
580b57cec5SDimitry Andric ~CommandObjectCommandsSource() override = default;
590b57cec5SDimitry Andric
GetRepeatCommand(Args & current_command_args,uint32_t index)600b57cec5SDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args,
610b57cec5SDimitry Andric uint32_t index) override {
620b57cec5SDimitry Andric return "";
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
659dba64beSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)669dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
670b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override {
680b57cec5SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
690b57cec5SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
700b57cec5SDimitry Andric request, nullptr);
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric
GetOptions()730b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric protected:
760b57cec5SDimitry Andric class CommandOptions : public Options {
770b57cec5SDimitry Andric public:
CommandOptions()780b57cec5SDimitry Andric CommandOptions()
790b57cec5SDimitry Andric : Options(), m_stop_on_error(true), m_silent_run(false),
800b57cec5SDimitry Andric m_stop_on_continue(true) {}
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric ~CommandOptions() override = default;
830b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)840b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
850b57cec5SDimitry Andric ExecutionContext *execution_context) override {
860b57cec5SDimitry Andric Status error;
870b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric switch (short_option) {
900b57cec5SDimitry Andric case 'e':
910b57cec5SDimitry Andric error = m_stop_on_error.SetValueFromString(option_arg);
920b57cec5SDimitry Andric break;
930b57cec5SDimitry Andric
940b57cec5SDimitry Andric case 'c':
950b57cec5SDimitry Andric error = m_stop_on_continue.SetValueFromString(option_arg);
960b57cec5SDimitry Andric break;
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric case 's':
990b57cec5SDimitry Andric error = m_silent_run.SetValueFromString(option_arg);
1000b57cec5SDimitry Andric break;
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric default:
1039dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andric return error;
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1090b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1100b57cec5SDimitry Andric m_stop_on_error.Clear();
1110b57cec5SDimitry Andric m_silent_run.Clear();
1120b57cec5SDimitry Andric m_stop_on_continue.Clear();
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
GetDefinitions()1150b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1160b57cec5SDimitry Andric return llvm::makeArrayRef(g_source_options);
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric
1190b57cec5SDimitry Andric // Instance variables to hold the values for command options.
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric OptionValueBoolean m_stop_on_error;
1220b57cec5SDimitry Andric OptionValueBoolean m_silent_run;
1230b57cec5SDimitry Andric OptionValueBoolean m_stop_on_continue;
1240b57cec5SDimitry Andric };
1250b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)1260b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1270b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) {
1280b57cec5SDimitry Andric result.AppendErrorWithFormat(
1290b57cec5SDimitry Andric "'%s' takes exactly one executable filename argument.\n",
1300b57cec5SDimitry Andric GetCommandName().str().c_str());
1310b57cec5SDimitry Andric return false;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric
1349dba64beSDimitry Andric FileSpec cmd_file(command[0].ref());
1350b57cec5SDimitry Andric FileSystem::Instance().Resolve(cmd_file);
1360b57cec5SDimitry Andric
137*5f7ddb14SDimitry Andric CommandInterpreterRunOptions options;
1380b57cec5SDimitry Andric // If any options were set, then use them
1390b57cec5SDimitry Andric if (m_options.m_stop_on_error.OptionWasSet() ||
1400b57cec5SDimitry Andric m_options.m_silent_run.OptionWasSet() ||
1410b57cec5SDimitry Andric m_options.m_stop_on_continue.OptionWasSet()) {
1420b57cec5SDimitry Andric if (m_options.m_stop_on_continue.OptionWasSet())
1430b57cec5SDimitry Andric options.SetStopOnContinue(
1440b57cec5SDimitry Andric m_options.m_stop_on_continue.GetCurrentValue());
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric if (m_options.m_stop_on_error.OptionWasSet())
1470b57cec5SDimitry Andric options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric // Individual silent setting is override for global command echo settings.
1500b57cec5SDimitry Andric if (m_options.m_silent_run.GetCurrentValue()) {
1510b57cec5SDimitry Andric options.SetSilent(true);
1520b57cec5SDimitry Andric } else {
1530b57cec5SDimitry Andric options.SetPrintResults(true);
1540b57cec5SDimitry Andric options.SetPrintErrors(true);
1550b57cec5SDimitry Andric options.SetEchoCommands(m_interpreter.GetEchoCommands());
1560b57cec5SDimitry Andric options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric }
159*5f7ddb14SDimitry Andric
160*5f7ddb14SDimitry Andric m_interpreter.HandleCommandsFromFile(cmd_file, options, result);
1610b57cec5SDimitry Andric return result.Succeeded();
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andric CommandOptions m_options;
1650b57cec5SDimitry Andric };
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andric #pragma mark CommandObjectCommandsAlias
1680b57cec5SDimitry Andric // CommandObjectCommandsAlias
1690b57cec5SDimitry Andric
1709dba64beSDimitry Andric #define LLDB_OPTIONS_alias
1719dba64beSDimitry Andric #include "CommandOptions.inc"
1720b57cec5SDimitry Andric
1730b57cec5SDimitry Andric static const char *g_python_command_instructions =
1740b57cec5SDimitry Andric "Enter your Python command(s). Type 'DONE' to end.\n"
1750b57cec5SDimitry Andric "You must define a Python function with this signature:\n"
1760b57cec5SDimitry Andric "def my_command_impl(debugger, args, result, internal_dict):\n";
1770b57cec5SDimitry Andric
1780b57cec5SDimitry Andric class CommandObjectCommandsAlias : public CommandObjectRaw {
1790b57cec5SDimitry Andric protected:
1800b57cec5SDimitry Andric class CommandOptions : public OptionGroup {
1810b57cec5SDimitry Andric public:
CommandOptions()1820b57cec5SDimitry Andric CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
1830b57cec5SDimitry Andric
1840b57cec5SDimitry Andric ~CommandOptions() override = default;
1850b57cec5SDimitry Andric
GetDefinitions()1860b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1870b57cec5SDimitry Andric return llvm::makeArrayRef(g_alias_options);
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_value,ExecutionContext * execution_context)1900b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
1910b57cec5SDimitry Andric ExecutionContext *execution_context) override {
1920b57cec5SDimitry Andric Status error;
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric const int short_option = GetDefinitions()[option_idx].short_option;
1950b57cec5SDimitry Andric std::string option_str(option_value);
1960b57cec5SDimitry Andric
1970b57cec5SDimitry Andric switch (short_option) {
1980b57cec5SDimitry Andric case 'h':
1990b57cec5SDimitry Andric m_help.SetCurrentValue(option_str);
2000b57cec5SDimitry Andric m_help.SetOptionWasSet();
2010b57cec5SDimitry Andric break;
2020b57cec5SDimitry Andric
2030b57cec5SDimitry Andric case 'H':
2040b57cec5SDimitry Andric m_long_help.SetCurrentValue(option_str);
2050b57cec5SDimitry Andric m_long_help.SetOptionWasSet();
2060b57cec5SDimitry Andric break;
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric default:
2099dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric
2120b57cec5SDimitry Andric return error;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)2150b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
2160b57cec5SDimitry Andric m_help.Clear();
2170b57cec5SDimitry Andric m_long_help.Clear();
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric
2200b57cec5SDimitry Andric OptionValueString m_help;
2210b57cec5SDimitry Andric OptionValueString m_long_help;
2220b57cec5SDimitry Andric };
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric OptionGroupOptions m_option_group;
2250b57cec5SDimitry Andric CommandOptions m_command_options;
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric public:
GetOptions()2280b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; }
2290b57cec5SDimitry Andric
CommandObjectCommandsAlias(CommandInterpreter & interpreter)2300b57cec5SDimitry Andric CommandObjectCommandsAlias(CommandInterpreter &interpreter)
2310b57cec5SDimitry Andric : CommandObjectRaw(
2320b57cec5SDimitry Andric interpreter, "command alias",
2330b57cec5SDimitry Andric "Define a custom command in terms of an existing command."),
2340b57cec5SDimitry Andric m_option_group(), m_command_options() {
2350b57cec5SDimitry Andric m_option_group.Append(&m_command_options);
2360b57cec5SDimitry Andric m_option_group.Finalize();
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric SetHelpLong(
2390b57cec5SDimitry Andric "'alias' allows the user to create a short-cut or abbreviation for long \
2400b57cec5SDimitry Andric commands, multi-word commands, and commands that take particular options. \
2410b57cec5SDimitry Andric Below are some simple examples of how one might use the 'alias' command:"
2420b57cec5SDimitry Andric R"(
2430b57cec5SDimitry Andric
2440b57cec5SDimitry Andric (lldb) command alias sc script
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric Creates the abbreviation 'sc' for the 'script' command.
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric (lldb) command alias bp breakpoint
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric )"
2510b57cec5SDimitry Andric " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
2520b57cec5SDimitry Andric breakpoint commands are two-word commands, the user would still need to \
2530b57cec5SDimitry Andric enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
2540b57cec5SDimitry Andric R"(
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric (lldb) command alias bpl breakpoint list
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
2590b57cec5SDimitry Andric
2600b57cec5SDimitry Andric )"
2610b57cec5SDimitry Andric "An alias can include some options for the command, with the values either \
2620b57cec5SDimitry Andric filled in at the time the alias is created, or specified as positional \
2630b57cec5SDimitry Andric arguments, to be filled in when the alias is invoked. The following example \
2640b57cec5SDimitry Andric shows how to create aliases with options:"
2650b57cec5SDimitry Andric R"(
2660b57cec5SDimitry Andric
2670b57cec5SDimitry Andric (lldb) command alias bfl breakpoint set -f %1 -l %2
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric )"
2700b57cec5SDimitry Andric " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
2710b57cec5SDimitry Andric options already part of the alias. So if the user wants to set a breakpoint \
2720b57cec5SDimitry Andric by file and line without explicitly having to use the -f and -l options, the \
2730b57cec5SDimitry Andric user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
2740b57cec5SDimitry Andric for the actual arguments that will be passed when the alias command is used. \
2750b57cec5SDimitry Andric The number in the placeholder refers to the position/order the actual value \
2760b57cec5SDimitry Andric occupies when the alias is used. All the occurrences of '%1' in the alias \
2770b57cec5SDimitry Andric will be replaced with the first argument, all the occurrences of '%2' in the \
2780b57cec5SDimitry Andric alias will be replaced with the second argument, and so on. This also allows \
2790b57cec5SDimitry Andric actual arguments to be used multiple times within an alias (see 'process \
2800b57cec5SDimitry Andric launch' example below)."
2810b57cec5SDimitry Andric R"(
2820b57cec5SDimitry Andric
2830b57cec5SDimitry Andric )"
2840b57cec5SDimitry Andric "Note: the positional arguments must substitute as whole words in the resultant \
2850b57cec5SDimitry Andric command, so you can't at present do something like this to append the file extension \
2860b57cec5SDimitry Andric \".cpp\":"
2870b57cec5SDimitry Andric R"(
2880b57cec5SDimitry Andric
2890b57cec5SDimitry Andric (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
2900b57cec5SDimitry Andric
2910b57cec5SDimitry Andric )"
2920b57cec5SDimitry Andric "For more complex aliasing, use the \"command regex\" command instead. In the \
2930b57cec5SDimitry Andric 'bfl' case above, the actual file value will be filled in with the first argument \
2940b57cec5SDimitry Andric following 'bfl' and the actual line number value will be filled in with the second \
2950b57cec5SDimitry Andric argument. The user would use this alias as follows:"
2960b57cec5SDimitry Andric R"(
2970b57cec5SDimitry Andric
2980b57cec5SDimitry Andric (lldb) command alias bfl breakpoint set -f %1 -l %2
2990b57cec5SDimitry Andric (lldb) bfl my-file.c 137
3000b57cec5SDimitry Andric
3010b57cec5SDimitry Andric This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
3020b57cec5SDimitry Andric
3030b57cec5SDimitry Andric Another example:
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric (lldb) command alias pltty process launch -s -o %1 -e %1
3060b57cec5SDimitry Andric (lldb) pltty /dev/tty0
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
3090b57cec5SDimitry Andric
3100b57cec5SDimitry Andric )"
3110b57cec5SDimitry Andric "If the user always wanted to pass the same value to a particular option, the \
3120b57cec5SDimitry Andric alias could be defined with that value directly in the alias as a constant, \
3130b57cec5SDimitry Andric rather than using a positional placeholder:"
3140b57cec5SDimitry Andric R"(
3150b57cec5SDimitry Andric
3160b57cec5SDimitry Andric (lldb) command alias bl3 breakpoint set -f %1 -l 3
3170b57cec5SDimitry Andric
3180b57cec5SDimitry Andric Always sets a breakpoint on line 3 of whatever file is indicated.)");
3190b57cec5SDimitry Andric
3200b57cec5SDimitry Andric CommandArgumentEntry arg1;
3210b57cec5SDimitry Andric CommandArgumentEntry arg2;
3220b57cec5SDimitry Andric CommandArgumentEntry arg3;
3230b57cec5SDimitry Andric CommandArgumentData alias_arg;
3240b57cec5SDimitry Andric CommandArgumentData cmd_arg;
3250b57cec5SDimitry Andric CommandArgumentData options_arg;
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
3280b57cec5SDimitry Andric alias_arg.arg_type = eArgTypeAliasName;
3290b57cec5SDimitry Andric alias_arg.arg_repetition = eArgRepeatPlain;
3300b57cec5SDimitry Andric
3310b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
3320b57cec5SDimitry Andric // argument entry.
3330b57cec5SDimitry Andric arg1.push_back(alias_arg);
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
3360b57cec5SDimitry Andric cmd_arg.arg_type = eArgTypeCommandName;
3370b57cec5SDimitry Andric cmd_arg.arg_repetition = eArgRepeatPlain;
3380b57cec5SDimitry Andric
3390b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
3400b57cec5SDimitry Andric // argument entry.
3410b57cec5SDimitry Andric arg2.push_back(cmd_arg);
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
3440b57cec5SDimitry Andric options_arg.arg_type = eArgTypeAliasOptions;
3450b57cec5SDimitry Andric options_arg.arg_repetition = eArgRepeatOptional;
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
3480b57cec5SDimitry Andric // argument entry.
3490b57cec5SDimitry Andric arg3.push_back(options_arg);
3500b57cec5SDimitry Andric
3510b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
3520b57cec5SDimitry Andric m_arguments.push_back(arg1);
3530b57cec5SDimitry Andric m_arguments.push_back(arg2);
3540b57cec5SDimitry Andric m_arguments.push_back(arg3);
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
3570b57cec5SDimitry Andric ~CommandObjectCommandsAlias() override = default;
3580b57cec5SDimitry Andric
3590b57cec5SDimitry Andric protected:
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)3600b57cec5SDimitry Andric bool DoExecute(llvm::StringRef raw_command_line,
3610b57cec5SDimitry Andric CommandReturnObject &result) override {
3620b57cec5SDimitry Andric if (raw_command_line.empty()) {
3630b57cec5SDimitry Andric result.AppendError("'command alias' requires at least two arguments");
3640b57cec5SDimitry Andric return false;
3650b57cec5SDimitry Andric }
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
3680b57cec5SDimitry Andric m_option_group.NotifyOptionParsingStarting(&exe_ctx);
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric OptionsWithRaw args_with_suffix(raw_command_line);
3710b57cec5SDimitry Andric
3720b57cec5SDimitry Andric if (args_with_suffix.HasArgs())
3730b57cec5SDimitry Andric if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
3740b57cec5SDimitry Andric m_option_group, exe_ctx))
3750b57cec5SDimitry Andric return false;
3760b57cec5SDimitry Andric
3775ffd83dbSDimitry Andric llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();
3780b57cec5SDimitry Andric Args args(raw_command_string);
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric if (args.GetArgumentCount() < 2) {
3810b57cec5SDimitry Andric result.AppendError("'command alias' requires at least two arguments");
3820b57cec5SDimitry Andric return false;
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric
3850b57cec5SDimitry Andric // Get the alias command.
3860b57cec5SDimitry Andric
3879dba64beSDimitry Andric auto alias_command = args[0].ref();
3880b57cec5SDimitry Andric if (alias_command.startswith("-")) {
3890b57cec5SDimitry Andric result.AppendError("aliases starting with a dash are not supported");
3900b57cec5SDimitry Andric if (alias_command == "--help" || alias_command == "--long-help") {
3910b57cec5SDimitry Andric result.AppendWarning("if trying to pass options to 'command alias' add "
3920b57cec5SDimitry Andric "a -- at the end of the options");
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric return false;
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric
3970b57cec5SDimitry Andric // Strip the new alias name off 'raw_command_string' (leave it on args,
3980b57cec5SDimitry Andric // which gets passed to 'Execute', which does the stripping itself.
3990b57cec5SDimitry Andric size_t pos = raw_command_string.find(alias_command);
4000b57cec5SDimitry Andric if (pos == 0) {
4010b57cec5SDimitry Andric raw_command_string = raw_command_string.substr(alias_command.size());
4020b57cec5SDimitry Andric pos = raw_command_string.find_first_not_of(' ');
4030b57cec5SDimitry Andric if ((pos != std::string::npos) && (pos > 0))
4040b57cec5SDimitry Andric raw_command_string = raw_command_string.substr(pos);
4050b57cec5SDimitry Andric } else {
4060b57cec5SDimitry Andric result.AppendError("Error parsing command string. No alias created.");
4070b57cec5SDimitry Andric return false;
4080b57cec5SDimitry Andric }
4090b57cec5SDimitry Andric
4100b57cec5SDimitry Andric // Verify that the command is alias-able.
4110b57cec5SDimitry Andric if (m_interpreter.CommandExists(alias_command)) {
4120b57cec5SDimitry Andric result.AppendErrorWithFormat(
4130b57cec5SDimitry Andric "'%s' is a permanent debugger command and cannot be redefined.\n",
4140b57cec5SDimitry Andric args[0].c_str());
4150b57cec5SDimitry Andric return false;
4160b57cec5SDimitry Andric }
4170b57cec5SDimitry Andric
4180b57cec5SDimitry Andric // Get CommandObject that is being aliased. The command name is read from
4190b57cec5SDimitry Andric // the front of raw_command_string. raw_command_string is returned with the
4200b57cec5SDimitry Andric // name of the command object stripped off the front.
4210b57cec5SDimitry Andric llvm::StringRef original_raw_command_string = raw_command_string;
4220b57cec5SDimitry Andric CommandObject *cmd_obj =
4230b57cec5SDimitry Andric m_interpreter.GetCommandObjectForCommand(raw_command_string);
4240b57cec5SDimitry Andric
4250b57cec5SDimitry Andric if (!cmd_obj) {
4260b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid command given to 'command alias'. "
4270b57cec5SDimitry Andric "'%s' does not begin with a valid command."
4280b57cec5SDimitry Andric " No alias created.",
4290b57cec5SDimitry Andric original_raw_command_string.str().c_str());
4300b57cec5SDimitry Andric return false;
4310b57cec5SDimitry Andric } else if (!cmd_obj->WantsRawCommandString()) {
4320b57cec5SDimitry Andric // Note that args was initialized with the original command, and has not
4330b57cec5SDimitry Andric // been updated to this point. Therefore can we pass it to the version of
4340b57cec5SDimitry Andric // Execute that does not need/expect raw input in the alias.
4350b57cec5SDimitry Andric return HandleAliasingNormalCommand(args, result);
4360b57cec5SDimitry Andric } else {
4370b57cec5SDimitry Andric return HandleAliasingRawCommand(alias_command, raw_command_string,
4380b57cec5SDimitry Andric *cmd_obj, result);
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric return result.Succeeded();
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric
HandleAliasingRawCommand(llvm::StringRef alias_command,llvm::StringRef raw_command_string,CommandObject & cmd_obj,CommandReturnObject & result)4430b57cec5SDimitry Andric bool HandleAliasingRawCommand(llvm::StringRef alias_command,
4440b57cec5SDimitry Andric llvm::StringRef raw_command_string,
4450b57cec5SDimitry Andric CommandObject &cmd_obj,
4460b57cec5SDimitry Andric CommandReturnObject &result) {
4470b57cec5SDimitry Andric // Verify & handle any options/arguments passed to the alias command
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric OptionArgVectorSP option_arg_vector_sp =
4500b57cec5SDimitry Andric OptionArgVectorSP(new OptionArgVector);
4510b57cec5SDimitry Andric
4520b57cec5SDimitry Andric if (CommandObjectSP cmd_obj_sp =
453af732203SDimitry Andric m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName())) {
4540b57cec5SDimitry Andric if (m_interpreter.AliasExists(alias_command) ||
4550b57cec5SDimitry Andric m_interpreter.UserCommandExists(alias_command)) {
4560b57cec5SDimitry Andric result.AppendWarningWithFormat(
4570b57cec5SDimitry Andric "Overwriting existing definition for '%s'.\n",
4580b57cec5SDimitry Andric alias_command.str().c_str());
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric if (CommandAlias *alias = m_interpreter.AddAlias(
4610b57cec5SDimitry Andric alias_command, cmd_obj_sp, raw_command_string)) {
4620b57cec5SDimitry Andric if (m_command_options.m_help.OptionWasSet())
4630b57cec5SDimitry Andric alias->SetHelp(m_command_options.m_help.GetCurrentValue());
4640b57cec5SDimitry Andric if (m_command_options.m_long_help.OptionWasSet())
4650b57cec5SDimitry Andric alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
4660b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
4670b57cec5SDimitry Andric } else {
4680b57cec5SDimitry Andric result.AppendError("Unable to create requested alias.\n");
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
4710b57cec5SDimitry Andric } else {
4720b57cec5SDimitry Andric result.AppendError("Unable to create requested alias.\n");
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric
4750b57cec5SDimitry Andric return result.Succeeded();
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric
HandleAliasingNormalCommand(Args & args,CommandReturnObject & result)4780b57cec5SDimitry Andric bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
4790b57cec5SDimitry Andric size_t argc = args.GetArgumentCount();
4800b57cec5SDimitry Andric
4810b57cec5SDimitry Andric if (argc < 2) {
4820b57cec5SDimitry Andric result.AppendError("'command alias' requires at least two arguments");
4830b57cec5SDimitry Andric return false;
4840b57cec5SDimitry Andric }
4850b57cec5SDimitry Andric
4860b57cec5SDimitry Andric // Save these in std::strings since we're going to shift them off.
4875ffd83dbSDimitry Andric const std::string alias_command(std::string(args[0].ref()));
4885ffd83dbSDimitry Andric const std::string actual_command(std::string(args[1].ref()));
4890b57cec5SDimitry Andric
4900b57cec5SDimitry Andric args.Shift(); // Shift the alias command word off the argument vector.
4910b57cec5SDimitry Andric args.Shift(); // Shift the old command word off the argument vector.
4920b57cec5SDimitry Andric
4930b57cec5SDimitry Andric // Verify that the command is alias'able, and get the appropriate command
4940b57cec5SDimitry Andric // object.
4950b57cec5SDimitry Andric
4960b57cec5SDimitry Andric if (m_interpreter.CommandExists(alias_command)) {
4970b57cec5SDimitry Andric result.AppendErrorWithFormat(
4980b57cec5SDimitry Andric "'%s' is a permanent debugger command and cannot be redefined.\n",
4990b57cec5SDimitry Andric alias_command.c_str());
5000b57cec5SDimitry Andric return false;
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric
5030b57cec5SDimitry Andric CommandObjectSP command_obj_sp(
5040b57cec5SDimitry Andric m_interpreter.GetCommandSPExact(actual_command, true));
5050b57cec5SDimitry Andric CommandObjectSP subcommand_obj_sp;
5060b57cec5SDimitry Andric bool use_subcommand = false;
5070b57cec5SDimitry Andric if (!command_obj_sp) {
5080b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' is not an existing command.\n",
5090b57cec5SDimitry Andric actual_command.c_str());
5100b57cec5SDimitry Andric return false;
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric CommandObject *cmd_obj = command_obj_sp.get();
5130b57cec5SDimitry Andric CommandObject *sub_cmd_obj = nullptr;
5140b57cec5SDimitry Andric OptionArgVectorSP option_arg_vector_sp =
5150b57cec5SDimitry Andric OptionArgVectorSP(new OptionArgVector);
5160b57cec5SDimitry Andric
5170b57cec5SDimitry Andric while (cmd_obj->IsMultiwordObject() && !args.empty()) {
5189dba64beSDimitry Andric auto sub_command = args[0].ref();
5190b57cec5SDimitry Andric assert(!sub_command.empty());
5200b57cec5SDimitry Andric subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
5210b57cec5SDimitry Andric if (!subcommand_obj_sp) {
5220b57cec5SDimitry Andric result.AppendErrorWithFormat(
5230b57cec5SDimitry Andric "'%s' is not a valid sub-command of '%s'. "
5240b57cec5SDimitry Andric "Unable to create alias.\n",
5250b57cec5SDimitry Andric args[0].c_str(), actual_command.c_str());
5260b57cec5SDimitry Andric return false;
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric sub_cmd_obj = subcommand_obj_sp.get();
5300b57cec5SDimitry Andric use_subcommand = true;
5310b57cec5SDimitry Andric args.Shift(); // Shift the sub_command word off the argument vector.
5320b57cec5SDimitry Andric cmd_obj = sub_cmd_obj;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
5350b57cec5SDimitry Andric // Verify & handle any options/arguments passed to the alias command
5360b57cec5SDimitry Andric
5370b57cec5SDimitry Andric std::string args_string;
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andric if (!args.empty()) {
5400b57cec5SDimitry Andric CommandObjectSP tmp_sp =
541af732203SDimitry Andric m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName());
5420b57cec5SDimitry Andric if (use_subcommand)
543af732203SDimitry Andric tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andric args.GetCommandString(args_string);
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric
5480b57cec5SDimitry Andric if (m_interpreter.AliasExists(alias_command) ||
5490b57cec5SDimitry Andric m_interpreter.UserCommandExists(alias_command)) {
5500b57cec5SDimitry Andric result.AppendWarningWithFormat(
5510b57cec5SDimitry Andric "Overwriting existing definition for '%s'.\n", alias_command.c_str());
5520b57cec5SDimitry Andric }
5530b57cec5SDimitry Andric
5540b57cec5SDimitry Andric if (CommandAlias *alias = m_interpreter.AddAlias(
5550b57cec5SDimitry Andric alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
5560b57cec5SDimitry Andric args_string)) {
5570b57cec5SDimitry Andric if (m_command_options.m_help.OptionWasSet())
5580b57cec5SDimitry Andric alias->SetHelp(m_command_options.m_help.GetCurrentValue());
5590b57cec5SDimitry Andric if (m_command_options.m_long_help.OptionWasSet())
5600b57cec5SDimitry Andric alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
5610b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
5620b57cec5SDimitry Andric } else {
5630b57cec5SDimitry Andric result.AppendError("Unable to create requested alias.\n");
5640b57cec5SDimitry Andric return false;
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric
5670b57cec5SDimitry Andric return result.Succeeded();
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric };
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric #pragma mark CommandObjectCommandsUnalias
5720b57cec5SDimitry Andric // CommandObjectCommandsUnalias
5730b57cec5SDimitry Andric
5740b57cec5SDimitry Andric class CommandObjectCommandsUnalias : public CommandObjectParsed {
5750b57cec5SDimitry Andric public:
CommandObjectCommandsUnalias(CommandInterpreter & interpreter)5760b57cec5SDimitry Andric CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
5770b57cec5SDimitry Andric : CommandObjectParsed(
5780b57cec5SDimitry Andric interpreter, "command unalias",
5790b57cec5SDimitry Andric "Delete one or more custom commands defined by 'command alias'.",
5800b57cec5SDimitry Andric nullptr) {
5810b57cec5SDimitry Andric CommandArgumentEntry arg;
5820b57cec5SDimitry Andric CommandArgumentData alias_arg;
5830b57cec5SDimitry Andric
5840b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
5850b57cec5SDimitry Andric alias_arg.arg_type = eArgTypeAliasName;
5860b57cec5SDimitry Andric alias_arg.arg_repetition = eArgRepeatPlain;
5870b57cec5SDimitry Andric
5880b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
5890b57cec5SDimitry Andric // argument entry.
5900b57cec5SDimitry Andric arg.push_back(alias_arg);
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
5930b57cec5SDimitry Andric m_arguments.push_back(arg);
5940b57cec5SDimitry Andric }
5950b57cec5SDimitry Andric
5960b57cec5SDimitry Andric ~CommandObjectCommandsUnalias() override = default;
5970b57cec5SDimitry Andric
598af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)599af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
600af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
601af732203SDimitry Andric if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
602af732203SDimitry Andric return;
603af732203SDimitry Andric
604af732203SDimitry Andric for (const auto &ent : m_interpreter.GetAliases()) {
605af732203SDimitry Andric request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
606af732203SDimitry Andric }
607af732203SDimitry Andric }
608af732203SDimitry Andric
6090b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)6100b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
6110b57cec5SDimitry Andric CommandObject::CommandMap::iterator pos;
6120b57cec5SDimitry Andric CommandObject *cmd_obj;
6130b57cec5SDimitry Andric
6140b57cec5SDimitry Andric if (args.empty()) {
6150b57cec5SDimitry Andric result.AppendError("must call 'unalias' with a valid alias");
6160b57cec5SDimitry Andric return false;
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric
6199dba64beSDimitry Andric auto command_name = args[0].ref();
6200b57cec5SDimitry Andric cmd_obj = m_interpreter.GetCommandObject(command_name);
6210b57cec5SDimitry Andric if (!cmd_obj) {
6220b57cec5SDimitry Andric result.AppendErrorWithFormat(
6230b57cec5SDimitry Andric "'%s' is not a known command.\nTry 'help' to see a "
6240b57cec5SDimitry Andric "current list of commands.\n",
6250b57cec5SDimitry Andric args[0].c_str());
6260b57cec5SDimitry Andric return false;
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric
6290b57cec5SDimitry Andric if (m_interpreter.CommandExists(command_name)) {
6300b57cec5SDimitry Andric if (cmd_obj->IsRemovable()) {
6310b57cec5SDimitry Andric result.AppendErrorWithFormat(
6320b57cec5SDimitry Andric "'%s' is not an alias, it is a debugger command which can be "
6330b57cec5SDimitry Andric "removed using the 'command delete' command.\n",
6340b57cec5SDimitry Andric args[0].c_str());
6350b57cec5SDimitry Andric } else {
6360b57cec5SDimitry Andric result.AppendErrorWithFormat(
6370b57cec5SDimitry Andric "'%s' is a permanent debugger command and cannot be removed.\n",
6380b57cec5SDimitry Andric args[0].c_str());
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric return false;
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric
6430b57cec5SDimitry Andric if (!m_interpreter.RemoveAlias(command_name)) {
6440b57cec5SDimitry Andric if (m_interpreter.AliasExists(command_name))
6450b57cec5SDimitry Andric result.AppendErrorWithFormat(
6460b57cec5SDimitry Andric "Error occurred while attempting to unalias '%s'.\n",
6470b57cec5SDimitry Andric args[0].c_str());
6480b57cec5SDimitry Andric else
6490b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
6500b57cec5SDimitry Andric args[0].c_str());
6510b57cec5SDimitry Andric return false;
6520b57cec5SDimitry Andric }
6530b57cec5SDimitry Andric
6540b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
6550b57cec5SDimitry Andric return result.Succeeded();
6560b57cec5SDimitry Andric }
6570b57cec5SDimitry Andric };
6580b57cec5SDimitry Andric
6590b57cec5SDimitry Andric #pragma mark CommandObjectCommandsDelete
6600b57cec5SDimitry Andric // CommandObjectCommandsDelete
6610b57cec5SDimitry Andric
6620b57cec5SDimitry Andric class CommandObjectCommandsDelete : public CommandObjectParsed {
6630b57cec5SDimitry Andric public:
CommandObjectCommandsDelete(CommandInterpreter & interpreter)6640b57cec5SDimitry Andric CommandObjectCommandsDelete(CommandInterpreter &interpreter)
6650b57cec5SDimitry Andric : CommandObjectParsed(
6660b57cec5SDimitry Andric interpreter, "command delete",
6670b57cec5SDimitry Andric "Delete one or more custom commands defined by 'command regex'.",
6680b57cec5SDimitry Andric nullptr) {
6690b57cec5SDimitry Andric CommandArgumentEntry arg;
6700b57cec5SDimitry Andric CommandArgumentData alias_arg;
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
6730b57cec5SDimitry Andric alias_arg.arg_type = eArgTypeCommandName;
6740b57cec5SDimitry Andric alias_arg.arg_repetition = eArgRepeatPlain;
6750b57cec5SDimitry Andric
6760b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
6770b57cec5SDimitry Andric // argument entry.
6780b57cec5SDimitry Andric arg.push_back(alias_arg);
6790b57cec5SDimitry Andric
6800b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
6810b57cec5SDimitry Andric m_arguments.push_back(arg);
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric
6840b57cec5SDimitry Andric ~CommandObjectCommandsDelete() override = default;
6850b57cec5SDimitry Andric
686af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)687af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
688af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
689af732203SDimitry Andric if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
690af732203SDimitry Andric return;
691af732203SDimitry Andric
692af732203SDimitry Andric for (const auto &ent : m_interpreter.GetCommands()) {
693af732203SDimitry Andric if (ent.second->IsRemovable())
694af732203SDimitry Andric request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
695af732203SDimitry Andric }
696af732203SDimitry Andric }
697af732203SDimitry Andric
6980b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)6990b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
7000b57cec5SDimitry Andric CommandObject::CommandMap::iterator pos;
7010b57cec5SDimitry Andric
7020b57cec5SDimitry Andric if (args.empty()) {
7030b57cec5SDimitry Andric result.AppendErrorWithFormat("must call '%s' with one or more valid user "
7040b57cec5SDimitry Andric "defined regular expression command names",
7050b57cec5SDimitry Andric GetCommandName().str().c_str());
7069dba64beSDimitry Andric return false;
7070b57cec5SDimitry Andric }
7080b57cec5SDimitry Andric
7099dba64beSDimitry Andric auto command_name = args[0].ref();
7100b57cec5SDimitry Andric if (!m_interpreter.CommandExists(command_name)) {
7110b57cec5SDimitry Andric StreamString error_msg_stream;
7120b57cec5SDimitry Andric const bool generate_upropos = true;
7130b57cec5SDimitry Andric const bool generate_type_lookup = false;
7140b57cec5SDimitry Andric CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
7150b57cec5SDimitry Andric &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
7160b57cec5SDimitry Andric generate_upropos, generate_type_lookup);
7170b57cec5SDimitry Andric result.AppendError(error_msg_stream.GetString());
7180b57cec5SDimitry Andric return false;
7190b57cec5SDimitry Andric }
7200b57cec5SDimitry Andric
7210b57cec5SDimitry Andric if (!m_interpreter.RemoveCommand(command_name)) {
7220b57cec5SDimitry Andric result.AppendErrorWithFormat(
7230b57cec5SDimitry Andric "'%s' is a permanent debugger command and cannot be removed.\n",
7240b57cec5SDimitry Andric args[0].c_str());
7250b57cec5SDimitry Andric return false;
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric
7280b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
7290b57cec5SDimitry Andric return true;
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric };
7320b57cec5SDimitry Andric
7330b57cec5SDimitry Andric // CommandObjectCommandsAddRegex
7340b57cec5SDimitry Andric
7359dba64beSDimitry Andric #define LLDB_OPTIONS_regex
7369dba64beSDimitry Andric #include "CommandOptions.inc"
7370b57cec5SDimitry Andric
7380b57cec5SDimitry Andric #pragma mark CommandObjectCommandsAddRegex
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric class CommandObjectCommandsAddRegex : public CommandObjectParsed,
7410b57cec5SDimitry Andric public IOHandlerDelegateMultiline {
7420b57cec5SDimitry Andric public:
CommandObjectCommandsAddRegex(CommandInterpreter & interpreter)7430b57cec5SDimitry Andric CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
7440b57cec5SDimitry Andric : CommandObjectParsed(
745480093f4SDimitry Andric interpreter, "command regex",
746480093f4SDimitry Andric "Define a custom command in terms of "
7470b57cec5SDimitry Andric "existing commands by matching "
7480b57cec5SDimitry Andric "regular expressions.",
7490b57cec5SDimitry Andric "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
7500b57cec5SDimitry Andric IOHandlerDelegateMultiline("",
7510b57cec5SDimitry Andric IOHandlerDelegate::Completion::LLDBCommand),
7520b57cec5SDimitry Andric m_options() {
7530b57cec5SDimitry Andric SetHelpLong(
7540b57cec5SDimitry Andric R"(
7550b57cec5SDimitry Andric )"
7560b57cec5SDimitry Andric "This command allows the user to create powerful regular expression commands \
7570b57cec5SDimitry Andric with substitutions. The regular expressions and substitutions are specified \
7580b57cec5SDimitry Andric using the regular expression substitution format of:"
7590b57cec5SDimitry Andric R"(
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric s/<regex>/<subst>/
7620b57cec5SDimitry Andric
7630b57cec5SDimitry Andric )"
7640b57cec5SDimitry Andric "<regex> is a regular expression that can use parenthesis to capture regular \
7650b57cec5SDimitry Andric expression input and substitute the captured matches in the output using %1 \
7660b57cec5SDimitry Andric for the first match, %2 for the second, and so on."
7670b57cec5SDimitry Andric R"(
7680b57cec5SDimitry Andric
7690b57cec5SDimitry Andric )"
7700b57cec5SDimitry Andric "The regular expressions can all be specified on the command line if more than \
7710b57cec5SDimitry Andric one argument is provided. If just the command name is provided on the command \
7720b57cec5SDimitry Andric line, then the regular expressions and substitutions can be entered on separate \
7730b57cec5SDimitry Andric lines, followed by an empty line to terminate the command definition."
7740b57cec5SDimitry Andric R"(
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric EXAMPLES
7770b57cec5SDimitry Andric
7780b57cec5SDimitry Andric )"
7790b57cec5SDimitry Andric "The following example will define a regular expression command named 'f' that \
7800b57cec5SDimitry Andric will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
7810b57cec5SDimitry Andric a number follows 'f':"
7820b57cec5SDimitry Andric R"(
7830b57cec5SDimitry Andric
7840b57cec5SDimitry Andric (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
7850b57cec5SDimitry Andric }
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric ~CommandObjectCommandsAddRegex() override = default;
7880b57cec5SDimitry Andric
7890b57cec5SDimitry Andric protected:
IOHandlerActivated(IOHandler & io_handler,bool interactive)7900b57cec5SDimitry Andric void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
7919dba64beSDimitry Andric StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
7920b57cec5SDimitry Andric if (output_sp && interactive) {
7930b57cec5SDimitry Andric output_sp->PutCString("Enter one or more sed substitution commands in "
7940b57cec5SDimitry Andric "the form: 's/<regex>/<subst>/'.\nTerminate the "
7950b57cec5SDimitry Andric "substitution list with an empty line.\n");
7960b57cec5SDimitry Andric output_sp->Flush();
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric
IOHandlerInputComplete(IOHandler & io_handler,std::string & data)8000b57cec5SDimitry Andric void IOHandlerInputComplete(IOHandler &io_handler,
8010b57cec5SDimitry Andric std::string &data) override {
8020b57cec5SDimitry Andric io_handler.SetIsDone(true);
8030b57cec5SDimitry Andric if (m_regex_cmd_up) {
8040b57cec5SDimitry Andric StringList lines;
8050b57cec5SDimitry Andric if (lines.SplitIntoLines(data)) {
8060b57cec5SDimitry Andric bool check_only = false;
8079dba64beSDimitry Andric for (const std::string &line : lines) {
8089dba64beSDimitry Andric Status error = AppendRegexSubstitution(line, check_only);
8090b57cec5SDimitry Andric if (error.Fail()) {
8100b57cec5SDimitry Andric if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
8110b57cec5SDimitry Andric StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
8120b57cec5SDimitry Andric out_stream->Printf("error: %s\n", error.AsCString());
8130b57cec5SDimitry Andric }
8140b57cec5SDimitry Andric }
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric }
8170b57cec5SDimitry Andric if (m_regex_cmd_up->HasRegexEntries()) {
8180b57cec5SDimitry Andric CommandObjectSP cmd_sp(m_regex_cmd_up.release());
8190b57cec5SDimitry Andric m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
8200b57cec5SDimitry Andric }
8210b57cec5SDimitry Andric }
8220b57cec5SDimitry Andric }
8230b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)8240b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
8250b57cec5SDimitry Andric const size_t argc = command.GetArgumentCount();
8260b57cec5SDimitry Andric if (argc == 0) {
8270b57cec5SDimitry Andric result.AppendError("usage: 'command regex <command-name> "
8280b57cec5SDimitry Andric "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
8290b57cec5SDimitry Andric return false;
8300b57cec5SDimitry Andric }
8310b57cec5SDimitry Andric
8320b57cec5SDimitry Andric Status error;
8339dba64beSDimitry Andric auto name = command[0].ref();
8349dba64beSDimitry Andric m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
8350b57cec5SDimitry Andric m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
8360b57cec5SDimitry Andric true);
8370b57cec5SDimitry Andric
8380b57cec5SDimitry Andric if (argc == 1) {
8390b57cec5SDimitry Andric Debugger &debugger = GetDebugger();
8400b57cec5SDimitry Andric bool color_prompt = debugger.GetUseColor();
8410b57cec5SDimitry Andric const bool multiple_lines = true; // Get multiple lines
8420b57cec5SDimitry Andric IOHandlerSP io_handler_sp(new IOHandlerEditline(
8430b57cec5SDimitry Andric debugger, IOHandler::Type::Other,
8440b57cec5SDimitry Andric "lldb-regex", // Name of input reader for history
8450b57cec5SDimitry Andric llvm::StringRef("> "), // Prompt
8460b57cec5SDimitry Andric llvm::StringRef(), // Continuation prompt
8470b57cec5SDimitry Andric multiple_lines, color_prompt,
8480b57cec5SDimitry Andric 0, // Don't show line numbers
8490b57cec5SDimitry Andric *this, nullptr));
8500b57cec5SDimitry Andric
8510b57cec5SDimitry Andric if (io_handler_sp) {
8525ffd83dbSDimitry Andric debugger.RunIOHandlerAsync(io_handler_sp);
8530b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
8540b57cec5SDimitry Andric }
8550b57cec5SDimitry Andric } else {
8560b57cec5SDimitry Andric for (auto &entry : command.entries().drop_front()) {
8570b57cec5SDimitry Andric bool check_only = false;
8589dba64beSDimitry Andric error = AppendRegexSubstitution(entry.ref(), check_only);
8590b57cec5SDimitry Andric if (error.Fail())
8600b57cec5SDimitry Andric break;
8610b57cec5SDimitry Andric }
8620b57cec5SDimitry Andric
8630b57cec5SDimitry Andric if (error.Success()) {
8640b57cec5SDimitry Andric AddRegexCommandToInterpreter();
8650b57cec5SDimitry Andric }
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric if (error.Fail()) {
8680b57cec5SDimitry Andric result.AppendError(error.AsCString());
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric
8710b57cec5SDimitry Andric return result.Succeeded();
8720b57cec5SDimitry Andric }
8730b57cec5SDimitry Andric
AppendRegexSubstitution(const llvm::StringRef & regex_sed,bool check_only)8740b57cec5SDimitry Andric Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed,
8750b57cec5SDimitry Andric bool check_only) {
8760b57cec5SDimitry Andric Status error;
8770b57cec5SDimitry Andric
8780b57cec5SDimitry Andric if (!m_regex_cmd_up) {
8790b57cec5SDimitry Andric error.SetErrorStringWithFormat(
8800b57cec5SDimitry Andric "invalid regular expression command object for: '%.*s'",
8810b57cec5SDimitry Andric (int)regex_sed.size(), regex_sed.data());
8820b57cec5SDimitry Andric return error;
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric
8850b57cec5SDimitry Andric size_t regex_sed_size = regex_sed.size();
8860b57cec5SDimitry Andric
8870b57cec5SDimitry Andric if (regex_sed_size <= 1) {
8880b57cec5SDimitry Andric error.SetErrorStringWithFormat(
8890b57cec5SDimitry Andric "regular expression substitution string is too short: '%.*s'",
8900b57cec5SDimitry Andric (int)regex_sed.size(), regex_sed.data());
8910b57cec5SDimitry Andric return error;
8920b57cec5SDimitry Andric }
8930b57cec5SDimitry Andric
8940b57cec5SDimitry Andric if (regex_sed[0] != 's') {
8950b57cec5SDimitry Andric error.SetErrorStringWithFormat("regular expression substitution string "
8960b57cec5SDimitry Andric "doesn't start with 's': '%.*s'",
8970b57cec5SDimitry Andric (int)regex_sed.size(), regex_sed.data());
8980b57cec5SDimitry Andric return error;
8990b57cec5SDimitry Andric }
9000b57cec5SDimitry Andric const size_t first_separator_char_pos = 1;
9010b57cec5SDimitry Andric // use the char that follows 's' as the regex separator character so we can
9020b57cec5SDimitry Andric // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
9030b57cec5SDimitry Andric const char separator_char = regex_sed[first_separator_char_pos];
9040b57cec5SDimitry Andric const size_t second_separator_char_pos =
9050b57cec5SDimitry Andric regex_sed.find(separator_char, first_separator_char_pos + 1);
9060b57cec5SDimitry Andric
9070b57cec5SDimitry Andric if (second_separator_char_pos == std::string::npos) {
9080b57cec5SDimitry Andric error.SetErrorStringWithFormat(
9090b57cec5SDimitry Andric "missing second '%c' separator char after '%.*s' in '%.*s'",
9100b57cec5SDimitry Andric separator_char,
9110b57cec5SDimitry Andric (int)(regex_sed.size() - first_separator_char_pos - 1),
9120b57cec5SDimitry Andric regex_sed.data() + (first_separator_char_pos + 1),
9130b57cec5SDimitry Andric (int)regex_sed.size(), regex_sed.data());
9140b57cec5SDimitry Andric return error;
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric
9170b57cec5SDimitry Andric const size_t third_separator_char_pos =
9180b57cec5SDimitry Andric regex_sed.find(separator_char, second_separator_char_pos + 1);
9190b57cec5SDimitry Andric
9200b57cec5SDimitry Andric if (third_separator_char_pos == std::string::npos) {
9210b57cec5SDimitry Andric error.SetErrorStringWithFormat(
9220b57cec5SDimitry Andric "missing third '%c' separator char after '%.*s' in '%.*s'",
9230b57cec5SDimitry Andric separator_char,
9240b57cec5SDimitry Andric (int)(regex_sed.size() - second_separator_char_pos - 1),
9250b57cec5SDimitry Andric regex_sed.data() + (second_separator_char_pos + 1),
9260b57cec5SDimitry Andric (int)regex_sed.size(), regex_sed.data());
9270b57cec5SDimitry Andric return error;
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric
9300b57cec5SDimitry Andric if (third_separator_char_pos != regex_sed_size - 1) {
9310b57cec5SDimitry Andric // Make sure that everything that follows the last regex separator char
9320b57cec5SDimitry Andric if (regex_sed.find_first_not_of("\t\n\v\f\r ",
9330b57cec5SDimitry Andric third_separator_char_pos + 1) !=
9340b57cec5SDimitry Andric std::string::npos) {
9350b57cec5SDimitry Andric error.SetErrorStringWithFormat(
9360b57cec5SDimitry Andric "extra data found after the '%.*s' regular expression substitution "
9370b57cec5SDimitry Andric "string: '%.*s'",
9380b57cec5SDimitry Andric (int)third_separator_char_pos + 1, regex_sed.data(),
9390b57cec5SDimitry Andric (int)(regex_sed.size() - third_separator_char_pos - 1),
9400b57cec5SDimitry Andric regex_sed.data() + (third_separator_char_pos + 1));
9410b57cec5SDimitry Andric return error;
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
9440b57cec5SDimitry Andric error.SetErrorStringWithFormat(
9450b57cec5SDimitry Andric "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
9460b57cec5SDimitry Andric separator_char, separator_char, separator_char, (int)regex_sed.size(),
9470b57cec5SDimitry Andric regex_sed.data());
9480b57cec5SDimitry Andric return error;
9490b57cec5SDimitry Andric } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
9500b57cec5SDimitry Andric error.SetErrorStringWithFormat(
9510b57cec5SDimitry Andric "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
9520b57cec5SDimitry Andric separator_char, separator_char, separator_char, (int)regex_sed.size(),
9530b57cec5SDimitry Andric regex_sed.data());
9540b57cec5SDimitry Andric return error;
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andric if (!check_only) {
9585ffd83dbSDimitry Andric std::string regex(std::string(regex_sed.substr(
9595ffd83dbSDimitry Andric first_separator_char_pos + 1,
9605ffd83dbSDimitry Andric second_separator_char_pos - first_separator_char_pos - 1)));
9615ffd83dbSDimitry Andric std::string subst(std::string(regex_sed.substr(
9625ffd83dbSDimitry Andric second_separator_char_pos + 1,
9635ffd83dbSDimitry Andric third_separator_char_pos - second_separator_char_pos - 1)));
964af732203SDimitry Andric m_regex_cmd_up->AddRegexCommand(regex, subst);
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric return error;
9670b57cec5SDimitry Andric }
9680b57cec5SDimitry Andric
AddRegexCommandToInterpreter()9690b57cec5SDimitry Andric void AddRegexCommandToInterpreter() {
9700b57cec5SDimitry Andric if (m_regex_cmd_up) {
9710b57cec5SDimitry Andric if (m_regex_cmd_up->HasRegexEntries()) {
9720b57cec5SDimitry Andric CommandObjectSP cmd_sp(m_regex_cmd_up.release());
9730b57cec5SDimitry Andric m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
9740b57cec5SDimitry Andric }
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric
9780b57cec5SDimitry Andric private:
9790b57cec5SDimitry Andric std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
9800b57cec5SDimitry Andric
9810b57cec5SDimitry Andric class CommandOptions : public Options {
9820b57cec5SDimitry Andric public:
CommandOptions()9830b57cec5SDimitry Andric CommandOptions() : Options() {}
9840b57cec5SDimitry Andric
9850b57cec5SDimitry Andric ~CommandOptions() override = default;
9860b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)9870b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
9880b57cec5SDimitry Andric ExecutionContext *execution_context) override {
9890b57cec5SDimitry Andric Status error;
9900b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
9910b57cec5SDimitry Andric
9920b57cec5SDimitry Andric switch (short_option) {
9930b57cec5SDimitry Andric case 'h':
9945ffd83dbSDimitry Andric m_help.assign(std::string(option_arg));
9950b57cec5SDimitry Andric break;
9960b57cec5SDimitry Andric case 's':
9975ffd83dbSDimitry Andric m_syntax.assign(std::string(option_arg));
9980b57cec5SDimitry Andric break;
9990b57cec5SDimitry Andric default:
10009dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric
10030b57cec5SDimitry Andric return error;
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)10060b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
10070b57cec5SDimitry Andric m_help.clear();
10080b57cec5SDimitry Andric m_syntax.clear();
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric
GetDefinitions()10110b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
10120b57cec5SDimitry Andric return llvm::makeArrayRef(g_regex_options);
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric
GetHelp()10155ffd83dbSDimitry Andric llvm::StringRef GetHelp() { return m_help; }
10160b57cec5SDimitry Andric
GetSyntax()10175ffd83dbSDimitry Andric llvm::StringRef GetSyntax() { return m_syntax; }
10180b57cec5SDimitry Andric
10190b57cec5SDimitry Andric protected:
10200b57cec5SDimitry Andric // Instance variables to hold the values for command options.
10210b57cec5SDimitry Andric
10220b57cec5SDimitry Andric std::string m_help;
10230b57cec5SDimitry Andric std::string m_syntax;
10240b57cec5SDimitry Andric };
10250b57cec5SDimitry Andric
GetOptions()10260b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
10270b57cec5SDimitry Andric
10280b57cec5SDimitry Andric CommandOptions m_options;
10290b57cec5SDimitry Andric };
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andric class CommandObjectPythonFunction : public CommandObjectRaw {
10320b57cec5SDimitry Andric public:
CommandObjectPythonFunction(CommandInterpreter & interpreter,std::string name,std::string funct,std::string help,ScriptedCommandSynchronicity synch)10330b57cec5SDimitry Andric CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
10340b57cec5SDimitry Andric std::string funct, std::string help,
10350b57cec5SDimitry Andric ScriptedCommandSynchronicity synch)
1036480093f4SDimitry Andric : CommandObjectRaw(interpreter, name), m_function_name(funct),
1037480093f4SDimitry Andric m_synchro(synch), m_fetched_help_long(false) {
10380b57cec5SDimitry Andric if (!help.empty())
10390b57cec5SDimitry Andric SetHelp(help);
10400b57cec5SDimitry Andric else {
10410b57cec5SDimitry Andric StreamString stream;
10420b57cec5SDimitry Andric stream.Printf("For more information run 'help %s'", name.c_str());
10430b57cec5SDimitry Andric SetHelp(stream.GetString());
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric
10470b57cec5SDimitry Andric ~CommandObjectPythonFunction() override = default;
10480b57cec5SDimitry Andric
IsRemovable() const10490b57cec5SDimitry Andric bool IsRemovable() const override { return true; }
10500b57cec5SDimitry Andric
GetFunctionName()10510b57cec5SDimitry Andric const std::string &GetFunctionName() { return m_function_name; }
10520b57cec5SDimitry Andric
GetSynchronicity()10530b57cec5SDimitry Andric ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
10540b57cec5SDimitry Andric
GetHelpLong()10550b57cec5SDimitry Andric llvm::StringRef GetHelpLong() override {
10560b57cec5SDimitry Andric if (m_fetched_help_long)
10570b57cec5SDimitry Andric return CommandObjectRaw::GetHelpLong();
10580b57cec5SDimitry Andric
10590b57cec5SDimitry Andric ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
10600b57cec5SDimitry Andric if (!scripter)
10610b57cec5SDimitry Andric return CommandObjectRaw::GetHelpLong();
10620b57cec5SDimitry Andric
10630b57cec5SDimitry Andric std::string docstring;
10640b57cec5SDimitry Andric m_fetched_help_long =
10650b57cec5SDimitry Andric scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
10660b57cec5SDimitry Andric if (!docstring.empty())
10670b57cec5SDimitry Andric SetHelpLong(docstring);
10680b57cec5SDimitry Andric return CommandObjectRaw::GetHelpLong();
10690b57cec5SDimitry Andric }
10700b57cec5SDimitry Andric
10710b57cec5SDimitry Andric protected:
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)10720b57cec5SDimitry Andric bool DoExecute(llvm::StringRef raw_command_line,
10730b57cec5SDimitry Andric CommandReturnObject &result) override {
10740b57cec5SDimitry Andric ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
10750b57cec5SDimitry Andric
10760b57cec5SDimitry Andric Status error;
10770b57cec5SDimitry Andric
10780b57cec5SDimitry Andric result.SetStatus(eReturnStatusInvalid);
10790b57cec5SDimitry Andric
1080480093f4SDimitry Andric if (!scripter || !scripter->RunScriptBasedCommand(
1081480093f4SDimitry Andric m_function_name.c_str(), raw_command_line, m_synchro,
1082480093f4SDimitry Andric result, error, m_exe_ctx)) {
10830b57cec5SDimitry Andric result.AppendError(error.AsCString());
10840b57cec5SDimitry Andric } else {
10850b57cec5SDimitry Andric // Don't change the status if the command already set it...
10860b57cec5SDimitry Andric if (result.GetStatus() == eReturnStatusInvalid) {
10870b57cec5SDimitry Andric if (result.GetOutputData().empty())
10880b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
10890b57cec5SDimitry Andric else
10900b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric }
10930b57cec5SDimitry Andric
10940b57cec5SDimitry Andric return result.Succeeded();
10950b57cec5SDimitry Andric }
10960b57cec5SDimitry Andric
10970b57cec5SDimitry Andric private:
10980b57cec5SDimitry Andric std::string m_function_name;
10990b57cec5SDimitry Andric ScriptedCommandSynchronicity m_synchro;
11000b57cec5SDimitry Andric bool m_fetched_help_long;
11010b57cec5SDimitry Andric };
11020b57cec5SDimitry Andric
11030b57cec5SDimitry Andric class CommandObjectScriptingObject : public CommandObjectRaw {
11040b57cec5SDimitry Andric public:
CommandObjectScriptingObject(CommandInterpreter & interpreter,std::string name,StructuredData::GenericSP cmd_obj_sp,ScriptedCommandSynchronicity synch)11050b57cec5SDimitry Andric CommandObjectScriptingObject(CommandInterpreter &interpreter,
11060b57cec5SDimitry Andric std::string name,
11070b57cec5SDimitry Andric StructuredData::GenericSP cmd_obj_sp,
11080b57cec5SDimitry Andric ScriptedCommandSynchronicity synch)
1109480093f4SDimitry Andric : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1110480093f4SDimitry Andric m_synchro(synch), m_fetched_help_short(false),
11110b57cec5SDimitry Andric m_fetched_help_long(false) {
11120b57cec5SDimitry Andric StreamString stream;
11130b57cec5SDimitry Andric stream.Printf("For more information run 'help %s'", name.c_str());
11140b57cec5SDimitry Andric SetHelp(stream.GetString());
11150b57cec5SDimitry Andric if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
11160b57cec5SDimitry Andric GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
11170b57cec5SDimitry Andric }
11180b57cec5SDimitry Andric
11190b57cec5SDimitry Andric ~CommandObjectScriptingObject() override = default;
11200b57cec5SDimitry Andric
IsRemovable() const11210b57cec5SDimitry Andric bool IsRemovable() const override { return true; }
11220b57cec5SDimitry Andric
GetSynchronicity()11230b57cec5SDimitry Andric ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
11240b57cec5SDimitry Andric
GetHelp()11250b57cec5SDimitry Andric llvm::StringRef GetHelp() override {
11260b57cec5SDimitry Andric if (m_fetched_help_short)
11270b57cec5SDimitry Andric return CommandObjectRaw::GetHelp();
11280b57cec5SDimitry Andric ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
11290b57cec5SDimitry Andric if (!scripter)
11300b57cec5SDimitry Andric return CommandObjectRaw::GetHelp();
11310b57cec5SDimitry Andric std::string docstring;
11320b57cec5SDimitry Andric m_fetched_help_short =
11330b57cec5SDimitry Andric scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
11340b57cec5SDimitry Andric if (!docstring.empty())
11350b57cec5SDimitry Andric SetHelp(docstring);
11360b57cec5SDimitry Andric
11370b57cec5SDimitry Andric return CommandObjectRaw::GetHelp();
11380b57cec5SDimitry Andric }
11390b57cec5SDimitry Andric
GetHelpLong()11400b57cec5SDimitry Andric llvm::StringRef GetHelpLong() override {
11410b57cec5SDimitry Andric if (m_fetched_help_long)
11420b57cec5SDimitry Andric return CommandObjectRaw::GetHelpLong();
11430b57cec5SDimitry Andric
11440b57cec5SDimitry Andric ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
11450b57cec5SDimitry Andric if (!scripter)
11460b57cec5SDimitry Andric return CommandObjectRaw::GetHelpLong();
11470b57cec5SDimitry Andric
11480b57cec5SDimitry Andric std::string docstring;
11490b57cec5SDimitry Andric m_fetched_help_long =
11500b57cec5SDimitry Andric scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
11510b57cec5SDimitry Andric if (!docstring.empty())
11520b57cec5SDimitry Andric SetHelpLong(docstring);
11530b57cec5SDimitry Andric return CommandObjectRaw::GetHelpLong();
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andric protected:
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)11570b57cec5SDimitry Andric bool DoExecute(llvm::StringRef raw_command_line,
11580b57cec5SDimitry Andric CommandReturnObject &result) override {
11590b57cec5SDimitry Andric ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
11600b57cec5SDimitry Andric
11610b57cec5SDimitry Andric Status error;
11620b57cec5SDimitry Andric
11630b57cec5SDimitry Andric result.SetStatus(eReturnStatusInvalid);
11640b57cec5SDimitry Andric
11650b57cec5SDimitry Andric if (!scripter ||
11660b57cec5SDimitry Andric !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
11670b57cec5SDimitry Andric m_synchro, result, error, m_exe_ctx)) {
11680b57cec5SDimitry Andric result.AppendError(error.AsCString());
11690b57cec5SDimitry Andric } else {
11700b57cec5SDimitry Andric // Don't change the status if the command already set it...
11710b57cec5SDimitry Andric if (result.GetStatus() == eReturnStatusInvalid) {
11720b57cec5SDimitry Andric if (result.GetOutputData().empty())
11730b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
11740b57cec5SDimitry Andric else
11750b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
11760b57cec5SDimitry Andric }
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric
11790b57cec5SDimitry Andric return result.Succeeded();
11800b57cec5SDimitry Andric }
11810b57cec5SDimitry Andric
11820b57cec5SDimitry Andric private:
11830b57cec5SDimitry Andric StructuredData::GenericSP m_cmd_obj_sp;
11840b57cec5SDimitry Andric ScriptedCommandSynchronicity m_synchro;
11850b57cec5SDimitry Andric bool m_fetched_help_short : 1;
11860b57cec5SDimitry Andric bool m_fetched_help_long : 1;
11870b57cec5SDimitry Andric };
11880b57cec5SDimitry Andric
11890b57cec5SDimitry Andric // CommandObjectCommandsScriptImport
11909dba64beSDimitry Andric #define LLDB_OPTIONS_script_import
11919dba64beSDimitry Andric #include "CommandOptions.inc"
11920b57cec5SDimitry Andric
11930b57cec5SDimitry Andric class CommandObjectCommandsScriptImport : public CommandObjectParsed {
11940b57cec5SDimitry Andric public:
CommandObjectCommandsScriptImport(CommandInterpreter & interpreter)11950b57cec5SDimitry Andric CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
11960b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "command script import",
11970b57cec5SDimitry Andric "Import a scripting module in LLDB.", nullptr),
11980b57cec5SDimitry Andric m_options() {
11990b57cec5SDimitry Andric CommandArgumentEntry arg1;
12000b57cec5SDimitry Andric CommandArgumentData cmd_arg;
12010b57cec5SDimitry Andric
12020b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
12030b57cec5SDimitry Andric cmd_arg.arg_type = eArgTypeFilename;
12040b57cec5SDimitry Andric cmd_arg.arg_repetition = eArgRepeatPlus;
12050b57cec5SDimitry Andric
12060b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
12070b57cec5SDimitry Andric // argument entry.
12080b57cec5SDimitry Andric arg1.push_back(cmd_arg);
12090b57cec5SDimitry Andric
12100b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
12110b57cec5SDimitry Andric m_arguments.push_back(arg1);
12120b57cec5SDimitry Andric }
12130b57cec5SDimitry Andric
12140b57cec5SDimitry Andric ~CommandObjectCommandsScriptImport() override = default;
12150b57cec5SDimitry Andric
12169dba64beSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)12179dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
12180b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override {
12190b57cec5SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
12200b57cec5SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
12210b57cec5SDimitry Andric request, nullptr);
12220b57cec5SDimitry Andric }
12230b57cec5SDimitry Andric
GetOptions()12240b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
12250b57cec5SDimitry Andric
12260b57cec5SDimitry Andric protected:
12270b57cec5SDimitry Andric class CommandOptions : public Options {
12280b57cec5SDimitry Andric public:
CommandOptions()12290b57cec5SDimitry Andric CommandOptions() : Options() {}
12300b57cec5SDimitry Andric
12310b57cec5SDimitry Andric ~CommandOptions() override = default;
12320b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)12330b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
12340b57cec5SDimitry Andric ExecutionContext *execution_context) override {
12350b57cec5SDimitry Andric Status error;
12360b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
12370b57cec5SDimitry Andric
12380b57cec5SDimitry Andric switch (short_option) {
12390b57cec5SDimitry Andric case 'r':
1240480093f4SDimitry Andric // NO-OP
12410b57cec5SDimitry Andric break;
1242af732203SDimitry Andric case 'c':
1243af732203SDimitry Andric relative_to_command_file = true;
1244af732203SDimitry Andric break;
1245*5f7ddb14SDimitry Andric case 's':
1246*5f7ddb14SDimitry Andric silent = true;
1247*5f7ddb14SDimitry Andric break;
12480b57cec5SDimitry Andric default:
12499dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric
12520b57cec5SDimitry Andric return error;
12530b57cec5SDimitry Andric }
12540b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)12550b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1256af732203SDimitry Andric relative_to_command_file = false;
12570b57cec5SDimitry Andric }
12580b57cec5SDimitry Andric
GetDefinitions()12590b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
12600b57cec5SDimitry Andric return llvm::makeArrayRef(g_script_import_options);
12610b57cec5SDimitry Andric }
1262af732203SDimitry Andric bool relative_to_command_file = false;
1263*5f7ddb14SDimitry Andric bool silent = false;
12640b57cec5SDimitry Andric };
12650b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)12660b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
12670b57cec5SDimitry Andric if (command.empty()) {
12680b57cec5SDimitry Andric result.AppendError("command script import needs one or more arguments");
12690b57cec5SDimitry Andric return false;
12700b57cec5SDimitry Andric }
12710b57cec5SDimitry Andric
1272af732203SDimitry Andric FileSpec source_dir = {};
1273af732203SDimitry Andric if (m_options.relative_to_command_file) {
1274af732203SDimitry Andric source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
1275af732203SDimitry Andric if (!source_dir) {
1276af732203SDimitry Andric result.AppendError("command script import -c can only be specified "
1277af732203SDimitry Andric "from a command file");
1278af732203SDimitry Andric return false;
1279af732203SDimitry Andric }
1280af732203SDimitry Andric }
1281af732203SDimitry Andric
12820b57cec5SDimitry Andric for (auto &entry : command.entries()) {
12830b57cec5SDimitry Andric Status error;
12840b57cec5SDimitry Andric
1285*5f7ddb14SDimitry Andric LoadScriptOptions options;
1286*5f7ddb14SDimitry Andric options.SetInitSession(true);
1287*5f7ddb14SDimitry Andric options.SetSilent(m_options.silent);
1288*5f7ddb14SDimitry Andric
12890b57cec5SDimitry Andric // FIXME: this is necessary because CommandObject::CheckRequirements()
12900b57cec5SDimitry Andric // assumes that commands won't ever be recursively invoked, but it's
12910b57cec5SDimitry Andric // actually possible to craft a Python script that does other "command
12920b57cec5SDimitry Andric // script imports" in __lldb_init_module the real fix is to have
12930b57cec5SDimitry Andric // recursive commands possible with a CommandInvocation object separate
12940b57cec5SDimitry Andric // from the CommandObject itself, so that recursive command invocations
12950b57cec5SDimitry Andric // won't stomp on each other (wrt to execution contents, options, and
12960b57cec5SDimitry Andric // more)
12970b57cec5SDimitry Andric m_exe_ctx.Clear();
12980b57cec5SDimitry Andric if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
1299*5f7ddb14SDimitry Andric entry.c_str(), options, error, /*module_sp=*/nullptr,
1300*5f7ddb14SDimitry Andric source_dir)) {
13010b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
13020b57cec5SDimitry Andric } else {
13030b57cec5SDimitry Andric result.AppendErrorWithFormat("module importing failed: %s",
13040b57cec5SDimitry Andric error.AsCString());
13050b57cec5SDimitry Andric }
13060b57cec5SDimitry Andric }
13070b57cec5SDimitry Andric
13080b57cec5SDimitry Andric return result.Succeeded();
13090b57cec5SDimitry Andric }
13100b57cec5SDimitry Andric
13110b57cec5SDimitry Andric CommandOptions m_options;
13120b57cec5SDimitry Andric };
13130b57cec5SDimitry Andric
13140b57cec5SDimitry Andric // CommandObjectCommandsScriptAdd
13150b57cec5SDimitry Andric static constexpr OptionEnumValueElement g_script_synchro_type[] = {
13169dba64beSDimitry Andric {
13179dba64beSDimitry Andric eScriptedCommandSynchronicitySynchronous,
13189dba64beSDimitry Andric "synchronous",
13199dba64beSDimitry Andric "Run synchronous",
13209dba64beSDimitry Andric },
13219dba64beSDimitry Andric {
13229dba64beSDimitry Andric eScriptedCommandSynchronicityAsynchronous,
13239dba64beSDimitry Andric "asynchronous",
13249dba64beSDimitry Andric "Run asynchronous",
13259dba64beSDimitry Andric },
13269dba64beSDimitry Andric {
13279dba64beSDimitry Andric eScriptedCommandSynchronicityCurrentValue,
13289dba64beSDimitry Andric "current",
13299dba64beSDimitry Andric "Do not alter current setting",
13309dba64beSDimitry Andric },
13319dba64beSDimitry Andric };
13320b57cec5SDimitry Andric
ScriptSynchroType()13330b57cec5SDimitry Andric static constexpr OptionEnumValues ScriptSynchroType() {
13340b57cec5SDimitry Andric return OptionEnumValues(g_script_synchro_type);
13350b57cec5SDimitry Andric }
13360b57cec5SDimitry Andric
13379dba64beSDimitry Andric #define LLDB_OPTIONS_script_add
13389dba64beSDimitry Andric #include "CommandOptions.inc"
13390b57cec5SDimitry Andric
13400b57cec5SDimitry Andric class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
13410b57cec5SDimitry Andric public IOHandlerDelegateMultiline {
13420b57cec5SDimitry Andric public:
CommandObjectCommandsScriptAdd(CommandInterpreter & interpreter)13430b57cec5SDimitry Andric CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
13440b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "command script add",
13450b57cec5SDimitry Andric "Add a scripted function as an LLDB command.",
13460b57cec5SDimitry Andric nullptr),
13470b57cec5SDimitry Andric IOHandlerDelegateMultiline("DONE"), m_options() {
13480b57cec5SDimitry Andric CommandArgumentEntry arg1;
13490b57cec5SDimitry Andric CommandArgumentData cmd_arg;
13500b57cec5SDimitry Andric
13510b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
13520b57cec5SDimitry Andric cmd_arg.arg_type = eArgTypeCommandName;
13530b57cec5SDimitry Andric cmd_arg.arg_repetition = eArgRepeatPlain;
13540b57cec5SDimitry Andric
13550b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
13560b57cec5SDimitry Andric // argument entry.
13570b57cec5SDimitry Andric arg1.push_back(cmd_arg);
13580b57cec5SDimitry Andric
13590b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
13600b57cec5SDimitry Andric m_arguments.push_back(arg1);
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric
13630b57cec5SDimitry Andric ~CommandObjectCommandsScriptAdd() override = default;
13640b57cec5SDimitry Andric
GetOptions()13650b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
13660b57cec5SDimitry Andric
13670b57cec5SDimitry Andric protected:
13680b57cec5SDimitry Andric class CommandOptions : public Options {
13690b57cec5SDimitry Andric public:
CommandOptions()13700b57cec5SDimitry Andric CommandOptions()
1371*5f7ddb14SDimitry Andric : Options(), m_class_name(), m_funct_name(), m_short_help() {}
13720b57cec5SDimitry Andric
13730b57cec5SDimitry Andric ~CommandOptions() override = default;
13740b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)13750b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
13760b57cec5SDimitry Andric ExecutionContext *execution_context) override {
13770b57cec5SDimitry Andric Status error;
13780b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
13790b57cec5SDimitry Andric
13800b57cec5SDimitry Andric switch (short_option) {
13810b57cec5SDimitry Andric case 'f':
13820b57cec5SDimitry Andric if (!option_arg.empty())
13835ffd83dbSDimitry Andric m_funct_name = std::string(option_arg);
13840b57cec5SDimitry Andric break;
13850b57cec5SDimitry Andric case 'c':
13860b57cec5SDimitry Andric if (!option_arg.empty())
13875ffd83dbSDimitry Andric m_class_name = std::string(option_arg);
13880b57cec5SDimitry Andric break;
13890b57cec5SDimitry Andric case 'h':
13900b57cec5SDimitry Andric if (!option_arg.empty())
13915ffd83dbSDimitry Andric m_short_help = std::string(option_arg);
13920b57cec5SDimitry Andric break;
13930b57cec5SDimitry Andric case 's':
13940b57cec5SDimitry Andric m_synchronicity =
13950b57cec5SDimitry Andric (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
13960b57cec5SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
13970b57cec5SDimitry Andric if (!error.Success())
13980b57cec5SDimitry Andric error.SetErrorStringWithFormat(
13990b57cec5SDimitry Andric "unrecognized value for synchronicity '%s'",
14000b57cec5SDimitry Andric option_arg.str().c_str());
14010b57cec5SDimitry Andric break;
14020b57cec5SDimitry Andric default:
14039dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric
14060b57cec5SDimitry Andric return error;
14070b57cec5SDimitry Andric }
14080b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)14090b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
14100b57cec5SDimitry Andric m_class_name.clear();
14110b57cec5SDimitry Andric m_funct_name.clear();
14120b57cec5SDimitry Andric m_short_help.clear();
14130b57cec5SDimitry Andric m_synchronicity = eScriptedCommandSynchronicitySynchronous;
14140b57cec5SDimitry Andric }
14150b57cec5SDimitry Andric
GetDefinitions()14160b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
14170b57cec5SDimitry Andric return llvm::makeArrayRef(g_script_add_options);
14180b57cec5SDimitry Andric }
14190b57cec5SDimitry Andric
14200b57cec5SDimitry Andric // Instance variables to hold the values for command options.
14210b57cec5SDimitry Andric
14220b57cec5SDimitry Andric std::string m_class_name;
14230b57cec5SDimitry Andric std::string m_funct_name;
14240b57cec5SDimitry Andric std::string m_short_help;
1425*5f7ddb14SDimitry Andric ScriptedCommandSynchronicity m_synchronicity =
1426*5f7ddb14SDimitry Andric eScriptedCommandSynchronicitySynchronous;
14270b57cec5SDimitry Andric };
14280b57cec5SDimitry Andric
IOHandlerActivated(IOHandler & io_handler,bool interactive)14290b57cec5SDimitry Andric void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
14309dba64beSDimitry Andric StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
14310b57cec5SDimitry Andric if (output_sp && interactive) {
14320b57cec5SDimitry Andric output_sp->PutCString(g_python_command_instructions);
14330b57cec5SDimitry Andric output_sp->Flush();
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric }
14360b57cec5SDimitry Andric
IOHandlerInputComplete(IOHandler & io_handler,std::string & data)14370b57cec5SDimitry Andric void IOHandlerInputComplete(IOHandler &io_handler,
14380b57cec5SDimitry Andric std::string &data) override {
14399dba64beSDimitry Andric StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
14400b57cec5SDimitry Andric
14410b57cec5SDimitry Andric ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
14420b57cec5SDimitry Andric if (interpreter) {
14430b57cec5SDimitry Andric
14440b57cec5SDimitry Andric StringList lines;
14450b57cec5SDimitry Andric lines.SplitIntoLines(data);
14460b57cec5SDimitry Andric if (lines.GetSize() > 0) {
14470b57cec5SDimitry Andric std::string funct_name_str;
14480b57cec5SDimitry Andric if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
14490b57cec5SDimitry Andric if (funct_name_str.empty()) {
14500b57cec5SDimitry Andric error_sp->Printf("error: unable to obtain a function name, didn't "
14510b57cec5SDimitry Andric "add python command.\n");
14520b57cec5SDimitry Andric error_sp->Flush();
14530b57cec5SDimitry Andric } else {
14540b57cec5SDimitry Andric // everything should be fine now, let's add this alias
14550b57cec5SDimitry Andric
14560b57cec5SDimitry Andric CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
14570b57cec5SDimitry Andric m_interpreter, m_cmd_name, funct_name_str, m_short_help,
14580b57cec5SDimitry Andric m_synchronicity));
14590b57cec5SDimitry Andric
14600b57cec5SDimitry Andric if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
14610b57cec5SDimitry Andric true)) {
14620b57cec5SDimitry Andric error_sp->Printf("error: unable to add selected command, didn't "
14630b57cec5SDimitry Andric "add python command.\n");
14640b57cec5SDimitry Andric error_sp->Flush();
14650b57cec5SDimitry Andric }
14660b57cec5SDimitry Andric }
14670b57cec5SDimitry Andric } else {
14680b57cec5SDimitry Andric error_sp->Printf(
14690b57cec5SDimitry Andric "error: unable to create function, didn't add python command.\n");
14700b57cec5SDimitry Andric error_sp->Flush();
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric } else {
14730b57cec5SDimitry Andric error_sp->Printf("error: empty function, didn't add python command.\n");
14740b57cec5SDimitry Andric error_sp->Flush();
14750b57cec5SDimitry Andric }
14760b57cec5SDimitry Andric } else {
14770b57cec5SDimitry Andric error_sp->Printf(
14780b57cec5SDimitry Andric "error: script interpreter missing, didn't add python command.\n");
14790b57cec5SDimitry Andric error_sp->Flush();
14800b57cec5SDimitry Andric }
14810b57cec5SDimitry Andric
14820b57cec5SDimitry Andric io_handler.SetIsDone(true);
14830b57cec5SDimitry Andric }
14840b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)14850b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
14860b57cec5SDimitry Andric if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
14870b57cec5SDimitry Andric result.AppendError("only scripting language supported for scripted "
14880b57cec5SDimitry Andric "commands is currently Python");
14890b57cec5SDimitry Andric return false;
14900b57cec5SDimitry Andric }
14910b57cec5SDimitry Andric
14920b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) {
14930b57cec5SDimitry Andric result.AppendError("'command script add' requires one argument");
14940b57cec5SDimitry Andric return false;
14950b57cec5SDimitry Andric }
14960b57cec5SDimitry Andric
14970b57cec5SDimitry Andric // Store the options in case we get multi-line input
14985ffd83dbSDimitry Andric m_cmd_name = std::string(command[0].ref());
14990b57cec5SDimitry Andric m_short_help.assign(m_options.m_short_help);
15000b57cec5SDimitry Andric m_synchronicity = m_options.m_synchronicity;
15010b57cec5SDimitry Andric
15020b57cec5SDimitry Andric if (m_options.m_class_name.empty()) {
15030b57cec5SDimitry Andric if (m_options.m_funct_name.empty()) {
15040b57cec5SDimitry Andric m_interpreter.GetPythonCommandsFromIOHandler(
15050b57cec5SDimitry Andric " ", // Prompt
1506480093f4SDimitry Andric *this); // IOHandlerDelegate
15070b57cec5SDimitry Andric } else {
15080b57cec5SDimitry Andric CommandObjectSP new_cmd(new CommandObjectPythonFunction(
15090b57cec5SDimitry Andric m_interpreter, m_cmd_name, m_options.m_funct_name,
15100b57cec5SDimitry Andric m_options.m_short_help, m_synchronicity));
15110b57cec5SDimitry Andric if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
15120b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
15130b57cec5SDimitry Andric } else {
15140b57cec5SDimitry Andric result.AppendError("cannot add command");
15150b57cec5SDimitry Andric }
15160b57cec5SDimitry Andric }
15170b57cec5SDimitry Andric } else {
15180b57cec5SDimitry Andric ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
15190b57cec5SDimitry Andric if (!interpreter) {
15200b57cec5SDimitry Andric result.AppendError("cannot find ScriptInterpreter");
15210b57cec5SDimitry Andric return false;
15220b57cec5SDimitry Andric }
15230b57cec5SDimitry Andric
15240b57cec5SDimitry Andric auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
15250b57cec5SDimitry Andric m_options.m_class_name.c_str());
15260b57cec5SDimitry Andric if (!cmd_obj_sp) {
15270b57cec5SDimitry Andric result.AppendError("cannot create helper object");
15280b57cec5SDimitry Andric return false;
15290b57cec5SDimitry Andric }
15300b57cec5SDimitry Andric
15310b57cec5SDimitry Andric CommandObjectSP new_cmd(new CommandObjectScriptingObject(
15320b57cec5SDimitry Andric m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
15330b57cec5SDimitry Andric if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
15340b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
15350b57cec5SDimitry Andric } else {
15360b57cec5SDimitry Andric result.AppendError("cannot add command");
15370b57cec5SDimitry Andric }
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric
15400b57cec5SDimitry Andric return result.Succeeded();
15410b57cec5SDimitry Andric }
15420b57cec5SDimitry Andric
15430b57cec5SDimitry Andric CommandOptions m_options;
15440b57cec5SDimitry Andric std::string m_cmd_name;
15450b57cec5SDimitry Andric std::string m_short_help;
15460b57cec5SDimitry Andric ScriptedCommandSynchronicity m_synchronicity;
15470b57cec5SDimitry Andric };
15480b57cec5SDimitry Andric
15490b57cec5SDimitry Andric // CommandObjectCommandsScriptList
15500b57cec5SDimitry Andric
15510b57cec5SDimitry Andric class CommandObjectCommandsScriptList : public CommandObjectParsed {
15520b57cec5SDimitry Andric public:
CommandObjectCommandsScriptList(CommandInterpreter & interpreter)15530b57cec5SDimitry Andric CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
15540b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "command script list",
15550b57cec5SDimitry Andric "List defined scripted commands.", nullptr) {}
15560b57cec5SDimitry Andric
15570b57cec5SDimitry Andric ~CommandObjectCommandsScriptList() override = default;
15580b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)15590b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
15609dba64beSDimitry Andric if (command.GetArgumentCount() != 0) {
15619dba64beSDimitry Andric result.AppendError("'command script list' doesn't take any arguments");
15629dba64beSDimitry Andric return false;
15639dba64beSDimitry Andric }
15649dba64beSDimitry Andric
15650b57cec5SDimitry Andric m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
15660b57cec5SDimitry Andric
15670b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
15680b57cec5SDimitry Andric
15690b57cec5SDimitry Andric return true;
15700b57cec5SDimitry Andric }
15710b57cec5SDimitry Andric };
15720b57cec5SDimitry Andric
15730b57cec5SDimitry Andric // CommandObjectCommandsScriptClear
15740b57cec5SDimitry Andric
15750b57cec5SDimitry Andric class CommandObjectCommandsScriptClear : public CommandObjectParsed {
15760b57cec5SDimitry Andric public:
CommandObjectCommandsScriptClear(CommandInterpreter & interpreter)15770b57cec5SDimitry Andric CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
15780b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "command script clear",
15790b57cec5SDimitry Andric "Delete all scripted commands.", nullptr) {}
15800b57cec5SDimitry Andric
15810b57cec5SDimitry Andric ~CommandObjectCommandsScriptClear() override = default;
15820b57cec5SDimitry Andric
15830b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)15840b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
15859dba64beSDimitry Andric if (command.GetArgumentCount() != 0) {
15869dba64beSDimitry Andric result.AppendError("'command script clear' doesn't take any arguments");
15879dba64beSDimitry Andric return false;
15889dba64beSDimitry Andric }
15899dba64beSDimitry Andric
15900b57cec5SDimitry Andric m_interpreter.RemoveAllUser();
15910b57cec5SDimitry Andric
15920b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
15930b57cec5SDimitry Andric
15940b57cec5SDimitry Andric return true;
15950b57cec5SDimitry Andric }
15960b57cec5SDimitry Andric };
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andric // CommandObjectCommandsScriptDelete
15990b57cec5SDimitry Andric
16000b57cec5SDimitry Andric class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
16010b57cec5SDimitry Andric public:
CommandObjectCommandsScriptDelete(CommandInterpreter & interpreter)16020b57cec5SDimitry Andric CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
16030b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "command script delete",
16040b57cec5SDimitry Andric "Delete a scripted command.", nullptr) {
16050b57cec5SDimitry Andric CommandArgumentEntry arg1;
16060b57cec5SDimitry Andric CommandArgumentData cmd_arg;
16070b57cec5SDimitry Andric
16080b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
16090b57cec5SDimitry Andric cmd_arg.arg_type = eArgTypeCommandName;
16100b57cec5SDimitry Andric cmd_arg.arg_repetition = eArgRepeatPlain;
16110b57cec5SDimitry Andric
16120b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
16130b57cec5SDimitry Andric // argument entry.
16140b57cec5SDimitry Andric arg1.push_back(cmd_arg);
16150b57cec5SDimitry Andric
16160b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
16170b57cec5SDimitry Andric m_arguments.push_back(arg1);
16180b57cec5SDimitry Andric }
16190b57cec5SDimitry Andric
16200b57cec5SDimitry Andric ~CommandObjectCommandsScriptDelete() override = default;
16210b57cec5SDimitry Andric
16225ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)16235ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
16245ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
16255ffd83dbSDimitry Andric if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
16265ffd83dbSDimitry Andric return;
16275ffd83dbSDimitry Andric
16285ffd83dbSDimitry Andric for (const auto &c : m_interpreter.GetUserCommands())
16295ffd83dbSDimitry Andric request.TryCompleteCurrentArg(c.first, c.second->GetHelp());
16305ffd83dbSDimitry Andric }
16315ffd83dbSDimitry Andric
16320b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)16330b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
16340b57cec5SDimitry Andric
16350b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) {
16360b57cec5SDimitry Andric result.AppendError("'command script delete' requires one argument");
16370b57cec5SDimitry Andric return false;
16380b57cec5SDimitry Andric }
16390b57cec5SDimitry Andric
16409dba64beSDimitry Andric auto cmd_name = command[0].ref();
16410b57cec5SDimitry Andric
16420b57cec5SDimitry Andric if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
16430b57cec5SDimitry Andric !m_interpreter.UserCommandExists(cmd_name)) {
16440b57cec5SDimitry Andric result.AppendErrorWithFormat("command %s not found", command[0].c_str());
16450b57cec5SDimitry Andric return false;
16460b57cec5SDimitry Andric }
16470b57cec5SDimitry Andric
16480b57cec5SDimitry Andric m_interpreter.RemoveUser(cmd_name);
16490b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
16500b57cec5SDimitry Andric return true;
16510b57cec5SDimitry Andric }
16520b57cec5SDimitry Andric };
16530b57cec5SDimitry Andric
16540b57cec5SDimitry Andric #pragma mark CommandObjectMultiwordCommandsScript
16550b57cec5SDimitry Andric
16560b57cec5SDimitry Andric // CommandObjectMultiwordCommandsScript
16570b57cec5SDimitry Andric
16580b57cec5SDimitry Andric class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
16590b57cec5SDimitry Andric public:
CommandObjectMultiwordCommandsScript(CommandInterpreter & interpreter)16600b57cec5SDimitry Andric CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
16610b57cec5SDimitry Andric : CommandObjectMultiword(
1662480093f4SDimitry Andric interpreter, "command script",
1663480093f4SDimitry Andric "Commands for managing custom "
16640b57cec5SDimitry Andric "commands implemented by "
16650b57cec5SDimitry Andric "interpreter scripts.",
16660b57cec5SDimitry Andric "command script <subcommand> [<subcommand-options>]") {
16670b57cec5SDimitry Andric LoadSubCommand("add", CommandObjectSP(
16680b57cec5SDimitry Andric new CommandObjectCommandsScriptAdd(interpreter)));
16690b57cec5SDimitry Andric LoadSubCommand(
16700b57cec5SDimitry Andric "delete",
16710b57cec5SDimitry Andric CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
16720b57cec5SDimitry Andric LoadSubCommand(
16730b57cec5SDimitry Andric "clear",
16740b57cec5SDimitry Andric CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
16750b57cec5SDimitry Andric LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
16760b57cec5SDimitry Andric interpreter)));
16770b57cec5SDimitry Andric LoadSubCommand(
16780b57cec5SDimitry Andric "import",
16790b57cec5SDimitry Andric CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric
16820b57cec5SDimitry Andric ~CommandObjectMultiwordCommandsScript() override = default;
16830b57cec5SDimitry Andric };
16840b57cec5SDimitry Andric
16850b57cec5SDimitry Andric #pragma mark CommandObjectMultiwordCommands
16860b57cec5SDimitry Andric
16870b57cec5SDimitry Andric // CommandObjectMultiwordCommands
16880b57cec5SDimitry Andric
CommandObjectMultiwordCommands(CommandInterpreter & interpreter)16890b57cec5SDimitry Andric CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
16900b57cec5SDimitry Andric CommandInterpreter &interpreter)
16910b57cec5SDimitry Andric : CommandObjectMultiword(interpreter, "command",
16920b57cec5SDimitry Andric "Commands for managing custom LLDB commands.",
16930b57cec5SDimitry Andric "command <subcommand> [<subcommand-options>]") {
16940b57cec5SDimitry Andric LoadSubCommand("source",
16950b57cec5SDimitry Andric CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
16960b57cec5SDimitry Andric LoadSubCommand("alias",
16970b57cec5SDimitry Andric CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
16980b57cec5SDimitry Andric LoadSubCommand("unalias", CommandObjectSP(
16990b57cec5SDimitry Andric new CommandObjectCommandsUnalias(interpreter)));
17000b57cec5SDimitry Andric LoadSubCommand("delete",
17010b57cec5SDimitry Andric CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
17020b57cec5SDimitry Andric LoadSubCommand(
17030b57cec5SDimitry Andric "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
17040b57cec5SDimitry Andric LoadSubCommand(
17050b57cec5SDimitry Andric "script",
17060b57cec5SDimitry Andric CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
17070b57cec5SDimitry Andric }
17080b57cec5SDimitry Andric
17090b57cec5SDimitry Andric CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1710