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 
13836de94cfSTatyana Krasnukha     CommandInterpreterRunOptions options;
139340b0309SGreg Clayton     // If any options were set, then use them
140340b0309SGreg Clayton     if (m_options.m_stop_on_error.OptionWasSet() ||
141340b0309SGreg Clayton         m_options.m_silent_run.OptionWasSet() ||
142b9c1b51eSKate Stone         m_options.m_stop_on_continue.OptionWasSet()) {
1431c19b74cSJonas Devlieghere       if (m_options.m_stop_on_continue.OptionWasSet())
1441c19b74cSJonas Devlieghere         options.SetStopOnContinue(
1451c19b74cSJonas Devlieghere             m_options.m_stop_on_continue.GetCurrentValue());
1461c19b74cSJonas Devlieghere 
1471c19b74cSJonas Devlieghere       if (m_options.m_stop_on_error.OptionWasSet())
14826c7bf93SJim Ingham         options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
149c678ed77SStefan Granitz 
150c678ed77SStefan Granitz       // Individual silent setting is override for global command echo settings.
151c678ed77SStefan Granitz       if (m_options.m_silent_run.GetCurrentValue()) {
152c678ed77SStefan Granitz         options.SetSilent(true);
153c678ed77SStefan Granitz       } else {
154c678ed77SStefan Granitz         options.SetPrintResults(true);
155c0b48ab6SJonas Devlieghere         options.SetPrintErrors(true);
156c678ed77SStefan Granitz         options.SetEchoCommands(m_interpreter.GetEchoCommands());
157c678ed77SStefan Granitz         options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
158c678ed77SStefan Granitz       }
159122a4ebdSPavel Labath     }
16036de94cfSTatyana Krasnukha 
16136de94cfSTatyana Krasnukha     m_interpreter.HandleCommandsFromFile(cmd_file, options, result);
162ebc09c36SJim Ingham     return result.Succeeded();
163ebc09c36SJim Ingham   }
1646e3d8e7fSEugene Zelenko 
1655a988416SJim Ingham   CommandOptions m_options;
166ebc09c36SJim Ingham };
167ebc09c36SJim Ingham 
168ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
169ebc09c36SJim Ingham // CommandObjectCommandsAlias
170ebc09c36SJim Ingham 
17164becc11SRaphael Isemann #define LLDB_OPTIONS_alias
17264becc11SRaphael Isemann #include "CommandOptions.inc"
1731f0f5b5bSZachary Turner 
174b9c1b51eSKate Stone static const char *g_python_command_instructions =
175b9c1b51eSKate Stone     "Enter your Python command(s). Type 'DONE' to end.\n"
176be93a35aSEnrico Granata     "You must define a Python function with this signature:\n"
17744d93782SGreg Clayton     "def my_command_impl(debugger, args, result, internal_dict):\n";
178be93a35aSEnrico Granata 
179b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw {
18045d0e238SEnrico Granata protected:
181b9c1b51eSKate Stone   class CommandOptions : public OptionGroup {
182ebc09c36SJim Ingham   public:
183b9c1b51eSKate Stone     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
18445d0e238SEnrico Granata 
18545d0e238SEnrico Granata     ~CommandOptions() override = default;
18645d0e238SEnrico Granata 
1871f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
18870602439SZachary Turner       return llvm::makeArrayRef(g_alias_options);
1891f0f5b5bSZachary Turner     }
19045d0e238SEnrico Granata 
19197206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
192b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
19397206d57SZachary Turner       Status error;
19445d0e238SEnrico Granata 
1951f0f5b5bSZachary Turner       const int short_option = GetDefinitions()[option_idx].short_option;
1968cef4b0bSZachary Turner       std::string option_str(option_value);
19745d0e238SEnrico Granata 
198b9c1b51eSKate Stone       switch (short_option) {
19945d0e238SEnrico Granata       case 'h':
2008cef4b0bSZachary Turner         m_help.SetCurrentValue(option_str);
20145d0e238SEnrico Granata         m_help.SetOptionWasSet();
20245d0e238SEnrico Granata         break;
20345d0e238SEnrico Granata 
20445d0e238SEnrico Granata       case 'H':
2058cef4b0bSZachary Turner         m_long_help.SetCurrentValue(option_str);
20645d0e238SEnrico Granata         m_long_help.SetOptionWasSet();
20745d0e238SEnrico Granata         break;
20845d0e238SEnrico Granata 
20945d0e238SEnrico Granata       default:
21036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
21145d0e238SEnrico Granata       }
21245d0e238SEnrico Granata 
21345d0e238SEnrico Granata       return error;
21445d0e238SEnrico Granata     }
21545d0e238SEnrico Granata 
216b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
21745d0e238SEnrico Granata       m_help.Clear();
21845d0e238SEnrico Granata       m_long_help.Clear();
21945d0e238SEnrico Granata     }
22045d0e238SEnrico Granata 
22145d0e238SEnrico Granata     OptionValueString m_help;
22245d0e238SEnrico Granata     OptionValueString m_long_help;
22345d0e238SEnrico Granata   };
22445d0e238SEnrico Granata 
22545d0e238SEnrico Granata   OptionGroupOptions m_option_group;
22645d0e238SEnrico Granata   CommandOptions m_command_options;
22745d0e238SEnrico Granata 
22845d0e238SEnrico Granata public:
229b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
23045d0e238SEnrico Granata 
2317428a18cSKate Stone   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
232b9c1b51eSKate Stone       : CommandObjectRaw(
233b9c1b51eSKate Stone             interpreter, "command alias",
234a449698cSZachary Turner             "Define a custom command in terms of an existing command."),
235b9c1b51eSKate Stone         m_option_group(), m_command_options() {
23645d0e238SEnrico Granata     m_option_group.Append(&m_command_options);
23745d0e238SEnrico Granata     m_option_group.Finalize();
23845d0e238SEnrico Granata 
239ebc09c36SJim Ingham     SetHelpLong(
240ea671fbdSKate Stone         "'alias' allows the user to create a short-cut or abbreviation for long \
241ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options.  \
242b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:"
243b9c1b51eSKate Stone         R"(
244ea671fbdSKate Stone 
245ea671fbdSKate Stone (lldb) command alias sc script
246ea671fbdSKate Stone 
247ea671fbdSKate Stone     Creates the abbreviation 'sc' for the 'script' command.
248ea671fbdSKate Stone 
249ea671fbdSKate Stone (lldb) command alias bp breakpoint
250ea671fbdSKate Stone 
251b9c1b51eSKate Stone )"
252b9c1b51eSKate Stone         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
253ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \
254b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
255b9c1b51eSKate Stone         R"(
256ea671fbdSKate Stone 
257ea671fbdSKate Stone (lldb) command alias bpl breakpoint list
258ea671fbdSKate Stone 
259ea671fbdSKate Stone     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
260ea671fbdSKate Stone 
261b9c1b51eSKate Stone )"
262b9c1b51eSKate Stone         "An alias can include some options for the command, with the values either \
263ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \
264ea671fbdSKate Stone arguments, to be filled in when the alias is invoked.  The following example \
265b9c1b51eSKate Stone shows how to create aliases with options:"
266b9c1b51eSKate Stone         R"(
267ea671fbdSKate Stone 
268ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
269ea671fbdSKate Stone 
270b9c1b51eSKate Stone )"
271b9c1b51eSKate Stone         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
272ea671fbdSKate Stone options already part of the alias.  So if the user wants to set a breakpoint \
273ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \
274ea671fbdSKate Stone user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
275ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used.  \
276ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \
277ea671fbdSKate Stone occupies when the alias is used.  All the occurrences of '%1' in the alias \
278ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \
279ea671fbdSKate Stone alias will be replaced with the second argument, and so on.  This also allows \
280ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \
281b9c1b51eSKate Stone launch' example below)."
282b9c1b51eSKate Stone         R"(
283ea671fbdSKate Stone 
284b9c1b51eSKate Stone )"
285b9c1b51eSKate Stone         "Note: the positional arguments must substitute as whole words in the resultant \
286ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \
287b9c1b51eSKate Stone \".cpp\":"
288b9c1b51eSKate Stone         R"(
289ea671fbdSKate Stone 
290ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
291ea671fbdSKate Stone 
292b9c1b51eSKate Stone )"
293b9c1b51eSKate Stone         "For more complex aliasing, use the \"command regex\" command instead.  In the \
294ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \
295ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \
296b9c1b51eSKate Stone argument.  The user would use this alias as follows:"
297b9c1b51eSKate Stone         R"(
298ea671fbdSKate Stone 
299ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
300ea671fbdSKate Stone (lldb) bfl my-file.c 137
301ea671fbdSKate Stone 
302ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
303ea671fbdSKate Stone 
304ea671fbdSKate Stone Another example:
305ea671fbdSKate Stone 
306ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1
307ea671fbdSKate Stone (lldb) pltty /dev/tty0
308ea671fbdSKate Stone 
309ea671fbdSKate Stone     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
310ea671fbdSKate Stone 
311b9c1b51eSKate Stone )"
312b9c1b51eSKate Stone         "If the user always wanted to pass the same value to a particular option, the \
313ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \
314b9c1b51eSKate Stone rather than using a positional placeholder:"
315b9c1b51eSKate Stone         R"(
316ea671fbdSKate Stone 
317ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3
318ea671fbdSKate Stone 
319b9c1b51eSKate Stone     Always sets a breakpoint on line 3 of whatever file is indicated.)");
320ebc09c36SJim Ingham 
321405fe67fSCaroline Tice     CommandArgumentEntry arg1;
322405fe67fSCaroline Tice     CommandArgumentEntry arg2;
323405fe67fSCaroline Tice     CommandArgumentEntry arg3;
324405fe67fSCaroline Tice     CommandArgumentData alias_arg;
325405fe67fSCaroline Tice     CommandArgumentData cmd_arg;
326405fe67fSCaroline Tice     CommandArgumentData options_arg;
327405fe67fSCaroline Tice 
328405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
329405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
330405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
331405fe67fSCaroline Tice 
332b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
333b9c1b51eSKate Stone     // argument entry.
334405fe67fSCaroline Tice     arg1.push_back(alias_arg);
335405fe67fSCaroline Tice 
336405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
337405fe67fSCaroline Tice     cmd_arg.arg_type = eArgTypeCommandName;
338405fe67fSCaroline Tice     cmd_arg.arg_repetition = eArgRepeatPlain;
339405fe67fSCaroline Tice 
340b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
341b9c1b51eSKate Stone     // argument entry.
342405fe67fSCaroline Tice     arg2.push_back(cmd_arg);
343405fe67fSCaroline Tice 
344405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
345405fe67fSCaroline Tice     options_arg.arg_type = eArgTypeAliasOptions;
346405fe67fSCaroline Tice     options_arg.arg_repetition = eArgRepeatOptional;
347405fe67fSCaroline Tice 
348b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
349b9c1b51eSKate Stone     // argument entry.
350405fe67fSCaroline Tice     arg3.push_back(options_arg);
351405fe67fSCaroline Tice 
352405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
353405fe67fSCaroline Tice     m_arguments.push_back(arg1);
354405fe67fSCaroline Tice     m_arguments.push_back(arg2);
355405fe67fSCaroline Tice     m_arguments.push_back(arg3);
356ebc09c36SJim Ingham   }
357ebc09c36SJim Ingham 
3586e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAlias() override = default;
359ebc09c36SJim Ingham 
3605a988416SJim Ingham protected:
3614d51a902SRaphael Isemann   bool DoExecute(llvm::StringRef raw_command_line,
362b9c1b51eSKate Stone                  CommandReturnObject &result) override {
3634d51a902SRaphael Isemann     if (raw_command_line.empty()) {
364d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
36545d0e238SEnrico Granata       return false;
36645d0e238SEnrico Granata     }
36745d0e238SEnrico Granata 
368e1cfbc79STodd Fiala     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
369e1cfbc79STodd Fiala     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
37045d0e238SEnrico Granata 
3713a0e1270SRaphael Isemann     OptionsWithRaw args_with_suffix(raw_command_line);
37245d0e238SEnrico Granata 
3733a0e1270SRaphael Isemann     if (args_with_suffix.HasArgs())
3743a0e1270SRaphael Isemann       if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
3753a0e1270SRaphael Isemann                                  m_option_group, exe_ctx))
37645d0e238SEnrico Granata         return false;
37745d0e238SEnrico Granata 
378daed98e5SShivam Mittal     llvm::StringRef raw_command_string = args_with_suffix.GetRawPart();
379a01bccdbSZachary Turner     Args args(raw_command_string);
380844d2303SCaroline Tice 
38111eb9c64SZachary Turner     if (args.GetArgumentCount() < 2) {
382d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
383844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
384844d2303SCaroline Tice       return false;
385844d2303SCaroline Tice     }
386844d2303SCaroline Tice 
387844d2303SCaroline Tice     // Get the alias command.
388844d2303SCaroline Tice 
3890d9a201eSRaphael Isemann     auto alias_command = args[0].ref();
3904574a890SZachary Turner     if (alias_command.startswith("-")) {
391d72e412fSEnrico Granata       result.AppendError("aliases starting with a dash are not supported");
392b9c1b51eSKate Stone       if (alias_command == "--help" || alias_command == "--long-help") {
393b9c1b51eSKate Stone         result.AppendWarning("if trying to pass options to 'command alias' add "
394b9c1b51eSKate Stone                              "a -- at the end of the options");
395d72e412fSEnrico Granata       }
396d72e412fSEnrico Granata       result.SetStatus(eReturnStatusFailed);
397d72e412fSEnrico Granata       return false;
398d72e412fSEnrico Granata     }
399844d2303SCaroline Tice 
400b9c1b51eSKate Stone     // Strip the new alias name off 'raw_command_string'  (leave it on args,
40105097246SAdrian Prantl     // which gets passed to 'Execute', which does the stripping itself.
402844d2303SCaroline Tice     size_t pos = raw_command_string.find(alias_command);
403b9c1b51eSKate Stone     if (pos == 0) {
404844d2303SCaroline Tice       raw_command_string = raw_command_string.substr(alias_command.size());
405844d2303SCaroline Tice       pos = raw_command_string.find_first_not_of(' ');
406844d2303SCaroline Tice       if ((pos != std::string::npos) && (pos > 0))
407844d2303SCaroline Tice         raw_command_string = raw_command_string.substr(pos);
408b9c1b51eSKate Stone     } else {
409844d2303SCaroline Tice       result.AppendError("Error parsing command string.  No alias created.");
410844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
411844d2303SCaroline Tice       return false;
412844d2303SCaroline Tice     }
413844d2303SCaroline Tice 
414844d2303SCaroline Tice     // Verify that the command is alias-able.
415771ef6d4SMalcolm Parsons     if (m_interpreter.CommandExists(alias_command)) {
416b9c1b51eSKate Stone       result.AppendErrorWithFormat(
417b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
4184574a890SZachary Turner           args[0].c_str());
419844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
420844d2303SCaroline Tice       return false;
421844d2303SCaroline Tice     }
422844d2303SCaroline Tice 
423b9c1b51eSKate Stone     // Get CommandObject that is being aliased. The command name is read from
424a01bccdbSZachary Turner     // the front of raw_command_string. raw_command_string is returned with the
425a01bccdbSZachary Turner     // name of the command object stripped off the front.
426a01bccdbSZachary Turner     llvm::StringRef original_raw_command_string = raw_command_string;
427b9c1b51eSKate Stone     CommandObject *cmd_obj =
428b9c1b51eSKate Stone         m_interpreter.GetCommandObjectForCommand(raw_command_string);
429844d2303SCaroline Tice 
430b9c1b51eSKate Stone     if (!cmd_obj) {
431b9c1b51eSKate Stone       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
432b9c1b51eSKate Stone                                    "'%s' does not begin with a valid command."
433b9c1b51eSKate Stone                                    "  No alias created.",
434a01bccdbSZachary Turner                                    original_raw_command_string.str().c_str());
435844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
436844d2303SCaroline Tice       return false;
437b9c1b51eSKate Stone     } else if (!cmd_obj->WantsRawCommandString()) {
438b9c1b51eSKate Stone       // Note that args was initialized with the original command, and has not
43905097246SAdrian Prantl       // been updated to this point. Therefore can we pass it to the version of
44005097246SAdrian Prantl       // Execute that does not need/expect raw input in the alias.
4415a988416SJim Ingham       return HandleAliasingNormalCommand(args, result);
442b9c1b51eSKate Stone     } else {
443b9c1b51eSKate Stone       return HandleAliasingRawCommand(alias_command, raw_command_string,
444b9c1b51eSKate Stone                                       *cmd_obj, result);
4455a988416SJim Ingham     }
4465a988416SJim Ingham     return result.Succeeded();
4475a988416SJim Ingham   }
4485a988416SJim Ingham 
449a01bccdbSZachary Turner   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
450a01bccdbSZachary Turner                                 llvm::StringRef raw_command_string,
451b9c1b51eSKate Stone                                 CommandObject &cmd_obj,
452b9c1b51eSKate Stone                                 CommandReturnObject &result) {
453844d2303SCaroline Tice     // Verify & handle any options/arguments passed to the alias command
454844d2303SCaroline Tice 
455b9c1b51eSKate Stone     OptionArgVectorSP option_arg_vector_sp =
456b9c1b51eSKate Stone         OptionArgVectorSP(new OptionArgVector);
457844d2303SCaroline Tice 
458b9c1b51eSKate Stone     if (CommandObjectSP cmd_obj_sp =
459a9448872SJonas Devlieghere             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName())) {
460a01bccdbSZachary Turner       if (m_interpreter.AliasExists(alias_command) ||
461a01bccdbSZachary Turner           m_interpreter.UserCommandExists(alias_command)) {
462b9c1b51eSKate Stone         result.AppendWarningWithFormat(
463b9c1b51eSKate Stone             "Overwriting existing definition for '%s'.\n",
464a01bccdbSZachary Turner             alias_command.str().c_str());
465844d2303SCaroline Tice       }
466b9c1b51eSKate Stone       if (CommandAlias *alias = m_interpreter.AddAlias(
467a01bccdbSZachary Turner               alias_command, cmd_obj_sp, raw_command_string)) {
46845d0e238SEnrico Granata         if (m_command_options.m_help.OptionWasSet())
46945d0e238SEnrico Granata           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
47045d0e238SEnrico Granata         if (m_command_options.m_long_help.OptionWasSet())
47145d0e238SEnrico Granata           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
472844d2303SCaroline Tice         result.SetStatus(eReturnStatusSuccessFinishNoResult);
473b9c1b51eSKate Stone       } else {
474472362e6SCaroline Tice         result.AppendError("Unable to create requested alias.\n");
475472362e6SCaroline Tice         result.SetStatus(eReturnStatusFailed);
476472362e6SCaroline Tice       }
477212130acSEnrico Granata 
478b9c1b51eSKate Stone     } else {
479212130acSEnrico Granata       result.AppendError("Unable to create requested alias.\n");
480212130acSEnrico Granata       result.SetStatus(eReturnStatusFailed);
481212130acSEnrico Granata     }
482212130acSEnrico Granata 
483844d2303SCaroline Tice     return result.Succeeded();
484844d2303SCaroline Tice   }
485ebc09c36SJim Ingham 
486b9c1b51eSKate Stone   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
487867b185dSCaroline Tice     size_t argc = args.GetArgumentCount();
488ebc09c36SJim Ingham 
489b9c1b51eSKate Stone     if (argc < 2) {
490d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
491ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
492ebc09c36SJim Ingham       return false;
493ebc09c36SJim Ingham     }
494ebc09c36SJim Ingham 
4954574a890SZachary Turner     // Save these in std::strings since we're going to shift them off.
496adcd0268SBenjamin Kramer     const std::string alias_command(std::string(args[0].ref()));
497adcd0268SBenjamin Kramer     const std::string actual_command(std::string(args[1].ref()));
498ebc09c36SJim Ingham 
499ebc09c36SJim Ingham     args.Shift(); // Shift the alias command word off the argument vector.
500ebc09c36SJim Ingham     args.Shift(); // Shift the old command word off the argument vector.
501ebc09c36SJim Ingham 
502b9c1b51eSKate Stone     // Verify that the command is alias'able, and get the appropriate command
503b9c1b51eSKate Stone     // object.
504ebc09c36SJim Ingham 
505771ef6d4SMalcolm Parsons     if (m_interpreter.CommandExists(alias_command)) {
506b9c1b51eSKate Stone       result.AppendErrorWithFormat(
507b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
508ebc09c36SJim Ingham           alias_command.c_str());
509ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
5104574a890SZachary Turner       return false;
5114574a890SZachary Turner     }
5124574a890SZachary Turner 
513b9c1b51eSKate Stone     CommandObjectSP command_obj_sp(
514a449698cSZachary Turner         m_interpreter.GetCommandSPExact(actual_command, true));
515ebc09c36SJim Ingham     CommandObjectSP subcommand_obj_sp;
516ebc09c36SJim Ingham     bool use_subcommand = false;
5174574a890SZachary Turner     if (!command_obj_sp) {
5184574a890SZachary Turner       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
5194574a890SZachary Turner                                    actual_command.c_str());
5204574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
5214574a890SZachary Turner       return false;
5224574a890SZachary Turner     }
523ebc09c36SJim Ingham     CommandObject *cmd_obj = command_obj_sp.get();
5246e3d8e7fSEugene Zelenko     CommandObject *sub_cmd_obj = nullptr;
525b9c1b51eSKate Stone     OptionArgVectorSP option_arg_vector_sp =
526b9c1b51eSKate Stone         OptionArgVectorSP(new OptionArgVector);
527ebc09c36SJim Ingham 
52811eb9c64SZachary Turner     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
5290d9a201eSRaphael Isemann       auto sub_command = args[0].ref();
53011eb9c64SZachary Turner       assert(!sub_command.empty());
5314574a890SZachary Turner       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
5324574a890SZachary Turner       if (!subcommand_obj_sp) {
533b9c1b51eSKate Stone         result.AppendErrorWithFormat(
534b9c1b51eSKate Stone             "'%s' is not a valid sub-command of '%s'.  "
535f415eeb4SCaroline Tice             "Unable to create alias.\n",
5364574a890SZachary Turner             args[0].c_str(), actual_command.c_str());
537ebc09c36SJim Ingham         result.SetStatus(eReturnStatusFailed);
538ebc09c36SJim Ingham         return false;
539ebc09c36SJim Ingham       }
5404574a890SZachary Turner 
5414574a890SZachary Turner       sub_cmd_obj = subcommand_obj_sp.get();
5424574a890SZachary Turner       use_subcommand = true;
5434574a890SZachary Turner       args.Shift(); // Shift the sub_command word off the argument vector.
5444574a890SZachary Turner       cmd_obj = sub_cmd_obj;
545ebc09c36SJim Ingham     }
546ebc09c36SJim Ingham 
547ebc09c36SJim Ingham     // Verify & handle any options/arguments passed to the alias command
548ebc09c36SJim Ingham 
549212130acSEnrico Granata     std::string args_string;
550212130acSEnrico Granata 
55111eb9c64SZachary Turner     if (!args.empty()) {
552b9c1b51eSKate Stone       CommandObjectSP tmp_sp =
553a9448872SJonas Devlieghere           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName());
554ebc09c36SJim Ingham       if (use_subcommand)
555a9448872SJonas Devlieghere         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName());
556ca90c47eSCaroline Tice 
557ca90c47eSCaroline Tice       args.GetCommandString(args_string);
558867b185dSCaroline Tice     }
559ebc09c36SJim Ingham 
560771ef6d4SMalcolm Parsons     if (m_interpreter.AliasExists(alias_command) ||
561771ef6d4SMalcolm Parsons         m_interpreter.UserCommandExists(alias_command)) {
562b9c1b51eSKate Stone       result.AppendWarningWithFormat(
5634574a890SZachary Turner           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
564ebc09c36SJim Ingham     }
565ebc09c36SJim Ingham 
566b9c1b51eSKate Stone     if (CommandAlias *alias = m_interpreter.AddAlias(
5674574a890SZachary Turner             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
568771ef6d4SMalcolm Parsons             args_string)) {
56945d0e238SEnrico Granata       if (m_command_options.m_help.OptionWasSet())
57045d0e238SEnrico Granata         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
57145d0e238SEnrico Granata       if (m_command_options.m_long_help.OptionWasSet())
57245d0e238SEnrico Granata         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
573ebc09c36SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
574b9c1b51eSKate Stone     } else {
575212130acSEnrico Granata       result.AppendError("Unable to create requested alias.\n");
576212130acSEnrico Granata       result.SetStatus(eReturnStatusFailed);
577212130acSEnrico Granata       return false;
578212130acSEnrico Granata     }
579ebc09c36SJim Ingham 
580ebc09c36SJim Ingham     return result.Succeeded();
581ebc09c36SJim Ingham   }
582ebc09c36SJim Ingham };
583ebc09c36SJim Ingham 
584ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
585ebc09c36SJim Ingham // CommandObjectCommandsUnalias
586ebc09c36SJim Ingham 
587b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed {
588ebc09c36SJim Ingham public:
5897428a18cSKate Stone   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
590b9c1b51eSKate Stone       : CommandObjectParsed(
591b9c1b51eSKate Stone             interpreter, "command unalias",
592b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command alias'.",
593b9c1b51eSKate Stone             nullptr) {
594405fe67fSCaroline Tice     CommandArgumentEntry arg;
595405fe67fSCaroline Tice     CommandArgumentData alias_arg;
596405fe67fSCaroline Tice 
597405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
598405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
599405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
600405fe67fSCaroline Tice 
601b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
602b9c1b51eSKate Stone     // argument entry.
603405fe67fSCaroline Tice     arg.push_back(alias_arg);
604405fe67fSCaroline Tice 
605405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
606405fe67fSCaroline Tice     m_arguments.push_back(arg);
607ebc09c36SJim Ingham   }
608ebc09c36SJim Ingham 
6096e3d8e7fSEugene Zelenko   ~CommandObjectCommandsUnalias() override = default;
610ebc09c36SJim Ingham 
61131fd64acSGongyu Deng   void
61231fd64acSGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
61331fd64acSGongyu Deng                            OptionElementVector &opt_element_vector) override {
61431fd64acSGongyu Deng     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
61531fd64acSGongyu Deng       return;
61631fd64acSGongyu Deng 
61731fd64acSGongyu Deng     for (const auto &ent : m_interpreter.GetAliases()) {
61831fd64acSGongyu Deng       request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
61931fd64acSGongyu Deng     }
62031fd64acSGongyu Deng   }
62131fd64acSGongyu Deng 
6225a988416SJim Ingham protected:
623b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
624ebc09c36SJim Ingham     CommandObject::CommandMap::iterator pos;
625ebc09c36SJim Ingham     CommandObject *cmd_obj;
626ebc09c36SJim Ingham 
62711eb9c64SZachary Turner     if (args.empty()) {
62811eb9c64SZachary Turner       result.AppendError("must call 'unalias' with a valid alias");
62911eb9c64SZachary Turner       result.SetStatus(eReturnStatusFailed);
63011eb9c64SZachary Turner       return false;
63111eb9c64SZachary Turner     }
63211eb9c64SZachary Turner 
6330d9a201eSRaphael Isemann     auto command_name = args[0].ref();
634a7015092SGreg Clayton     cmd_obj = m_interpreter.GetCommandObject(command_name);
6354574a890SZachary Turner     if (!cmd_obj) {
6364574a890SZachary Turner       result.AppendErrorWithFormat(
6374574a890SZachary Turner           "'%s' is not a known command.\nTry 'help' to see a "
6384574a890SZachary Turner           "current list of commands.\n",
639867e7d17SZachary Turner           args[0].c_str());
6404574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
6414574a890SZachary Turner       return false;
6424574a890SZachary Turner     }
6434574a890SZachary Turner 
644b9c1b51eSKate Stone     if (m_interpreter.CommandExists(command_name)) {
645b9c1b51eSKate Stone       if (cmd_obj->IsRemovable()) {
646b9c1b51eSKate Stone         result.AppendErrorWithFormat(
647b9c1b51eSKate Stone             "'%s' is not an alias, it is a debugger command which can be "
648b9c1b51eSKate Stone             "removed using the 'command delete' command.\n",
649867e7d17SZachary Turner             args[0].c_str());
650b9c1b51eSKate Stone       } else {
651b9c1b51eSKate Stone         result.AppendErrorWithFormat(
652b9c1b51eSKate Stone             "'%s' is a permanent debugger command and cannot be removed.\n",
653867e7d17SZachary Turner             args[0].c_str());
654b547278cSGreg Clayton       }
655ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
6564574a890SZachary Turner       return false;
6574574a890SZachary Turner     }
6584574a890SZachary Turner 
659b9c1b51eSKate Stone     if (!m_interpreter.RemoveAlias(command_name)) {
660a7015092SGreg Clayton       if (m_interpreter.AliasExists(command_name))
661b9c1b51eSKate Stone         result.AppendErrorWithFormat(
662867e7d17SZachary Turner             "Error occurred while attempting to unalias '%s'.\n",
663867e7d17SZachary Turner             args[0].c_str());
664ebc09c36SJim Ingham       else
665b9c1b51eSKate Stone         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
666867e7d17SZachary Turner                                      args[0].c_str());
667ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
6684574a890SZachary Turner       return false;
669ebc09c36SJim Ingham     }
670ebc09c36SJim Ingham 
6714574a890SZachary Turner     result.SetStatus(eReturnStatusSuccessFinishNoResult);
672ebc09c36SJim Ingham     return result.Succeeded();
673ebc09c36SJim Ingham   }
674ebc09c36SJim Ingham };
675ebc09c36SJim Ingham 
676b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete
677b547278cSGreg Clayton // CommandObjectCommandsDelete
678b547278cSGreg Clayton 
679b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed {
680b547278cSGreg Clayton public:
6817428a18cSKate Stone   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
682b9c1b51eSKate Stone       : CommandObjectParsed(
683b9c1b51eSKate Stone             interpreter, "command delete",
684b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command regex'.",
685b9c1b51eSKate Stone             nullptr) {
686b547278cSGreg Clayton     CommandArgumentEntry arg;
687b547278cSGreg Clayton     CommandArgumentData alias_arg;
688b547278cSGreg Clayton 
689b547278cSGreg Clayton     // Define the first (and only) variant of this arg.
690b547278cSGreg Clayton     alias_arg.arg_type = eArgTypeCommandName;
691b547278cSGreg Clayton     alias_arg.arg_repetition = eArgRepeatPlain;
692b547278cSGreg Clayton 
693b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
694b9c1b51eSKate Stone     // argument entry.
695b547278cSGreg Clayton     arg.push_back(alias_arg);
696b547278cSGreg Clayton 
697b547278cSGreg Clayton     // Push the data for the first argument into the m_arguments vector.
698b547278cSGreg Clayton     m_arguments.push_back(arg);
699b547278cSGreg Clayton   }
700b547278cSGreg Clayton 
7016e3d8e7fSEugene Zelenko   ~CommandObjectCommandsDelete() override = default;
702b547278cSGreg Clayton 
70331fd64acSGongyu Deng   void
70431fd64acSGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
70531fd64acSGongyu Deng                            OptionElementVector &opt_element_vector) override {
70631fd64acSGongyu Deng     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
70731fd64acSGongyu Deng       return;
70831fd64acSGongyu Deng 
70931fd64acSGongyu Deng     for (const auto &ent : m_interpreter.GetCommands()) {
71031fd64acSGongyu Deng       if (ent.second->IsRemovable())
71131fd64acSGongyu Deng         request.TryCompleteCurrentArg(ent.first, ent.second->GetHelp());
71231fd64acSGongyu Deng     }
71331fd64acSGongyu Deng   }
71431fd64acSGongyu Deng 
715b547278cSGreg Clayton protected:
716b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
717b547278cSGreg Clayton     CommandObject::CommandMap::iterator pos;
718b547278cSGreg Clayton 
71911eb9c64SZachary Turner     if (args.empty()) {
72011eb9c64SZachary Turner       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
72111eb9c64SZachary Turner                                    "defined regular expression command names",
722a449698cSZachary Turner                                    GetCommandName().str().c_str());
72311eb9c64SZachary Turner       result.SetStatus(eReturnStatusFailed);
724d77ea5b2SRaphael Isemann       return false;
72511eb9c64SZachary Turner     }
72611eb9c64SZachary Turner 
7270d9a201eSRaphael Isemann     auto command_name = args[0].ref();
7284574a890SZachary Turner     if (!m_interpreter.CommandExists(command_name)) {
72946d4aa21SEnrico Granata       StreamString error_msg_stream;
730d5b44036SJonas Devlieghere       const bool generate_upropos = true;
73146d4aa21SEnrico Granata       const bool generate_type_lookup = false;
732b9c1b51eSKate Stone       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
7334574a890SZachary Turner           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
734d5b44036SJonas Devlieghere           generate_upropos, generate_type_lookup);
735c156427dSZachary Turner       result.AppendError(error_msg_stream.GetString());
736b547278cSGreg Clayton       result.SetStatus(eReturnStatusFailed);
7374574a890SZachary Turner       return false;
738b547278cSGreg Clayton     }
739b547278cSGreg Clayton 
7404574a890SZachary Turner     if (!m_interpreter.RemoveCommand(command_name)) {
7414574a890SZachary Turner       result.AppendErrorWithFormat(
7424574a890SZachary Turner           "'%s' is a permanent debugger command and cannot be removed.\n",
743867e7d17SZachary Turner           args[0].c_str());
7444574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
7454574a890SZachary Turner       return false;
7464574a890SZachary Turner     }
7474574a890SZachary Turner 
7484574a890SZachary Turner     result.SetStatus(eReturnStatusSuccessFinishNoResult);
7494574a890SZachary Turner     return true;
750b547278cSGreg Clayton   }
751b547278cSGreg Clayton };
752b547278cSGreg Clayton 
753de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
7541f0f5b5bSZachary Turner 
75564becc11SRaphael Isemann #define LLDB_OPTIONS_regex
75664becc11SRaphael Isemann #include "CommandOptions.inc"
7571f0f5b5bSZachary Turner 
7585a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex
759de164aaaSGreg Clayton 
760b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed,
761b9c1b51eSKate Stone                                       public IOHandlerDelegateMultiline {
762de164aaaSGreg Clayton public:
7637428a18cSKate Stone   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
764b9c1b51eSKate Stone       : CommandObjectParsed(
765a925974bSAdrian Prantl             interpreter, "command regex",
766a925974bSAdrian Prantl             "Define a custom command in terms of "
767b9c1b51eSKate Stone             "existing commands by matching "
768b9c1b51eSKate Stone             "regular expressions.",
7690e5e5a79SGreg Clayton             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
770b9c1b51eSKate Stone         IOHandlerDelegateMultiline("",
771b9c1b51eSKate Stone                                    IOHandlerDelegate::Completion::LLDBCommand),
772b9c1b51eSKate Stone         m_options() {
773b9c1b51eSKate Stone     SetHelpLong(
774b9c1b51eSKate Stone         R"(
775b9c1b51eSKate Stone )"
776b9c1b51eSKate Stone         "This command allows the user to create powerful regular expression commands \
777ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \
778b9c1b51eSKate Stone using the regular expression substitution format of:"
779b9c1b51eSKate Stone         R"(
780ea671fbdSKate Stone 
781ea671fbdSKate Stone     s/<regex>/<subst>/
782ea671fbdSKate Stone 
783b9c1b51eSKate Stone )"
784b9c1b51eSKate Stone         "<regex> is a regular expression that can use parenthesis to capture regular \
785ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \
786b9c1b51eSKate Stone for the first match, %2 for the second, and so on."
787b9c1b51eSKate Stone         R"(
788ea671fbdSKate Stone 
789b9c1b51eSKate Stone )"
790b9c1b51eSKate Stone         "The regular expressions can all be specified on the command line if more than \
791ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \
792ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \
793b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition."
794b9c1b51eSKate Stone         R"(
795ea671fbdSKate Stone 
796ea671fbdSKate Stone EXAMPLES
797ea671fbdSKate Stone 
798b9c1b51eSKate Stone )"
799b9c1b51eSKate Stone         "The following example will define a regular expression command named 'f' that \
800ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
801b9c1b51eSKate Stone a number follows 'f':"
802b9c1b51eSKate Stone         R"(
803ea671fbdSKate Stone 
804b9c1b51eSKate Stone     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
805de164aaaSGreg Clayton   }
806de164aaaSGreg Clayton 
8076e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAddRegex() override = default;
808de164aaaSGreg Clayton 
8095a988416SJim Ingham protected:
8100affb582SDave Lee   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
8117ca15ba7SLawrence D'Anna     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
8120affb582SDave Lee     if (output_sp && interactive) {
8130affb582SDave Lee       output_sp->PutCString("Enter one or more sed substitution commands in "
814b9c1b51eSKate Stone                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
815b9c1b51eSKate Stone                             "substitution list with an empty line.\n");
81644d93782SGreg Clayton       output_sp->Flush();
81744d93782SGreg Clayton     }
81844d93782SGreg Clayton   }
81944d93782SGreg Clayton 
820b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
821b9c1b51eSKate Stone                               std::string &data) override {
82244d93782SGreg Clayton     io_handler.SetIsDone(true);
823d5b44036SJonas Devlieghere     if (m_regex_cmd_up) {
82444d93782SGreg Clayton       StringList lines;
825b9c1b51eSKate Stone       if (lines.SplitIntoLines(data)) {
82644d93782SGreg Clayton         bool check_only = false;
8274c78b788SRaphael Isemann         for (const std::string &line : lines) {
8284c78b788SRaphael Isemann           Status error = AppendRegexSubstitution(line, check_only);
829b9c1b51eSKate Stone           if (error.Fail()) {
83057179860SJonas Devlieghere             if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) {
83157179860SJonas Devlieghere               StreamSP out_stream = GetDebugger().GetAsyncOutputStream();
83244d93782SGreg Clayton               out_stream->Printf("error: %s\n", error.AsCString());
83344d93782SGreg Clayton             }
83444d93782SGreg Clayton           }
83544d93782SGreg Clayton         }
83644d93782SGreg Clayton       }
837d5b44036SJonas Devlieghere       if (m_regex_cmd_up->HasRegexEntries()) {
838d5b44036SJonas Devlieghere         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
83944d93782SGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
84044d93782SGreg Clayton       }
84144d93782SGreg Clayton     }
84244d93782SGreg Clayton   }
84344d93782SGreg Clayton 
844b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
8455a988416SJim Ingham     const size_t argc = command.GetArgumentCount();
846b9c1b51eSKate Stone     if (argc == 0) {
847b9c1b51eSKate Stone       result.AppendError("usage: 'command regex <command-name> "
848b9c1b51eSKate Stone                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
8490e5e5a79SGreg Clayton       result.SetStatus(eReturnStatusFailed);
85011eb9c64SZachary Turner       return false;
85111eb9c64SZachary Turner     }
85211eb9c64SZachary Turner 
85397206d57SZachary Turner     Status error;
8540d9a201eSRaphael Isemann     auto name = command[0].ref();
855a8f3ae7cSJonas Devlieghere     m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>(
8564574a890SZachary Turner         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
8574574a890SZachary Turner         true);
8580e5e5a79SGreg Clayton 
859b9c1b51eSKate Stone     if (argc == 1) {
86057179860SJonas Devlieghere       Debugger &debugger = GetDebugger();
861e30f11d9SKate Stone       bool color_prompt = debugger.GetUseColor();
86244d93782SGreg Clayton       const bool multiple_lines = true; // Get multiple lines
863b9c1b51eSKate Stone       IOHandlerSP io_handler_sp(new IOHandlerEditline(
864b9c1b51eSKate Stone           debugger, IOHandler::Type::Other,
86573d80faaSGreg Clayton           "lldb-regex",          // Name of input reader for history
866514d8cd8SZachary Turner           llvm::StringRef("> "), // Prompt
867514d8cd8SZachary Turner           llvm::StringRef(),     // Continuation prompt
868b9c1b51eSKate Stone           multiple_lines, color_prompt,
869f6913cd7SGreg Clayton           0, // Don't show line numbers
870d77c2e09SJonas Devlieghere           *this, nullptr));
87144d93782SGreg Clayton 
872b9c1b51eSKate Stone       if (io_handler_sp) {
8737ce2de2cSJonas Devlieghere         debugger.RunIOHandlerAsync(io_handler_sp);
874de164aaaSGreg Clayton         result.SetStatus(eReturnStatusSuccessFinishNoResult);
875de164aaaSGreg Clayton       }
876b9c1b51eSKate Stone     } else {
87797d2c401SZachary Turner       for (auto &entry : command.entries().drop_front()) {
87844d93782SGreg Clayton         bool check_only = false;
8790d9a201eSRaphael Isemann         error = AppendRegexSubstitution(entry.ref(), check_only);
8800e5e5a79SGreg Clayton         if (error.Fail())
8810e5e5a79SGreg Clayton           break;
8820e5e5a79SGreg Clayton       }
8830e5e5a79SGreg Clayton 
884b9c1b51eSKate Stone       if (error.Success()) {
8850e5e5a79SGreg Clayton         AddRegexCommandToInterpreter();
8860e5e5a79SGreg Clayton       }
8870e5e5a79SGreg Clayton     }
888b9c1b51eSKate Stone     if (error.Fail()) {
8890e5e5a79SGreg Clayton       result.AppendError(error.AsCString());
890de164aaaSGreg Clayton       result.SetStatus(eReturnStatusFailed);
891de164aaaSGreg Clayton     }
8920e5e5a79SGreg Clayton 
893de164aaaSGreg Clayton     return result.Succeeded();
894de164aaaSGreg Clayton   }
895de164aaaSGreg Clayton 
89697206d57SZachary Turner   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
897b9c1b51eSKate Stone                                  bool check_only) {
89897206d57SZachary Turner     Status error;
8990e5e5a79SGreg Clayton 
900d5b44036SJonas Devlieghere     if (!m_regex_cmd_up) {
901b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
902b9c1b51eSKate Stone           "invalid regular expression command object for: '%.*s'",
903b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
9040e5e5a79SGreg Clayton       return error;
905de164aaaSGreg Clayton     }
9060e5e5a79SGreg Clayton 
9070e5e5a79SGreg Clayton     size_t regex_sed_size = regex_sed.size();
9080e5e5a79SGreg Clayton 
909b9c1b51eSKate Stone     if (regex_sed_size <= 1) {
910b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
911b9c1b51eSKate Stone           "regular expression substitution string is too short: '%.*s'",
912b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
9130e5e5a79SGreg Clayton       return error;
9140e5e5a79SGreg Clayton     }
9150e5e5a79SGreg Clayton 
916b9c1b51eSKate Stone     if (regex_sed[0] != 's') {
917b9c1b51eSKate Stone       error.SetErrorStringWithFormat("regular expression substitution string "
918b9c1b51eSKate Stone                                      "doesn't start with 's': '%.*s'",
919b9c1b51eSKate Stone                                      (int)regex_sed.size(), regex_sed.data());
9200e5e5a79SGreg Clayton       return error;
9210e5e5a79SGreg Clayton     }
9220e5e5a79SGreg Clayton     const size_t first_separator_char_pos = 1;
92305097246SAdrian Prantl     // use the char that follows 's' as the regex separator character so we can
92405097246SAdrian Prantl     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
9250e5e5a79SGreg Clayton     const char separator_char = regex_sed[first_separator_char_pos];
926b9c1b51eSKate Stone     const size_t second_separator_char_pos =
927b9c1b51eSKate Stone         regex_sed.find(separator_char, first_separator_char_pos + 1);
9280e5e5a79SGreg Clayton 
929b9c1b51eSKate Stone     if (second_separator_char_pos == std::string::npos) {
930b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
931b9c1b51eSKate Stone           "missing second '%c' separator char after '%.*s' in '%.*s'",
9320e5e5a79SGreg Clayton           separator_char,
9330e5e5a79SGreg Clayton           (int)(regex_sed.size() - first_separator_char_pos - 1),
934ea508635SGreg Clayton           regex_sed.data() + (first_separator_char_pos + 1),
935b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
9360e5e5a79SGreg Clayton       return error;
9370e5e5a79SGreg Clayton     }
9380e5e5a79SGreg Clayton 
939b9c1b51eSKate Stone     const size_t third_separator_char_pos =
940b9c1b51eSKate Stone         regex_sed.find(separator_char, second_separator_char_pos + 1);
9410e5e5a79SGreg Clayton 
942b9c1b51eSKate Stone     if (third_separator_char_pos == std::string::npos) {
943b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
944b9c1b51eSKate Stone           "missing third '%c' separator char after '%.*s' in '%.*s'",
9450e5e5a79SGreg Clayton           separator_char,
9460e5e5a79SGreg Clayton           (int)(regex_sed.size() - second_separator_char_pos - 1),
947ea508635SGreg Clayton           regex_sed.data() + (second_separator_char_pos + 1),
948b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
9490e5e5a79SGreg Clayton       return error;
9500e5e5a79SGreg Clayton     }
9510e5e5a79SGreg Clayton 
952b9c1b51eSKate Stone     if (third_separator_char_pos != regex_sed_size - 1) {
95305097246SAdrian Prantl       // Make sure that everything that follows the last regex separator char
954b9c1b51eSKate Stone       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
955b9c1b51eSKate Stone                                       third_separator_char_pos + 1) !=
956b9c1b51eSKate Stone           std::string::npos) {
957b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
958b9c1b51eSKate Stone             "extra data found after the '%.*s' regular expression substitution "
959b9c1b51eSKate Stone             "string: '%.*s'",
960b9c1b51eSKate Stone             (int)third_separator_char_pos + 1, regex_sed.data(),
9610e5e5a79SGreg Clayton             (int)(regex_sed.size() - third_separator_char_pos - 1),
9620e5e5a79SGreg Clayton             regex_sed.data() + (third_separator_char_pos + 1));
9630e5e5a79SGreg Clayton         return error;
9640e5e5a79SGreg Clayton       }
965b9c1b51eSKate Stone     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
966b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
967b9c1b51eSKate Stone           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
968b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
9690e5e5a79SGreg Clayton           regex_sed.data());
9700e5e5a79SGreg Clayton       return error;
971b9c1b51eSKate Stone     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
972b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
973b9c1b51eSKate Stone           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
974b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
9750e5e5a79SGreg Clayton           regex_sed.data());
9760e5e5a79SGreg Clayton       return error;
9770e5e5a79SGreg Clayton     }
97844d93782SGreg Clayton 
979b9c1b51eSKate Stone     if (!check_only) {
980adcd0268SBenjamin Kramer       std::string regex(std::string(regex_sed.substr(
981adcd0268SBenjamin Kramer           first_separator_char_pos + 1,
982adcd0268SBenjamin Kramer           second_separator_char_pos - first_separator_char_pos - 1)));
983adcd0268SBenjamin Kramer       std::string subst(std::string(regex_sed.substr(
984adcd0268SBenjamin Kramer           second_separator_char_pos + 1,
985adcd0268SBenjamin Kramer           third_separator_char_pos - second_separator_char_pos - 1)));
98643224195SRaphael Isemann       m_regex_cmd_up->AddRegexCommand(regex, subst);
98744d93782SGreg Clayton     }
9880e5e5a79SGreg Clayton     return error;
989de164aaaSGreg Clayton   }
990de164aaaSGreg Clayton 
991b9c1b51eSKate Stone   void AddRegexCommandToInterpreter() {
992d5b44036SJonas Devlieghere     if (m_regex_cmd_up) {
993d5b44036SJonas Devlieghere       if (m_regex_cmd_up->HasRegexEntries()) {
994d5b44036SJonas Devlieghere         CommandObjectSP cmd_sp(m_regex_cmd_up.release());
995de164aaaSGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
996de164aaaSGreg Clayton       }
997de164aaaSGreg Clayton     }
998de164aaaSGreg Clayton   }
999de164aaaSGreg Clayton 
1000de164aaaSGreg Clayton private:
1001d5b44036SJonas Devlieghere   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up;
1002de164aaaSGreg Clayton 
1003b9c1b51eSKate Stone   class CommandOptions : public Options {
1004de164aaaSGreg Clayton   public:
1005b9c1b51eSKate Stone     CommandOptions() : Options() {}
1006de164aaaSGreg Clayton 
10076e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1008de164aaaSGreg Clayton 
100997206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1010b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
101197206d57SZachary Turner       Status error;
10123bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1013de164aaaSGreg Clayton 
1014b9c1b51eSKate Stone       switch (short_option) {
1015de164aaaSGreg Clayton       case 'h':
1016adcd0268SBenjamin Kramer         m_help.assign(std::string(option_arg));
1017de164aaaSGreg Clayton         break;
1018de164aaaSGreg Clayton       case 's':
1019adcd0268SBenjamin Kramer         m_syntax.assign(std::string(option_arg));
1020de164aaaSGreg Clayton         break;
1021de164aaaSGreg Clayton       default:
102236162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
1023de164aaaSGreg Clayton       }
1024de164aaaSGreg Clayton 
1025de164aaaSGreg Clayton       return error;
1026de164aaaSGreg Clayton     }
1027de164aaaSGreg Clayton 
1028b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1029de164aaaSGreg Clayton       m_help.clear();
1030de164aaaSGreg Clayton       m_syntax.clear();
1031de164aaaSGreg Clayton     }
1032de164aaaSGreg Clayton 
10331f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
103470602439SZachary Turner       return llvm::makeArrayRef(g_regex_options);
10351f0f5b5bSZachary Turner     }
1036de164aaaSGreg Clayton 
1037daed98e5SShivam Mittal     llvm::StringRef GetHelp() { return m_help; }
10386e3d8e7fSEugene Zelenko 
1039daed98e5SShivam Mittal     llvm::StringRef GetSyntax() { return m_syntax; }
10406e3d8e7fSEugene Zelenko 
1041de164aaaSGreg Clayton   protected:
10426e3d8e7fSEugene Zelenko     // Instance variables to hold the values for command options.
10436e3d8e7fSEugene Zelenko 
1044de164aaaSGreg Clayton     std::string m_help;
1045de164aaaSGreg Clayton     std::string m_syntax;
1046de164aaaSGreg Clayton   };
1047de164aaaSGreg Clayton 
1048b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
1049de164aaaSGreg Clayton 
10505a988416SJim Ingham   CommandOptions m_options;
1051de164aaaSGreg Clayton };
1052de164aaaSGreg Clayton 
1053b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw {
1054223383edSEnrico Granata public:
1055b9c1b51eSKate Stone   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1056b9c1b51eSKate Stone                               std::string funct, std::string help,
1057b9c1b51eSKate Stone                               ScriptedCommandSynchronicity synch)
1058a925974bSAdrian Prantl       : CommandObjectRaw(interpreter, name), m_function_name(funct),
1059a925974bSAdrian Prantl         m_synchro(synch), m_fetched_help_long(false) {
1060735152e3SEnrico Granata     if (!help.empty())
1061442f6530SZachary Turner       SetHelp(help);
1062b9c1b51eSKate Stone     else {
1063735152e3SEnrico Granata       StreamString stream;
1064735152e3SEnrico Granata       stream.Printf("For more information run 'help %s'", name.c_str());
1065c156427dSZachary Turner       SetHelp(stream.GetString());
1066735152e3SEnrico Granata     }
1067223383edSEnrico Granata   }
1068223383edSEnrico Granata 
10696e3d8e7fSEugene Zelenko   ~CommandObjectPythonFunction() override = default;
1070223383edSEnrico Granata 
1071b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
10725a988416SJim Ingham 
1073b9c1b51eSKate Stone   const std::string &GetFunctionName() { return m_function_name; }
10745a988416SJim Ingham 
1075b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
10765a988416SJim Ingham 
1077442f6530SZachary Turner   llvm::StringRef GetHelpLong() override {
1078442f6530SZachary Turner     if (m_fetched_help_long)
1079442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1080442f6530SZachary Turner 
10812b29b432SJonas Devlieghere     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1082442f6530SZachary Turner     if (!scripter)
1083442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1084442f6530SZachary Turner 
1085fac939e9SEnrico Granata     std::string docstring;
1086442f6530SZachary Turner     m_fetched_help_long =
1087442f6530SZachary Turner         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1088fac939e9SEnrico Granata     if (!docstring.empty())
1089442f6530SZachary Turner       SetHelpLong(docstring);
1090fac939e9SEnrico Granata     return CommandObjectRaw::GetHelpLong();
1091fac939e9SEnrico Granata   }
1092fac939e9SEnrico Granata 
10935a988416SJim Ingham protected:
10944d51a902SRaphael Isemann   bool DoExecute(llvm::StringRef raw_command_line,
1095b9c1b51eSKate Stone                  CommandReturnObject &result) override {
10962b29b432SJonas Devlieghere     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1097223383edSEnrico Granata 
109897206d57SZachary Turner     Status error;
1099223383edSEnrico Granata 
110070f11f88SJim Ingham     result.SetStatus(eReturnStatusInvalid);
110170f11f88SJim Ingham 
1102a925974bSAdrian Prantl     if (!scripter || !scripter->RunScriptBasedCommand(
1103a925974bSAdrian Prantl                          m_function_name.c_str(), raw_command_line, m_synchro,
1104a925974bSAdrian Prantl                          result, error, m_exe_ctx)) {
1105223383edSEnrico Granata       result.AppendError(error.AsCString());
1106223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1107b9c1b51eSKate Stone     } else {
110870f11f88SJim Ingham       // Don't change the status if the command already set it...
1109b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1110c156427dSZachary Turner         if (result.GetOutputData().empty())
1111223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
111270f11f88SJim Ingham         else
111370f11f88SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishResult);
111470f11f88SJim Ingham       }
111570f11f88SJim Ingham     }
1116223383edSEnrico Granata 
1117223383edSEnrico Granata     return result.Succeeded();
1118223383edSEnrico Granata   }
1119223383edSEnrico Granata 
11206e3d8e7fSEugene Zelenko private:
11216e3d8e7fSEugene Zelenko   std::string m_function_name;
11226e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
11236e3d8e7fSEugene Zelenko   bool m_fetched_help_long;
1124223383edSEnrico Granata };
1125223383edSEnrico Granata 
1126b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw {
11279fe00e52SEnrico Granata public:
11289fe00e52SEnrico Granata   CommandObjectScriptingObject(CommandInterpreter &interpreter,
11299fe00e52SEnrico Granata                                std::string name,
11300641ca1aSZachary Turner                                StructuredData::GenericSP cmd_obj_sp,
1131b9c1b51eSKate Stone                                ScriptedCommandSynchronicity synch)
1132a925974bSAdrian Prantl       : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp),
1133a925974bSAdrian Prantl         m_synchro(synch), m_fetched_help_short(false),
1134b9c1b51eSKate Stone         m_fetched_help_long(false) {
11359fe00e52SEnrico Granata     StreamString stream;
11369fe00e52SEnrico Granata     stream.Printf("For more information run 'help %s'", name.c_str());
1137c156427dSZachary Turner     SetHelp(stream.GetString());
11382b29b432SJonas Devlieghere     if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter())
1139e87764f2SEnrico Granata       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
11409fe00e52SEnrico Granata   }
11419fe00e52SEnrico Granata 
11426e3d8e7fSEugene Zelenko   ~CommandObjectScriptingObject() override = default;
11439fe00e52SEnrico Granata 
1144b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
11459fe00e52SEnrico Granata 
1146b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
11479fe00e52SEnrico Granata 
1148442f6530SZachary Turner   llvm::StringRef GetHelp() override {
1149442f6530SZachary Turner     if (m_fetched_help_short)
1150442f6530SZachary Turner       return CommandObjectRaw::GetHelp();
11512b29b432SJonas Devlieghere     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1152442f6530SZachary Turner     if (!scripter)
1153442f6530SZachary Turner       return CommandObjectRaw::GetHelp();
11546f79bb2dSEnrico Granata     std::string docstring;
1155b9c1b51eSKate Stone     m_fetched_help_short =
1156b9c1b51eSKate Stone         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
11576f79bb2dSEnrico Granata     if (!docstring.empty())
1158442f6530SZachary Turner       SetHelp(docstring);
1159442f6530SZachary Turner 
11606f79bb2dSEnrico Granata     return CommandObjectRaw::GetHelp();
11616f79bb2dSEnrico Granata   }
11626f79bb2dSEnrico Granata 
1163442f6530SZachary Turner   llvm::StringRef GetHelpLong() override {
1164442f6530SZachary Turner     if (m_fetched_help_long)
1165442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1166442f6530SZachary Turner 
11672b29b432SJonas Devlieghere     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
1168442f6530SZachary Turner     if (!scripter)
1169442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1170442f6530SZachary Turner 
11716f79bb2dSEnrico Granata     std::string docstring;
1172b9c1b51eSKate Stone     m_fetched_help_long =
1173b9c1b51eSKate Stone         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
11746f79bb2dSEnrico Granata     if (!docstring.empty())
1175442f6530SZachary Turner       SetHelpLong(docstring);
11769fe00e52SEnrico Granata     return CommandObjectRaw::GetHelpLong();
11779fe00e52SEnrico Granata   }
11789fe00e52SEnrico Granata 
11799fe00e52SEnrico Granata protected:
11804d51a902SRaphael Isemann   bool DoExecute(llvm::StringRef raw_command_line,
1181b9c1b51eSKate Stone                  CommandReturnObject &result) override {
11822b29b432SJonas Devlieghere     ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter();
11839fe00e52SEnrico Granata 
118497206d57SZachary Turner     Status error;
11859fe00e52SEnrico Granata 
11869fe00e52SEnrico Granata     result.SetStatus(eReturnStatusInvalid);
11879fe00e52SEnrico Granata 
1188b9c1b51eSKate Stone     if (!scripter ||
1189b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1190b9c1b51eSKate Stone                                          m_synchro, result, error, m_exe_ctx)) {
11919fe00e52SEnrico Granata       result.AppendError(error.AsCString());
11929fe00e52SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1193b9c1b51eSKate Stone     } else {
11949fe00e52SEnrico Granata       // Don't change the status if the command already set it...
1195b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1196c156427dSZachary Turner         if (result.GetOutputData().empty())
11979fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
11989fe00e52SEnrico Granata         else
11999fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishResult);
12009fe00e52SEnrico Granata       }
12019fe00e52SEnrico Granata     }
12029fe00e52SEnrico Granata 
12039fe00e52SEnrico Granata     return result.Succeeded();
12049fe00e52SEnrico Granata   }
12059fe00e52SEnrico Granata 
12066e3d8e7fSEugene Zelenko private:
12076e3d8e7fSEugene Zelenko   StructuredData::GenericSP m_cmd_obj_sp;
12086e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
12096e3d8e7fSEugene Zelenko   bool m_fetched_help_short : 1;
12106e3d8e7fSEugene Zelenko   bool m_fetched_help_long : 1;
12119fe00e52SEnrico Granata };
12129fe00e52SEnrico Granata 
1213a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport
121464becc11SRaphael Isemann #define LLDB_OPTIONS_script_import
121564becc11SRaphael Isemann #include "CommandOptions.inc"
12161f0f5b5bSZachary Turner 
1217b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed {
12185a988416SJim Ingham public:
1219b9c1b51eSKate Stone   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1220b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script import",
1221b9c1b51eSKate Stone                             "Import a scripting module in LLDB.", nullptr),
1222b9c1b51eSKate Stone         m_options() {
12235a988416SJim Ingham     CommandArgumentEntry arg1;
12245a988416SJim Ingham     CommandArgumentData cmd_arg;
12255a988416SJim Ingham 
12265a988416SJim Ingham     // Define the first (and only) variant of this arg.
12275a988416SJim Ingham     cmd_arg.arg_type = eArgTypeFilename;
12283b00e35bSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlus;
12295a988416SJim Ingham 
1230b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1231b9c1b51eSKate Stone     // argument entry.
12325a988416SJim Ingham     arg1.push_back(cmd_arg);
12335a988416SJim Ingham 
12345a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
12355a988416SJim Ingham     m_arguments.push_back(arg1);
12365a988416SJim Ingham   }
12375a988416SJim Ingham 
12386e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptImport() override = default;
12395a988416SJim Ingham 
1240ae34ed2cSRaphael Isemann   void
1241ae34ed2cSRaphael Isemann   HandleArgumentCompletion(CompletionRequest &request,
12422443bbd4SRaphael Isemann                            OptionElementVector &opt_element_vector) override {
1243b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
1244b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1245a2e76c0bSRaphael Isemann         request, nullptr);
12465a988416SJim Ingham   }
12475a988416SJim Ingham 
1248b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
12495a988416SJim Ingham 
12505a988416SJim Ingham protected:
1251b9c1b51eSKate Stone   class CommandOptions : public Options {
12520a305db7SEnrico Granata   public:
1253b9c1b51eSKate Stone     CommandOptions() : Options() {}
12540a305db7SEnrico Granata 
12556e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
12560a305db7SEnrico Granata 
125797206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1258b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
125997206d57SZachary Turner       Status error;
12603bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
12610a305db7SEnrico Granata 
1262b9c1b51eSKate Stone       switch (short_option) {
12630a305db7SEnrico Granata       case 'r':
126415625112SJonas Devlieghere         // NO-OP
12650a305db7SEnrico Granata         break;
126600bb397bSJonas Devlieghere       case 'c':
126700bb397bSJonas Devlieghere         relative_to_command_file = true;
126800bb397bSJonas Devlieghere         break;
12690a305db7SEnrico Granata       default:
127036162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
12710a305db7SEnrico Granata       }
12720a305db7SEnrico Granata 
12730a305db7SEnrico Granata       return error;
12740a305db7SEnrico Granata     }
12750a305db7SEnrico Granata 
1276b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
127700bb397bSJonas Devlieghere       relative_to_command_file = false;
12780a305db7SEnrico Granata     }
12790a305db7SEnrico Granata 
12801f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
128170602439SZachary Turner       return llvm::makeArrayRef(g_script_import_options);
12821f0f5b5bSZachary Turner     }
128300bb397bSJonas Devlieghere     bool relative_to_command_file = false;
12840a305db7SEnrico Granata   };
12850a305db7SEnrico Granata 
1286b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
128711eb9c64SZachary Turner     if (command.empty()) {
12883b00e35bSEnrico Granata       result.AppendError("command script import needs one or more arguments");
1289a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1290a9dbf432SEnrico Granata       return false;
1291a9dbf432SEnrico Granata     }
1292a9dbf432SEnrico Granata 
129300bb397bSJonas Devlieghere     FileSpec source_dir = {};
129400bb397bSJonas Devlieghere     if (m_options.relative_to_command_file) {
129500bb397bSJonas Devlieghere       source_dir = GetDebugger().GetCommandInterpreter().GetCurrentSourceDir();
129600bb397bSJonas Devlieghere       if (!source_dir) {
129700bb397bSJonas Devlieghere         result.AppendError("command script import -c can only be specified "
129800bb397bSJonas Devlieghere                            "from a command file");
129900bb397bSJonas Devlieghere         result.SetStatus(eReturnStatusFailed);
130000bb397bSJonas Devlieghere         return false;
130100bb397bSJonas Devlieghere       }
130200bb397bSJonas Devlieghere     }
130300bb397bSJonas Devlieghere 
130411eb9c64SZachary Turner     for (auto &entry : command.entries()) {
130597206d57SZachary Turner       Status error;
1306a9dbf432SEnrico Granata 
1307c9d645d3SGreg Clayton       const bool init_session = true;
1308b9c1b51eSKate Stone       // FIXME: this is necessary because CommandObject::CheckRequirements()
130911eb9c64SZachary Turner       // assumes that commands won't ever be recursively invoked, but it's
131011eb9c64SZachary Turner       // actually possible to craft a Python script that does other "command
131105097246SAdrian Prantl       // script imports" in __lldb_init_module the real fix is to have
131205097246SAdrian Prantl       // recursive commands possible with a CommandInvocation object separate
131305097246SAdrian Prantl       // from the CommandObject itself, so that recursive command invocations
131405097246SAdrian Prantl       // won't stomp on each other (wrt to execution contents, options, and
131505097246SAdrian Prantl       // more)
1316078551c7SEnrico Granata       m_exe_ctx.Clear();
13172b29b432SJonas Devlieghere       if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule(
131800bb397bSJonas Devlieghere               entry.c_str(), init_session, error, nullptr, source_dir)) {
1319a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1320b9c1b51eSKate Stone       } else {
1321b9c1b51eSKate Stone         result.AppendErrorWithFormat("module importing failed: %s",
1322b9c1b51eSKate Stone                                      error.AsCString());
1323a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusFailed);
1324a9dbf432SEnrico Granata       }
13253b00e35bSEnrico Granata     }
1326a9dbf432SEnrico Granata 
1327a9dbf432SEnrico Granata     return result.Succeeded();
1328a9dbf432SEnrico Granata   }
13290a305db7SEnrico Granata 
13305a988416SJim Ingham   CommandOptions m_options;
1331a9dbf432SEnrico Granata };
1332223383edSEnrico Granata 
1333223383edSEnrico Granata // CommandObjectCommandsScriptAdd
13348fe53c49STatyana Krasnukha static constexpr OptionEnumValueElement g_script_synchro_type[] = {
1335e063ecccSJonas Devlieghere     {
1336e063ecccSJonas Devlieghere         eScriptedCommandSynchronicitySynchronous,
1337e063ecccSJonas Devlieghere         "synchronous",
1338e063ecccSJonas Devlieghere         "Run synchronous",
1339e063ecccSJonas Devlieghere     },
1340e063ecccSJonas Devlieghere     {
1341e063ecccSJonas Devlieghere         eScriptedCommandSynchronicityAsynchronous,
1342e063ecccSJonas Devlieghere         "asynchronous",
1343e063ecccSJonas Devlieghere         "Run asynchronous",
1344e063ecccSJonas Devlieghere     },
1345e063ecccSJonas Devlieghere     {
1346e063ecccSJonas Devlieghere         eScriptedCommandSynchronicityCurrentValue,
1347e063ecccSJonas Devlieghere         "current",
1348e063ecccSJonas Devlieghere         "Do not alter current setting",
1349e063ecccSJonas Devlieghere     },
1350e063ecccSJonas Devlieghere };
13511f0f5b5bSZachary Turner 
13528fe53c49STatyana Krasnukha static constexpr OptionEnumValues ScriptSynchroType() {
13538fe53c49STatyana Krasnukha   return OptionEnumValues(g_script_synchro_type);
13548fe53c49STatyana Krasnukha }
13558fe53c49STatyana Krasnukha 
135664becc11SRaphael Isemann #define LLDB_OPTIONS_script_add
135764becc11SRaphael Isemann #include "CommandOptions.inc"
13581f0f5b5bSZachary Turner 
1359b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1360b9c1b51eSKate Stone                                        public IOHandlerDelegateMultiline {
13615a988416SJim Ingham public:
1362b9c1b51eSKate Stone   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1363b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script add",
13645a988416SJim Ingham                             "Add a scripted function as an LLDB command.",
13656e3d8e7fSEugene Zelenko                             nullptr),
1366b9c1b51eSKate Stone         IOHandlerDelegateMultiline("DONE"), m_options() {
13675a988416SJim Ingham     CommandArgumentEntry arg1;
13685a988416SJim Ingham     CommandArgumentData cmd_arg;
13695a988416SJim Ingham 
13705a988416SJim Ingham     // Define the first (and only) variant of this arg.
13715a988416SJim Ingham     cmd_arg.arg_type = eArgTypeCommandName;
13725a988416SJim Ingham     cmd_arg.arg_repetition = eArgRepeatPlain;
13735a988416SJim Ingham 
1374b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1375b9c1b51eSKate Stone     // argument entry.
13765a988416SJim Ingham     arg1.push_back(cmd_arg);
13775a988416SJim Ingham 
13785a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
13795a988416SJim Ingham     m_arguments.push_back(arg1);
13805a988416SJim Ingham   }
13815a988416SJim Ingham 
13826e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptAdd() override = default;
13835a988416SJim Ingham 
1384b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
13855a988416SJim Ingham 
13865a988416SJim Ingham protected:
1387b9c1b51eSKate Stone   class CommandOptions : public Options {
1388223383edSEnrico Granata   public:
1389b9c1b51eSKate Stone     CommandOptions()
1390*9494c510SJonas Devlieghere         : Options(), m_class_name(), m_funct_name(), m_short_help() {}
1391223383edSEnrico Granata 
13926e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1393223383edSEnrico Granata 
139497206d57SZachary Turner     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1395b9c1b51eSKate Stone                           ExecutionContext *execution_context) override {
139697206d57SZachary Turner       Status error;
13973bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1398223383edSEnrico Granata 
1399b9c1b51eSKate Stone       switch (short_option) {
1400223383edSEnrico Granata       case 'f':
1401fe11483bSZachary Turner         if (!option_arg.empty())
1402adcd0268SBenjamin Kramer           m_funct_name = std::string(option_arg);
1403735152e3SEnrico Granata         break;
14049fe00e52SEnrico Granata       case 'c':
1405fe11483bSZachary Turner         if (!option_arg.empty())
1406adcd0268SBenjamin Kramer           m_class_name = std::string(option_arg);
14079fe00e52SEnrico Granata         break;
1408735152e3SEnrico Granata       case 'h':
1409fe11483bSZachary Turner         if (!option_arg.empty())
1410adcd0268SBenjamin Kramer           m_short_help = std::string(option_arg);
1411223383edSEnrico Granata         break;
14120a305db7SEnrico Granata       case 's':
1413b9c1b51eSKate Stone         m_synchronicity =
141447cbf4a0SPavel Labath             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1415fe11483bSZachary Turner                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
14160a305db7SEnrico Granata         if (!error.Success())
1417b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1418fe11483bSZachary Turner               "unrecognized value for synchronicity '%s'",
1419fe11483bSZachary Turner               option_arg.str().c_str());
14200a305db7SEnrico Granata         break;
1421223383edSEnrico Granata       default:
142236162014SRaphael Isemann         llvm_unreachable("Unimplemented option");
1423223383edSEnrico Granata       }
1424223383edSEnrico Granata 
1425223383edSEnrico Granata       return error;
1426223383edSEnrico Granata     }
1427223383edSEnrico Granata 
1428b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
14299fe00e52SEnrico Granata       m_class_name.clear();
1430735152e3SEnrico Granata       m_funct_name.clear();
1431735152e3SEnrico Granata       m_short_help.clear();
143244d93782SGreg Clayton       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1433223383edSEnrico Granata     }
1434223383edSEnrico Granata 
14351f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
143670602439SZachary Turner       return llvm::makeArrayRef(g_script_add_options);
14371f0f5b5bSZachary Turner     }
1438223383edSEnrico Granata 
1439223383edSEnrico Granata     // Instance variables to hold the values for command options.
1440223383edSEnrico Granata 
14419fe00e52SEnrico Granata     std::string m_class_name;
1442223383edSEnrico Granata     std::string m_funct_name;
1443735152e3SEnrico Granata     std::string m_short_help;
1444*9494c510SJonas Devlieghere     ScriptedCommandSynchronicity m_synchronicity =
1445*9494c510SJonas Devlieghere         eScriptedCommandSynchronicitySynchronous;
1446223383edSEnrico Granata   };
1447223383edSEnrico Granata 
14480affb582SDave Lee   void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
14497ca15ba7SLawrence D'Anna     StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
14500affb582SDave Lee     if (output_sp && interactive) {
145144d93782SGreg Clayton       output_sp->PutCString(g_python_command_instructions);
145244d93782SGreg Clayton       output_sp->Flush();
1453223383edSEnrico Granata     }
1454223383edSEnrico Granata   }
1455223383edSEnrico Granata 
1456b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1457b9c1b51eSKate Stone                               std::string &data) override {
14587ca15ba7SLawrence D'Anna     StreamFileSP error_sp = io_handler.GetErrorStreamFileSP();
145944d93782SGreg Clayton 
14602b29b432SJonas Devlieghere     ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1461b9c1b51eSKate Stone     if (interpreter) {
146244d93782SGreg Clayton 
146344d93782SGreg Clayton       StringList lines;
146444d93782SGreg Clayton       lines.SplitIntoLines(data);
1465b9c1b51eSKate Stone       if (lines.GetSize() > 0) {
1466a73b7df7SEnrico Granata         std::string funct_name_str;
1467b9c1b51eSKate Stone         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1468b9c1b51eSKate Stone           if (funct_name_str.empty()) {
1469b9c1b51eSKate Stone             error_sp->Printf("error: unable to obtain a function name, didn't "
1470b9c1b51eSKate Stone                              "add python command.\n");
147144d93782SGreg Clayton             error_sp->Flush();
1472b9c1b51eSKate Stone           } else {
1473223383edSEnrico Granata             // everything should be fine now, let's add this alias
1474223383edSEnrico Granata 
1475b9c1b51eSKate Stone             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1476771ef6d4SMalcolm Parsons                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
147744d93782SGreg Clayton                 m_synchronicity));
1478223383edSEnrico Granata 
1479b9c1b51eSKate Stone             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1480b9c1b51eSKate Stone                                               true)) {
1481b9c1b51eSKate Stone               error_sp->Printf("error: unable to add selected command, didn't "
1482b9c1b51eSKate Stone                                "add python command.\n");
148344d93782SGreg Clayton               error_sp->Flush();
1484223383edSEnrico Granata             }
1485223383edSEnrico Granata           }
1486b9c1b51eSKate Stone         } else {
1487b9c1b51eSKate Stone           error_sp->Printf(
1488b9c1b51eSKate Stone               "error: unable to create function, didn't add python command.\n");
148944d93782SGreg Clayton           error_sp->Flush();
149044d93782SGreg Clayton         }
1491b9c1b51eSKate Stone       } else {
149244d93782SGreg Clayton         error_sp->Printf("error: empty function, didn't add python command.\n");
149344d93782SGreg Clayton         error_sp->Flush();
149444d93782SGreg Clayton       }
1495b9c1b51eSKate Stone     } else {
1496b9c1b51eSKate Stone       error_sp->Printf(
1497b9c1b51eSKate Stone           "error: script interpreter missing, didn't add python command.\n");
149844d93782SGreg Clayton       error_sp->Flush();
149944d93782SGreg Clayton     }
150044d93782SGreg Clayton 
150144d93782SGreg Clayton     io_handler.SetIsDone(true);
150244d93782SGreg Clayton   }
1503223383edSEnrico Granata 
1504b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
150557179860SJonas Devlieghere     if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) {
1506b9c1b51eSKate Stone       result.AppendError("only scripting language supported for scripted "
1507b9c1b51eSKate Stone                          "commands is currently Python");
150899f0b8f9SEnrico Granata       result.SetStatus(eReturnStatusFailed);
150999f0b8f9SEnrico Granata       return false;
151099f0b8f9SEnrico Granata     }
151199f0b8f9SEnrico Granata 
151211eb9c64SZachary Turner     if (command.GetArgumentCount() != 1) {
1513223383edSEnrico Granata       result.AppendError("'command script add' requires one argument");
1514223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1515223383edSEnrico Granata       return false;
1516223383edSEnrico Granata     }
1517223383edSEnrico Granata 
1518735152e3SEnrico Granata     // Store the options in case we get multi-line input
1519adcd0268SBenjamin Kramer     m_cmd_name = std::string(command[0].ref());
1520735152e3SEnrico Granata     m_short_help.assign(m_options.m_short_help);
152144d93782SGreg Clayton     m_synchronicity = m_options.m_synchronicity;
1522223383edSEnrico Granata 
1523b9c1b51eSKate Stone     if (m_options.m_class_name.empty()) {
1524b9c1b51eSKate Stone       if (m_options.m_funct_name.empty()) {
1525b9c1b51eSKate Stone         m_interpreter.GetPythonCommandsFromIOHandler(
1526b9c1b51eSKate Stone             "     ", // Prompt
1527a6faf851SJonas Devlieghere             *this);  // IOHandlerDelegate
1528b9c1b51eSKate Stone       } else {
1529b9c1b51eSKate Stone         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1530b9c1b51eSKate Stone             m_interpreter, m_cmd_name, m_options.m_funct_name,
1531b9c1b51eSKate Stone             m_options.m_short_help, m_synchronicity));
1532b9c1b51eSKate Stone         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1533223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1534b9c1b51eSKate Stone         } else {
1535223383edSEnrico Granata           result.AppendError("cannot add command");
1536223383edSEnrico Granata           result.SetStatus(eReturnStatusFailed);
1537223383edSEnrico Granata         }
1538223383edSEnrico Granata       }
1539b9c1b51eSKate Stone     } else {
15402b29b432SJonas Devlieghere       ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
1541b9c1b51eSKate Stone       if (!interpreter) {
15429fe00e52SEnrico Granata         result.AppendError("cannot find ScriptInterpreter");
15439fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
15449fe00e52SEnrico Granata         return false;
15459fe00e52SEnrico Granata       }
15469fe00e52SEnrico Granata 
1547b9c1b51eSKate Stone       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1548b9c1b51eSKate Stone           m_options.m_class_name.c_str());
1549b9c1b51eSKate Stone       if (!cmd_obj_sp) {
15509fe00e52SEnrico Granata         result.AppendError("cannot create helper object");
15519fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
15529fe00e52SEnrico Granata         return false;
15539fe00e52SEnrico Granata       }
15549fe00e52SEnrico Granata 
1555b9c1b51eSKate Stone       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1556b9c1b51eSKate Stone           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1557b9c1b51eSKate Stone       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
15589fe00e52SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1559b9c1b51eSKate Stone       } else {
15609fe00e52SEnrico Granata         result.AppendError("cannot add command");
15619fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
15629fe00e52SEnrico Granata       }
15639fe00e52SEnrico Granata     }
1564223383edSEnrico Granata 
1565223383edSEnrico Granata     return result.Succeeded();
1566223383edSEnrico Granata   }
15675a988416SJim Ingham 
15685a988416SJim Ingham   CommandOptions m_options;
156944d93782SGreg Clayton   std::string m_cmd_name;
1570735152e3SEnrico Granata   std::string m_short_help;
157144d93782SGreg Clayton   ScriptedCommandSynchronicity m_synchronicity;
1572223383edSEnrico Granata };
1573223383edSEnrico Granata 
1574223383edSEnrico Granata // CommandObjectCommandsScriptList
1575223383edSEnrico Granata 
1576b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed {
1577223383edSEnrico Granata public:
1578b9c1b51eSKate Stone   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1579b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script list",
1580b9c1b51eSKate Stone                             "List defined scripted commands.", nullptr) {}
1581223383edSEnrico Granata 
15826e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptList() override = default;
1583223383edSEnrico Granata 
1584b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1585d77ea5b2SRaphael Isemann     if (command.GetArgumentCount() != 0) {
1586d77ea5b2SRaphael Isemann       result.AppendError("'command script list' doesn't take any arguments");
1587d77ea5b2SRaphael Isemann       result.SetStatus(eReturnStatusFailed);
1588d77ea5b2SRaphael Isemann       return false;
1589d77ea5b2SRaphael Isemann     }
1590d77ea5b2SRaphael Isemann 
1591b9c1b51eSKate Stone     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1592223383edSEnrico Granata 
1593223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1594223383edSEnrico Granata 
1595223383edSEnrico Granata     return true;
1596223383edSEnrico Granata   }
1597223383edSEnrico Granata };
1598223383edSEnrico Granata 
1599223383edSEnrico Granata // CommandObjectCommandsScriptClear
1600223383edSEnrico Granata 
1601b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1602223383edSEnrico Granata public:
1603b9c1b51eSKate Stone   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1604b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script clear",
1605b9c1b51eSKate Stone                             "Delete all scripted commands.", nullptr) {}
1606223383edSEnrico Granata 
16076e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptClear() override = default;
1608223383edSEnrico Granata 
16095a988416SJim Ingham protected:
1610b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1611d77ea5b2SRaphael Isemann     if (command.GetArgumentCount() != 0) {
1612d77ea5b2SRaphael Isemann       result.AppendError("'command script clear' doesn't take any arguments");
1613d77ea5b2SRaphael Isemann       result.SetStatus(eReturnStatusFailed);
1614d77ea5b2SRaphael Isemann       return false;
1615d77ea5b2SRaphael Isemann     }
1616d77ea5b2SRaphael Isemann 
1617223383edSEnrico Granata     m_interpreter.RemoveAllUser();
1618223383edSEnrico Granata 
1619223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1620223383edSEnrico Granata 
1621223383edSEnrico Granata     return true;
1622223383edSEnrico Granata   }
1623223383edSEnrico Granata };
1624223383edSEnrico Granata 
1625223383edSEnrico Granata // CommandObjectCommandsScriptDelete
1626223383edSEnrico Granata 
1627b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1628223383edSEnrico Granata public:
1629b9c1b51eSKate Stone   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1630b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script delete",
1631b9c1b51eSKate Stone                             "Delete a scripted command.", nullptr) {
1632223383edSEnrico Granata     CommandArgumentEntry arg1;
1633223383edSEnrico Granata     CommandArgumentData cmd_arg;
1634223383edSEnrico Granata 
1635223383edSEnrico Granata     // Define the first (and only) variant of this arg.
1636223383edSEnrico Granata     cmd_arg.arg_type = eArgTypeCommandName;
1637223383edSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlain;
1638223383edSEnrico Granata 
1639b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1640b9c1b51eSKate Stone     // argument entry.
1641223383edSEnrico Granata     arg1.push_back(cmd_arg);
1642223383edSEnrico Granata 
1643223383edSEnrico Granata     // Push the data for the first argument into the m_arguments vector.
1644223383edSEnrico Granata     m_arguments.push_back(arg1);
1645223383edSEnrico Granata   }
1646223383edSEnrico Granata 
16476e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptDelete() override = default;
1648223383edSEnrico Granata 
16492e8f304fSGongyu Deng   void
16502e8f304fSGongyu Deng   HandleArgumentCompletion(CompletionRequest &request,
16512e8f304fSGongyu Deng                            OptionElementVector &opt_element_vector) override {
16522e8f304fSGongyu Deng     if (!m_interpreter.HasCommands() || request.GetCursorIndex() != 0)
16532e8f304fSGongyu Deng       return;
16542e8f304fSGongyu Deng 
16552ebe30c6SRaphael Isemann     for (const auto &c : m_interpreter.GetUserCommands())
16562ebe30c6SRaphael Isemann       request.TryCompleteCurrentArg(c.first, c.second->GetHelp());
16572e8f304fSGongyu Deng   }
16582e8f304fSGongyu Deng 
16595a988416SJim Ingham protected:
1660b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1661223383edSEnrico Granata 
166211eb9c64SZachary Turner     if (command.GetArgumentCount() != 1) {
1663223383edSEnrico Granata       result.AppendError("'command script delete' requires one argument");
1664223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1665223383edSEnrico Granata       return false;
1666223383edSEnrico Granata     }
1667223383edSEnrico Granata 
16680d9a201eSRaphael Isemann     auto cmd_name = command[0].ref();
1669223383edSEnrico Granata 
16704574a890SZachary Turner     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
16714574a890SZachary Turner         !m_interpreter.UserCommandExists(cmd_name)) {
1672867e7d17SZachary Turner       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1673223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
16744574a890SZachary Turner       return false;
1675223383edSEnrico Granata     }
1676223383edSEnrico Granata 
16774574a890SZachary Turner     m_interpreter.RemoveUser(cmd_name);
16784574a890SZachary Turner     result.SetStatus(eReturnStatusSuccessFinishResult);
16794574a890SZachary Turner     return true;
1680223383edSEnrico Granata   }
1681223383edSEnrico Granata };
1682223383edSEnrico Granata 
1683223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript
1684223383edSEnrico Granata 
1685223383edSEnrico Granata // CommandObjectMultiwordCommandsScript
1686223383edSEnrico Granata 
1687b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1688223383edSEnrico Granata public:
16897428a18cSKate Stone   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1690b9c1b51eSKate Stone       : CommandObjectMultiword(
1691a925974bSAdrian Prantl             interpreter, "command script",
1692a925974bSAdrian Prantl             "Commands for managing custom "
1693b9c1b51eSKate Stone             "commands implemented by "
1694b9c1b51eSKate Stone             "interpreter scripts.",
1695b9c1b51eSKate Stone             "command script <subcommand> [<subcommand-options>]") {
1696b9c1b51eSKate Stone     LoadSubCommand("add", CommandObjectSP(
1697b9c1b51eSKate Stone                               new CommandObjectCommandsScriptAdd(interpreter)));
1698b9c1b51eSKate Stone     LoadSubCommand(
1699b9c1b51eSKate Stone         "delete",
1700b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1701b9c1b51eSKate Stone     LoadSubCommand(
1702b9c1b51eSKate Stone         "clear",
1703b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1704b9c1b51eSKate Stone     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1705b9c1b51eSKate Stone                                interpreter)));
1706b9c1b51eSKate Stone     LoadSubCommand(
1707b9c1b51eSKate Stone         "import",
1708b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1709223383edSEnrico Granata   }
1710223383edSEnrico Granata 
17116e3d8e7fSEugene Zelenko   ~CommandObjectMultiwordCommandsScript() override = default;
1712223383edSEnrico Granata };
1713223383edSEnrico Granata 
1714ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
1715ebc09c36SJim Ingham 
1716ebc09c36SJim Ingham // CommandObjectMultiwordCommands
1717ebc09c36SJim Ingham 
1718b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1719b9c1b51eSKate Stone     CommandInterpreter &interpreter)
1720b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "command",
1721b9c1b51eSKate Stone                              "Commands for managing custom LLDB commands.",
1722b9c1b51eSKate Stone                              "command <subcommand> [<subcommand-options>]") {
1723b9c1b51eSKate Stone   LoadSubCommand("source",
1724b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1725b9c1b51eSKate Stone   LoadSubCommand("alias",
1726b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1727b9c1b51eSKate Stone   LoadSubCommand("unalias", CommandObjectSP(
1728b9c1b51eSKate Stone                                 new CommandObjectCommandsUnalias(interpreter)));
1729b9c1b51eSKate Stone   LoadSubCommand("delete",
1730b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1731b9c1b51eSKate Stone   LoadSubCommand(
1732b9c1b51eSKate Stone       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1733b9c1b51eSKate Stone   LoadSubCommand(
1734b9c1b51eSKate Stone       "script",
1735b9c1b51eSKate Stone       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1736ebc09c36SJim Ingham }
1737ebc09c36SJim Ingham 
17386e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1739