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