1ebc09c36SJim Ingham //===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===//
2ebc09c36SJim Ingham //
3ebc09c36SJim Ingham //                     The LLVM Compiler Infrastructure
4ebc09c36SJim Ingham //
5ebc09c36SJim Ingham // This file is distributed under the University of Illinois Open Source
6ebc09c36SJim Ingham // License. See LICENSE.TXT for details.
7ebc09c36SJim Ingham //
8ebc09c36SJim Ingham //===----------------------------------------------------------------------===//
9ebc09c36SJim Ingham 
10ebc09c36SJim Ingham // C Includes
11ebc09c36SJim Ingham // C++ Includes
12ebc09c36SJim Ingham // Other libraries and framework includes
130e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h"
140e5e5a79SGreg Clayton 
15ebc09c36SJim Ingham // Project includes
166e3d8e7fSEugene Zelenko #include "CommandObjectCommands.h"
1746d4aa21SEnrico Granata #include "CommandObjectHelp.h"
18ebc09c36SJim Ingham #include "lldb/Core/Debugger.h"
1944d93782SGreg Clayton #include "lldb/Core/IOHandler.h"
20be93a35aSEnrico Granata #include "lldb/Core/StringList.h"
21de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h"
227594f14fSEnrico Granata #include "lldb/Interpreter/CommandHistory.h"
23ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
24de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h"
25ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h"
26012d4fcaSEnrico Granata #include "lldb/Interpreter/OptionValueBoolean.h"
2745d0e238SEnrico Granata #include "lldb/Interpreter/OptionValueString.h"
287594f14fSEnrico Granata #include "lldb/Interpreter/OptionValueUInt64.h"
29ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h"
3099f0b8f9SEnrico Granata #include "lldb/Interpreter/ScriptInterpreter.h"
31ebc09c36SJim Ingham 
32ebc09c36SJim Ingham using namespace lldb;
33ebc09c36SJim Ingham using namespace lldb_private;
34ebc09c36SJim Ingham 
35ebc09c36SJim Ingham //-------------------------------------------------------------------------
36ebc09c36SJim Ingham // CommandObjectCommandsSource
37ebc09c36SJim Ingham //-------------------------------------------------------------------------
38ebc09c36SJim Ingham 
39*b9c1b51eSKate Stone class CommandObjectCommandsHistory : public CommandObjectParsed {
405a988416SJim Ingham public:
41*b9c1b51eSKate Stone   CommandObjectCommandsHistory(CommandInterpreter &interpreter)
42*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command history",
435a988416SJim Ingham                             "Dump the history of commands in this session.",
446e3d8e7fSEugene Zelenko                             nullptr),
45*b9c1b51eSKate Stone         m_options() {}
465a988416SJim Ingham 
476e3d8e7fSEugene Zelenko   ~CommandObjectCommandsHistory() override = default;
485a988416SJim Ingham 
49*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
505a988416SJim Ingham 
515a988416SJim Ingham protected:
52*b9c1b51eSKate Stone   class CommandOptions : public Options {
53a5a97ebeSJim Ingham   public:
54*b9c1b51eSKate Stone     CommandOptions()
55*b9c1b51eSKate Stone         : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
56a5a97ebeSJim Ingham     }
57a5a97ebeSJim Ingham 
586e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
59a5a97ebeSJim Ingham 
60*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
61*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
62a5a97ebeSJim Ingham       Error error;
633bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
64a5a97ebeSJim Ingham 
65*b9c1b51eSKate Stone       switch (short_option) {
66a5a97ebeSJim Ingham       case 'c':
67c95f7e2aSPavel Labath         error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
68a5a97ebeSJim Ingham         break;
69a5a97ebeSJim Ingham       case 's':
70*b9c1b51eSKate Stone         if (option_arg && strcmp("end", option_arg) == 0) {
717594f14fSEnrico Granata           m_start_idx.SetCurrentValue(UINT64_MAX);
727594f14fSEnrico Granata           m_start_idx.SetOptionWasSet();
73*b9c1b51eSKate Stone         } else
74*b9c1b51eSKate Stone           error = m_start_idx.SetValueFromString(option_arg,
75*b9c1b51eSKate Stone                                                  eVarSetOperationAssign);
767594f14fSEnrico Granata         break;
777594f14fSEnrico Granata       case 'e':
78*b9c1b51eSKate Stone         error =
79*b9c1b51eSKate Stone             m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
807594f14fSEnrico Granata         break;
8163123b64SEnrico Granata       case 'C':
8263123b64SEnrico Granata         m_clear.SetCurrentValue(true);
8363123b64SEnrico Granata         m_clear.SetOptionWasSet();
84a5a97ebeSJim Ingham         break;
85a5a97ebeSJim Ingham       default:
86*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
87*b9c1b51eSKate Stone                                        short_option);
88a5a97ebeSJim Ingham         break;
89a5a97ebeSJim Ingham       }
90a5a97ebeSJim Ingham 
91a5a97ebeSJim Ingham       return error;
92a5a97ebeSJim Ingham     }
93a5a97ebeSJim Ingham 
94*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
957594f14fSEnrico Granata       m_start_idx.Clear();
967594f14fSEnrico Granata       m_stop_idx.Clear();
977594f14fSEnrico Granata       m_count.Clear();
9863123b64SEnrico Granata       m_clear.Clear();
99a5a97ebeSJim Ingham     }
100a5a97ebeSJim Ingham 
101*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
102a5a97ebeSJim Ingham 
103a5a97ebeSJim Ingham     // Options table: Required for subclasses of Options.
104a5a97ebeSJim Ingham 
105a5a97ebeSJim Ingham     static OptionDefinition g_option_table[];
106a5a97ebeSJim Ingham 
107a5a97ebeSJim Ingham     // Instance variables to hold the values for command options.
108a5a97ebeSJim Ingham 
1097594f14fSEnrico Granata     OptionValueUInt64 m_start_idx;
1107594f14fSEnrico Granata     OptionValueUInt64 m_stop_idx;
1117594f14fSEnrico Granata     OptionValueUInt64 m_count;
11263123b64SEnrico Granata     OptionValueBoolean m_clear;
113a5a97ebeSJim Ingham   };
114a5a97ebeSJim Ingham 
115*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
116*b9c1b51eSKate Stone     if (m_options.m_clear.GetCurrentValue() &&
117*b9c1b51eSKate Stone         m_options.m_clear.OptionWasSet()) {
1187594f14fSEnrico Granata       m_interpreter.GetCommandHistory().Clear();
1197594f14fSEnrico Granata       result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
120*b9c1b51eSKate Stone     } else {
121*b9c1b51eSKate Stone       if (m_options.m_start_idx.OptionWasSet() &&
122*b9c1b51eSKate Stone           m_options.m_stop_idx.OptionWasSet() &&
123*b9c1b51eSKate Stone           m_options.m_count.OptionWasSet()) {
124*b9c1b51eSKate Stone         result.AppendError("--count, --start-index and --end-index cannot be "
125*b9c1b51eSKate Stone                            "all specified in the same invocation");
1267594f14fSEnrico Granata         result.SetStatus(lldb::eReturnStatusFailed);
127*b9c1b51eSKate Stone       } else {
128*b9c1b51eSKate Stone         std::pair<bool, uint64_t> start_idx(
129*b9c1b51eSKate Stone             m_options.m_start_idx.OptionWasSet(),
130*b9c1b51eSKate Stone             m_options.m_start_idx.GetCurrentValue());
131*b9c1b51eSKate Stone         std::pair<bool, uint64_t> stop_idx(
132*b9c1b51eSKate Stone             m_options.m_stop_idx.OptionWasSet(),
133*b9c1b51eSKate Stone             m_options.m_stop_idx.GetCurrentValue());
134*b9c1b51eSKate Stone         std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
135*b9c1b51eSKate Stone                                         m_options.m_count.GetCurrentValue());
136a5a97ebeSJim Ingham 
1377594f14fSEnrico Granata         const CommandHistory &history(m_interpreter.GetCommandHistory());
1387594f14fSEnrico Granata 
139*b9c1b51eSKate Stone         if (start_idx.first && start_idx.second == UINT64_MAX) {
140*b9c1b51eSKate Stone           if (count.first) {
1417594f14fSEnrico Granata             start_idx.second = history.GetSize() - count.second;
1427594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
143*b9c1b51eSKate Stone           } else if (stop_idx.first) {
1447594f14fSEnrico Granata             start_idx.second = stop_idx.second;
1457594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
146*b9c1b51eSKate Stone           } else {
1477594f14fSEnrico Granata             start_idx.second = 0;
1487594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
1497594f14fSEnrico Granata           }
150*b9c1b51eSKate Stone         } else {
151*b9c1b51eSKate Stone           if (!start_idx.first && !stop_idx.first && !count.first) {
1527594f14fSEnrico Granata             start_idx.second = 0;
1537594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
154*b9c1b51eSKate Stone           } else if (start_idx.first) {
155*b9c1b51eSKate Stone             if (count.first) {
1567594f14fSEnrico Granata               stop_idx.second = start_idx.second + count.second - 1;
157*b9c1b51eSKate Stone             } else if (!stop_idx.first) {
1587594f14fSEnrico Granata               stop_idx.second = history.GetSize() - 1;
1597594f14fSEnrico Granata             }
160*b9c1b51eSKate Stone           } else if (stop_idx.first) {
161*b9c1b51eSKate Stone             if (count.first) {
1627594f14fSEnrico Granata               if (stop_idx.second >= count.second)
1637594f14fSEnrico Granata                 start_idx.second = stop_idx.second - count.second + 1;
1647594f14fSEnrico Granata               else
1657594f14fSEnrico Granata                 start_idx.second = 0;
1667594f14fSEnrico Granata             }
167*b9c1b51eSKate Stone           } else /* if (count.first) */
1687594f14fSEnrico Granata           {
1697594f14fSEnrico Granata             start_idx.second = 0;
1707594f14fSEnrico Granata             stop_idx.second = count.second - 1;
1717594f14fSEnrico Granata           }
1727594f14fSEnrico Granata         }
173*b9c1b51eSKate Stone         history.Dump(result.GetOutputStream(), start_idx.second,
174*b9c1b51eSKate Stone                      stop_idx.second);
1757594f14fSEnrico Granata       }
1767594f14fSEnrico Granata     }
177a5a97ebeSJim Ingham     return result.Succeeded();
178a5a97ebeSJim Ingham   }
1795a988416SJim Ingham 
1805a988416SJim Ingham   CommandOptions m_options;
181a5a97ebeSJim Ingham };
182a5a97ebeSJim Ingham 
183a5a97ebeSJim Ingham OptionDefinition
184*b9c1b51eSKate Stone     CommandObjectCommandsHistory::CommandOptions::g_option_table[] = {
185ac9c3a62SKate Stone         // clang-format off
1866e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1, false, "count",       'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
1876e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)."},
1886e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1, false, "end-index",   'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
1896e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_2, false, "clear",       'C', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeBoolean,         "Clears the current command history."},
1906e3d8e7fSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
191ac9c3a62SKate Stone         // clang-format on
192a5a97ebeSJim Ingham };
193a5a97ebeSJim Ingham 
194a5a97ebeSJim Ingham //-------------------------------------------------------------------------
195a5a97ebeSJim Ingham // CommandObjectCommandsSource
196a5a97ebeSJim Ingham //-------------------------------------------------------------------------
197a5a97ebeSJim Ingham 
198*b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed {
1995a988416SJim Ingham public:
2007428a18cSKate Stone   CommandObjectCommandsSource(CommandInterpreter &interpreter)
201*b9c1b51eSKate Stone       : CommandObjectParsed(
202*b9c1b51eSKate Stone             interpreter, "command source",
203*b9c1b51eSKate Stone             "Read and execute LLDB commands from the file <filename>.",
2046e3d8e7fSEugene Zelenko             nullptr),
205*b9c1b51eSKate Stone         m_options() {
2065a988416SJim Ingham     CommandArgumentEntry arg;
2075a988416SJim Ingham     CommandArgumentData file_arg;
2085a988416SJim Ingham 
2095a988416SJim Ingham     // Define the first (and only) variant of this arg.
2105a988416SJim Ingham     file_arg.arg_type = eArgTypeFilename;
2115a988416SJim Ingham     file_arg.arg_repetition = eArgRepeatPlain;
2125a988416SJim Ingham 
213*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
214*b9c1b51eSKate Stone     // argument entry.
2155a988416SJim Ingham     arg.push_back(file_arg);
2165a988416SJim Ingham 
2175a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
2185a988416SJim Ingham     m_arguments.push_back(arg);
2195a988416SJim Ingham   }
2205a988416SJim Ingham 
2216e3d8e7fSEugene Zelenko   ~CommandObjectCommandsSource() override = default;
2225a988416SJim Ingham 
223*b9c1b51eSKate Stone   const char *GetRepeatCommand(Args &current_command_args,
224*b9c1b51eSKate Stone                                uint32_t index) override {
2255a988416SJim Ingham     return "";
2265a988416SJim Ingham   }
2275a988416SJim Ingham 
228*b9c1b51eSKate Stone   int HandleArgumentCompletion(Args &input, int &cursor_index,
2295a988416SJim Ingham                                int &cursor_char_position,
2305a988416SJim Ingham                                OptionElementVector &opt_element_vector,
231*b9c1b51eSKate Stone                                int match_start_point, int max_return_elements,
2325a988416SJim Ingham                                bool &word_complete,
233*b9c1b51eSKate Stone                                StringList &matches) override {
2345a988416SJim Ingham     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
2355a988416SJim Ingham     completion_str.erase(cursor_char_position);
2365a988416SJim Ingham 
237*b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
238*b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
239*b9c1b51eSKate Stone         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
240*b9c1b51eSKate Stone         word_complete, matches);
2415a988416SJim Ingham     return matches.GetSize();
2425a988416SJim Ingham   }
2435a988416SJim Ingham 
244*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
2455a988416SJim Ingham 
2465a988416SJim Ingham protected:
247*b9c1b51eSKate Stone   class CommandOptions : public Options {
248e16c50a1SJim Ingham   public:
249*b9c1b51eSKate Stone     CommandOptions()
250*b9c1b51eSKate Stone         : Options(), m_stop_on_error(true), m_silent_run(false),
251*b9c1b51eSKate Stone           m_stop_on_continue(true) {}
252e16c50a1SJim Ingham 
2536e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
254e16c50a1SJim Ingham 
255*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
256*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
257e16c50a1SJim Ingham       Error error;
2583bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
259e16c50a1SJim Ingham 
260*b9c1b51eSKate Stone       switch (short_option) {
261e16c50a1SJim Ingham       case 'e':
262c95f7e2aSPavel Labath         error = m_stop_on_error.SetValueFromString(option_arg);
263e16c50a1SJim Ingham         break;
264340b0309SGreg Clayton 
265e16c50a1SJim Ingham       case 'c':
266c95f7e2aSPavel Labath         error = m_stop_on_continue.SetValueFromString(option_arg);
267e16c50a1SJim Ingham         break;
268340b0309SGreg Clayton 
26960986174SMichael Sartain       case 's':
270c95f7e2aSPavel Labath         error = m_silent_run.SetValueFromString(option_arg);
27160986174SMichael Sartain         break;
272340b0309SGreg Clayton 
273e16c50a1SJim Ingham       default:
274*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
275*b9c1b51eSKate Stone                                        short_option);
276e16c50a1SJim Ingham         break;
277e16c50a1SJim Ingham       }
278e16c50a1SJim Ingham 
279e16c50a1SJim Ingham       return error;
280e16c50a1SJim Ingham     }
281e16c50a1SJim Ingham 
282*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
283012d4fcaSEnrico Granata       m_stop_on_error.Clear();
284340b0309SGreg Clayton       m_silent_run.Clear();
285340b0309SGreg Clayton       m_stop_on_continue.Clear();
286e16c50a1SJim Ingham     }
287e16c50a1SJim Ingham 
288*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
289e16c50a1SJim Ingham 
290e16c50a1SJim Ingham     // Options table: Required for subclasses of Options.
291e16c50a1SJim Ingham 
292e0d378b3SGreg Clayton     static OptionDefinition g_option_table[];
293e16c50a1SJim Ingham 
294e16c50a1SJim Ingham     // Instance variables to hold the values for command options.
295e16c50a1SJim Ingham 
296012d4fcaSEnrico Granata     OptionValueBoolean m_stop_on_error;
297340b0309SGreg Clayton     OptionValueBoolean m_silent_run;
298340b0309SGreg Clayton     OptionValueBoolean m_stop_on_continue;
299e16c50a1SJim Ingham   };
300e16c50a1SJim Ingham 
301*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
302c7bece56SGreg Clayton     const size_t argc = command.GetArgumentCount();
303*b9c1b51eSKate Stone     if (argc == 1) {
3045a988416SJim Ingham       const char *filename = command.GetArgumentAtIndex(0);
305ebc09c36SJim Ingham 
3061ee3853fSJohnny Chen       FileSpec cmd_file(filename, true);
3076e3d8e7fSEugene Zelenko       ExecutionContext *exe_ctx = nullptr; // Just use the default context.
308ebc09c36SJim Ingham 
309340b0309SGreg Clayton       // If any options were set, then use them
310340b0309SGreg Clayton       if (m_options.m_stop_on_error.OptionWasSet() ||
311340b0309SGreg Clayton           m_options.m_silent_run.OptionWasSet() ||
312*b9c1b51eSKate Stone           m_options.m_stop_on_continue.OptionWasSet()) {
313340b0309SGreg Clayton         // Use user set settings
31426c7bf93SJim Ingham         CommandInterpreterRunOptions options;
315*b9c1b51eSKate Stone         options.SetStopOnContinue(
316*b9c1b51eSKate Stone             m_options.m_stop_on_continue.GetCurrentValue());
31726c7bf93SJim Ingham         options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
3187d8555c4SJim Ingham         options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
3197d8555c4SJim Ingham         options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
32026c7bf93SJim Ingham 
321*b9c1b51eSKate Stone         m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
322e16c50a1SJim Ingham                                              result);
323*b9c1b51eSKate Stone       } else {
324*b9c1b51eSKate Stone         // No options were set, inherit any settings from nested "command
325*b9c1b51eSKate Stone         // source" commands,
326340b0309SGreg Clayton         // or set to sane default settings...
32726c7bf93SJim Ingham         CommandInterpreterRunOptions options;
328*b9c1b51eSKate Stone         m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
329340b0309SGreg Clayton                                              result);
330340b0309SGreg Clayton       }
331*b9c1b51eSKate Stone     } else {
332*b9c1b51eSKate Stone       result.AppendErrorWithFormat(
333*b9c1b51eSKate Stone           "'%s' takes exactly one executable filename argument.\n",
334*b9c1b51eSKate Stone           GetCommandName());
335ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
336ebc09c36SJim Ingham     }
337ebc09c36SJim Ingham     return result.Succeeded();
338ebc09c36SJim Ingham   }
3396e3d8e7fSEugene Zelenko 
3405a988416SJim Ingham   CommandOptions m_options;
341ebc09c36SJim Ingham };
342ebc09c36SJim Ingham 
343*b9c1b51eSKate Stone OptionDefinition CommandObjectCommandsSource::CommandOptions::g_option_table[] =
344e16c50a1SJim Ingham     {
345ac9c3a62SKate Stone         // clang-format off
3466e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "stop-on-error",    'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
3476e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
3486e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "silent-run",       's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
3496e3d8e7fSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
350ac9c3a62SKate Stone         // clang-format on
351e16c50a1SJim Ingham };
352e16c50a1SJim Ingham 
353ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
354ebc09c36SJim Ingham //-------------------------------------------------------------------------
355ebc09c36SJim Ingham // CommandObjectCommandsAlias
356ebc09c36SJim Ingham //-------------------------------------------------------------------------
357ebc09c36SJim Ingham 
358*b9c1b51eSKate Stone static const char *g_python_command_instructions =
359*b9c1b51eSKate Stone     "Enter your Python command(s). Type 'DONE' to end.\n"
360be93a35aSEnrico Granata     "You must define a Python function with this signature:\n"
36144d93782SGreg Clayton     "def my_command_impl(debugger, args, result, internal_dict):\n";
362be93a35aSEnrico Granata 
363*b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw {
36445d0e238SEnrico Granata protected:
365*b9c1b51eSKate Stone   class CommandOptions : public OptionGroup {
366ebc09c36SJim Ingham   public:
367*b9c1b51eSKate Stone     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
36845d0e238SEnrico Granata 
36945d0e238SEnrico Granata     ~CommandOptions() override = default;
37045d0e238SEnrico Granata 
371*b9c1b51eSKate Stone     uint32_t GetNumDefinitions() override { return 3; }
37245d0e238SEnrico Granata 
373*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
37445d0e238SEnrico Granata 
375*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_value,
376*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
37745d0e238SEnrico Granata       Error error;
37845d0e238SEnrico Granata 
37945d0e238SEnrico Granata       const int short_option = g_option_table[option_idx].short_option;
38045d0e238SEnrico Granata 
381*b9c1b51eSKate Stone       switch (short_option) {
38245d0e238SEnrico Granata       case 'h':
38345d0e238SEnrico Granata         m_help.SetCurrentValue(option_value);
38445d0e238SEnrico Granata         m_help.SetOptionWasSet();
38545d0e238SEnrico Granata         break;
38645d0e238SEnrico Granata 
38745d0e238SEnrico Granata       case 'H':
38845d0e238SEnrico Granata         m_long_help.SetCurrentValue(option_value);
38945d0e238SEnrico Granata         m_long_help.SetOptionWasSet();
39045d0e238SEnrico Granata         break;
39145d0e238SEnrico Granata 
39245d0e238SEnrico Granata       default:
393*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("invalid short option character '%c'",
394*b9c1b51eSKate Stone                                        short_option);
39545d0e238SEnrico Granata         break;
39645d0e238SEnrico Granata       }
39745d0e238SEnrico Granata 
39845d0e238SEnrico Granata       return error;
39945d0e238SEnrico Granata     }
40045d0e238SEnrico Granata 
401*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
40245d0e238SEnrico Granata       m_help.Clear();
40345d0e238SEnrico Granata       m_long_help.Clear();
40445d0e238SEnrico Granata     }
40545d0e238SEnrico Granata 
40645d0e238SEnrico Granata     // Options table: Required for subclasses of Options.
40745d0e238SEnrico Granata 
40845d0e238SEnrico Granata     static OptionDefinition g_option_table[];
40945d0e238SEnrico Granata     OptionValueString m_help;
41045d0e238SEnrico Granata     OptionValueString m_long_help;
41145d0e238SEnrico Granata   };
41245d0e238SEnrico Granata 
41345d0e238SEnrico Granata   OptionGroupOptions m_option_group;
41445d0e238SEnrico Granata   CommandOptions m_command_options;
41545d0e238SEnrico Granata 
41645d0e238SEnrico Granata public:
417*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
41845d0e238SEnrico Granata 
4197428a18cSKate Stone   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
420*b9c1b51eSKate Stone       : CommandObjectRaw(
421*b9c1b51eSKate Stone             interpreter, "command alias",
422*b9c1b51eSKate Stone             "Define a custom command in terms of an existing command.",
42345d0e238SEnrico Granata             nullptr),
424*b9c1b51eSKate Stone         m_option_group(), m_command_options() {
42545d0e238SEnrico Granata     m_option_group.Append(&m_command_options);
42645d0e238SEnrico Granata     m_option_group.Finalize();
42745d0e238SEnrico Granata 
428ebc09c36SJim Ingham     SetHelpLong(
429ea671fbdSKate Stone         "'alias' allows the user to create a short-cut or abbreviation for long \
430ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options.  \
431*b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:"
432*b9c1b51eSKate Stone         R"(
433ea671fbdSKate Stone 
434ea671fbdSKate Stone (lldb) command alias sc script
435ea671fbdSKate Stone 
436ea671fbdSKate Stone     Creates the abbreviation 'sc' for the 'script' command.
437ea671fbdSKate Stone 
438ea671fbdSKate Stone (lldb) command alias bp breakpoint
439ea671fbdSKate Stone 
440*b9c1b51eSKate Stone )"
441*b9c1b51eSKate Stone         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
442ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \
443*b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
444*b9c1b51eSKate Stone         R"(
445ea671fbdSKate Stone 
446ea671fbdSKate Stone (lldb) command alias bpl breakpoint list
447ea671fbdSKate Stone 
448ea671fbdSKate Stone     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
449ea671fbdSKate Stone 
450*b9c1b51eSKate Stone )"
451*b9c1b51eSKate Stone         "An alias can include some options for the command, with the values either \
452ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \
453ea671fbdSKate Stone arguments, to be filled in when the alias is invoked.  The following example \
454*b9c1b51eSKate Stone shows how to create aliases with options:"
455*b9c1b51eSKate Stone         R"(
456ea671fbdSKate Stone 
457ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
458ea671fbdSKate Stone 
459*b9c1b51eSKate Stone )"
460*b9c1b51eSKate Stone         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
461ea671fbdSKate Stone options already part of the alias.  So if the user wants to set a breakpoint \
462ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \
463ea671fbdSKate Stone user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
464ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used.  \
465ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \
466ea671fbdSKate Stone occupies when the alias is used.  All the occurrences of '%1' in the alias \
467ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \
468ea671fbdSKate Stone alias will be replaced with the second argument, and so on.  This also allows \
469ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \
470*b9c1b51eSKate Stone launch' example below)."
471*b9c1b51eSKate Stone         R"(
472ea671fbdSKate Stone 
473*b9c1b51eSKate Stone )"
474*b9c1b51eSKate Stone         "Note: the positional arguments must substitute as whole words in the resultant \
475ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \
476*b9c1b51eSKate Stone \".cpp\":"
477*b9c1b51eSKate Stone         R"(
478ea671fbdSKate Stone 
479ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
480ea671fbdSKate Stone 
481*b9c1b51eSKate Stone )"
482*b9c1b51eSKate Stone         "For more complex aliasing, use the \"command regex\" command instead.  In the \
483ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \
484ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \
485*b9c1b51eSKate Stone argument.  The user would use this alias as follows:"
486*b9c1b51eSKate Stone         R"(
487ea671fbdSKate Stone 
488ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
489ea671fbdSKate Stone (lldb) bfl my-file.c 137
490ea671fbdSKate Stone 
491ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
492ea671fbdSKate Stone 
493ea671fbdSKate Stone Another example:
494ea671fbdSKate Stone 
495ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1
496ea671fbdSKate Stone (lldb) pltty /dev/tty0
497ea671fbdSKate Stone 
498ea671fbdSKate Stone     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
499ea671fbdSKate Stone 
500*b9c1b51eSKate Stone )"
501*b9c1b51eSKate Stone         "If the user always wanted to pass the same value to a particular option, the \
502ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \
503*b9c1b51eSKate Stone rather than using a positional placeholder:"
504*b9c1b51eSKate Stone         R"(
505ea671fbdSKate Stone 
506ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3
507ea671fbdSKate Stone 
508*b9c1b51eSKate Stone     Always sets a breakpoint on line 3 of whatever file is indicated.)");
509ebc09c36SJim Ingham 
510405fe67fSCaroline Tice     CommandArgumentEntry arg1;
511405fe67fSCaroline Tice     CommandArgumentEntry arg2;
512405fe67fSCaroline Tice     CommandArgumentEntry arg3;
513405fe67fSCaroline Tice     CommandArgumentData alias_arg;
514405fe67fSCaroline Tice     CommandArgumentData cmd_arg;
515405fe67fSCaroline Tice     CommandArgumentData options_arg;
516405fe67fSCaroline Tice 
517405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
518405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
519405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
520405fe67fSCaroline Tice 
521*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
522*b9c1b51eSKate Stone     // argument entry.
523405fe67fSCaroline Tice     arg1.push_back(alias_arg);
524405fe67fSCaroline Tice 
525405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
526405fe67fSCaroline Tice     cmd_arg.arg_type = eArgTypeCommandName;
527405fe67fSCaroline Tice     cmd_arg.arg_repetition = eArgRepeatPlain;
528405fe67fSCaroline Tice 
529*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
530*b9c1b51eSKate Stone     // argument entry.
531405fe67fSCaroline Tice     arg2.push_back(cmd_arg);
532405fe67fSCaroline Tice 
533405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
534405fe67fSCaroline Tice     options_arg.arg_type = eArgTypeAliasOptions;
535405fe67fSCaroline Tice     options_arg.arg_repetition = eArgRepeatOptional;
536405fe67fSCaroline Tice 
537*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
538*b9c1b51eSKate Stone     // argument entry.
539405fe67fSCaroline Tice     arg3.push_back(options_arg);
540405fe67fSCaroline Tice 
541405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
542405fe67fSCaroline Tice     m_arguments.push_back(arg1);
543405fe67fSCaroline Tice     m_arguments.push_back(arg2);
544405fe67fSCaroline Tice     m_arguments.push_back(arg3);
545ebc09c36SJim Ingham   }
546ebc09c36SJim Ingham 
5476e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAlias() override = default;
548ebc09c36SJim Ingham 
5495a988416SJim Ingham protected:
550*b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
551*b9c1b51eSKate Stone                  CommandReturnObject &result) override {
552*b9c1b51eSKate Stone     if (!raw_command_line || !raw_command_line[0]) {
553d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
55445d0e238SEnrico Granata       return false;
55545d0e238SEnrico Granata     }
55645d0e238SEnrico Granata 
557e1cfbc79STodd Fiala     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
558e1cfbc79STodd Fiala     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
55945d0e238SEnrico Granata 
56045d0e238SEnrico Granata     const char *remainder = nullptr;
56145d0e238SEnrico Granata 
562*b9c1b51eSKate Stone     if (raw_command_line[0] == '-') {
56345d0e238SEnrico Granata       // We have some options and these options MUST end with --.
56445d0e238SEnrico Granata       const char *end_options = nullptr;
56545d0e238SEnrico Granata       const char *s = raw_command_line;
566*b9c1b51eSKate Stone       while (s && s[0]) {
56745d0e238SEnrico Granata         end_options = ::strstr(s, "--");
568*b9c1b51eSKate Stone         if (end_options) {
56945d0e238SEnrico Granata           end_options += 2; // Get past the "--"
570*b9c1b51eSKate Stone           if (::isspace(end_options[0])) {
57145d0e238SEnrico Granata             remainder = end_options;
57245d0e238SEnrico Granata             while (::isspace(*remainder))
57345d0e238SEnrico Granata               ++remainder;
57445d0e238SEnrico Granata             break;
57545d0e238SEnrico Granata           }
57645d0e238SEnrico Granata         }
57745d0e238SEnrico Granata         s = end_options;
57845d0e238SEnrico Granata       }
57945d0e238SEnrico Granata 
580*b9c1b51eSKate Stone       if (end_options) {
581*b9c1b51eSKate Stone         Args args(
582*b9c1b51eSKate Stone             llvm::StringRef(raw_command_line, end_options - raw_command_line));
58345d0e238SEnrico Granata         if (!ParseOptions(args, result))
58445d0e238SEnrico Granata           return false;
58545d0e238SEnrico Granata 
586e1cfbc79STodd Fiala         Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
587*b9c1b51eSKate Stone         if (error.Fail()) {
58845d0e238SEnrico Granata           result.AppendError(error.AsCString());
58945d0e238SEnrico Granata           result.SetStatus(eReturnStatusFailed);
59045d0e238SEnrico Granata           return false;
59145d0e238SEnrico Granata         }
59245d0e238SEnrico Granata       }
59345d0e238SEnrico Granata     }
59445d0e238SEnrico Granata     if (nullptr == remainder)
59545d0e238SEnrico Granata       remainder = raw_command_line;
59645d0e238SEnrico Granata 
59745d0e238SEnrico Granata     std::string raw_command_string(remainder);
59845d0e238SEnrico Granata     Args args(raw_command_string.c_str());
599844d2303SCaroline Tice 
600844d2303SCaroline Tice     size_t argc = args.GetArgumentCount();
601844d2303SCaroline Tice 
602*b9c1b51eSKate Stone     if (argc < 2) {
603d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
604844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
605844d2303SCaroline Tice       return false;
606844d2303SCaroline Tice     }
607844d2303SCaroline Tice 
608844d2303SCaroline Tice     // Get the alias command.
609844d2303SCaroline Tice 
610844d2303SCaroline Tice     const std::string alias_command = args.GetArgumentAtIndex(0);
611*b9c1b51eSKate Stone     if (alias_command.size() > 1 && alias_command[0] == '-') {
612d72e412fSEnrico Granata       result.AppendError("aliases starting with a dash are not supported");
613*b9c1b51eSKate Stone       if (alias_command == "--help" || alias_command == "--long-help") {
614*b9c1b51eSKate Stone         result.AppendWarning("if trying to pass options to 'command alias' add "
615*b9c1b51eSKate Stone                              "a -- at the end of the options");
616d72e412fSEnrico Granata       }
617d72e412fSEnrico Granata       result.SetStatus(eReturnStatusFailed);
618d72e412fSEnrico Granata       return false;
619d72e412fSEnrico Granata     }
620844d2303SCaroline Tice 
621*b9c1b51eSKate Stone     // Strip the new alias name off 'raw_command_string'  (leave it on args,
622*b9c1b51eSKate Stone     // which gets passed to 'Execute', which
623844d2303SCaroline Tice     // does the stripping itself.
624844d2303SCaroline Tice     size_t pos = raw_command_string.find(alias_command);
625*b9c1b51eSKate Stone     if (pos == 0) {
626844d2303SCaroline Tice       raw_command_string = raw_command_string.substr(alias_command.size());
627844d2303SCaroline Tice       pos = raw_command_string.find_first_not_of(' ');
628844d2303SCaroline Tice       if ((pos != std::string::npos) && (pos > 0))
629844d2303SCaroline Tice         raw_command_string = raw_command_string.substr(pos);
630*b9c1b51eSKate Stone     } else {
631844d2303SCaroline Tice       result.AppendError("Error parsing command string.  No alias created.");
632844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
633844d2303SCaroline Tice       return false;
634844d2303SCaroline Tice     }
635844d2303SCaroline Tice 
636844d2303SCaroline Tice     // Verify that the command is alias-able.
637*b9c1b51eSKate Stone     if (m_interpreter.CommandExists(alias_command.c_str())) {
638*b9c1b51eSKate Stone       result.AppendErrorWithFormat(
639*b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
640844d2303SCaroline Tice           alias_command.c_str());
641844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
642844d2303SCaroline Tice       return false;
643844d2303SCaroline Tice     }
644844d2303SCaroline Tice 
645*b9c1b51eSKate Stone     // Get CommandObject that is being aliased. The command name is read from
646*b9c1b51eSKate Stone     // the front of raw_command_string.
647*b9c1b51eSKate Stone     // raw_command_string is returned with the name of the command object
648*b9c1b51eSKate Stone     // stripped off the front.
649d72e412fSEnrico Granata     std::string original_raw_command_string(raw_command_string);
650*b9c1b51eSKate Stone     CommandObject *cmd_obj =
651*b9c1b51eSKate Stone         m_interpreter.GetCommandObjectForCommand(raw_command_string);
652844d2303SCaroline Tice 
653*b9c1b51eSKate Stone     if (!cmd_obj) {
654*b9c1b51eSKate Stone       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
655*b9c1b51eSKate Stone                                    "'%s' does not begin with a valid command."
656*b9c1b51eSKate Stone                                    "  No alias created.",
657*b9c1b51eSKate Stone                                    original_raw_command_string.c_str());
658844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
659844d2303SCaroline Tice       return false;
660*b9c1b51eSKate Stone     } else if (!cmd_obj->WantsRawCommandString()) {
661*b9c1b51eSKate Stone       // Note that args was initialized with the original command, and has not
662*b9c1b51eSKate Stone       // been updated to this point.
663*b9c1b51eSKate Stone       // Therefore can we pass it to the version of Execute that does not
664*b9c1b51eSKate Stone       // need/expect raw input in the alias.
6655a988416SJim Ingham       return HandleAliasingNormalCommand(args, result);
666*b9c1b51eSKate Stone     } else {
667*b9c1b51eSKate Stone       return HandleAliasingRawCommand(alias_command, raw_command_string,
668*b9c1b51eSKate Stone                                       *cmd_obj, result);
6695a988416SJim Ingham     }
6705a988416SJim Ingham     return result.Succeeded();
6715a988416SJim Ingham   }
6725a988416SJim Ingham 
673*b9c1b51eSKate Stone   bool HandleAliasingRawCommand(const std::string &alias_command,
674*b9c1b51eSKate Stone                                 std::string &raw_command_string,
675*b9c1b51eSKate Stone                                 CommandObject &cmd_obj,
676*b9c1b51eSKate Stone                                 CommandReturnObject &result) {
677844d2303SCaroline Tice     // Verify & handle any options/arguments passed to the alias command
678844d2303SCaroline Tice 
679*b9c1b51eSKate Stone     OptionArgVectorSP option_arg_vector_sp =
680*b9c1b51eSKate Stone         OptionArgVectorSP(new OptionArgVector);
681844d2303SCaroline Tice 
682*b9c1b51eSKate Stone     if (CommandObjectSP cmd_obj_sp =
683*b9c1b51eSKate Stone             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
684*b9c1b51eSKate Stone       if (m_interpreter.AliasExists(alias_command.c_str()) ||
685*b9c1b51eSKate Stone           m_interpreter.UserCommandExists(alias_command.c_str())) {
686*b9c1b51eSKate Stone         result.AppendWarningWithFormat(
687*b9c1b51eSKate Stone             "Overwriting existing definition for '%s'.\n",
688844d2303SCaroline Tice             alias_command.c_str());
689844d2303SCaroline Tice       }
690*b9c1b51eSKate Stone       if (CommandAlias *alias = m_interpreter.AddAlias(
691*b9c1b51eSKate Stone               alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) {
69245d0e238SEnrico Granata         if (m_command_options.m_help.OptionWasSet())
69345d0e238SEnrico Granata           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
69445d0e238SEnrico Granata         if (m_command_options.m_long_help.OptionWasSet())
69545d0e238SEnrico Granata           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
696844d2303SCaroline Tice         result.SetStatus(eReturnStatusSuccessFinishNoResult);
697*b9c1b51eSKate Stone       } else {
698472362e6SCaroline Tice         result.AppendError("Unable to create requested alias.\n");
699472362e6SCaroline Tice         result.SetStatus(eReturnStatusFailed);
700472362e6SCaroline Tice       }
701212130acSEnrico Granata 
702*b9c1b51eSKate Stone     } else {
703212130acSEnrico Granata       result.AppendError("Unable to create requested alias.\n");
704212130acSEnrico Granata       result.SetStatus(eReturnStatusFailed);
705212130acSEnrico Granata     }
706212130acSEnrico Granata 
707844d2303SCaroline Tice     return result.Succeeded();
708844d2303SCaroline Tice   }
709ebc09c36SJim Ingham 
710*b9c1b51eSKate Stone   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
711867b185dSCaroline Tice     size_t argc = args.GetArgumentCount();
712ebc09c36SJim Ingham 
713*b9c1b51eSKate Stone     if (argc < 2) {
714d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
715ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
716ebc09c36SJim Ingham       return false;
717ebc09c36SJim Ingham     }
718ebc09c36SJim Ingham 
719ebc09c36SJim Ingham     const std::string alias_command = args.GetArgumentAtIndex(0);
720ebc09c36SJim Ingham     const std::string actual_command = args.GetArgumentAtIndex(1);
721ebc09c36SJim Ingham 
722ebc09c36SJim Ingham     args.Shift(); // Shift the alias command word off the argument vector.
723ebc09c36SJim Ingham     args.Shift(); // Shift the old command word off the argument vector.
724ebc09c36SJim Ingham 
725*b9c1b51eSKate Stone     // Verify that the command is alias'able, and get the appropriate command
726*b9c1b51eSKate Stone     // object.
727ebc09c36SJim Ingham 
728*b9c1b51eSKate Stone     if (m_interpreter.CommandExists(alias_command.c_str())) {
729*b9c1b51eSKate Stone       result.AppendErrorWithFormat(
730*b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
731ebc09c36SJim Ingham           alias_command.c_str());
732ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
733*b9c1b51eSKate Stone     } else {
734*b9c1b51eSKate Stone       CommandObjectSP command_obj_sp(
735*b9c1b51eSKate Stone           m_interpreter.GetCommandSPExact(actual_command.c_str(), true));
736ebc09c36SJim Ingham       CommandObjectSP subcommand_obj_sp;
737ebc09c36SJim Ingham       bool use_subcommand = false;
738*b9c1b51eSKate Stone       if (command_obj_sp) {
739ebc09c36SJim Ingham         CommandObject *cmd_obj = command_obj_sp.get();
7406e3d8e7fSEugene Zelenko         CommandObject *sub_cmd_obj = nullptr;
741*b9c1b51eSKate Stone         OptionArgVectorSP option_arg_vector_sp =
742*b9c1b51eSKate Stone             OptionArgVectorSP(new OptionArgVector);
743ebc09c36SJim Ingham 
744*b9c1b51eSKate Stone         while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) {
745*b9c1b51eSKate Stone           if (argc >= 3) {
746ebc09c36SJim Ingham             const std::string sub_command = args.GetArgumentAtIndex(0);
747ebc09c36SJim Ingham             assert(sub_command.length() != 0);
748998255bfSGreg Clayton             subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command.c_str());
749*b9c1b51eSKate Stone             if (subcommand_obj_sp) {
750ebc09c36SJim Ingham               sub_cmd_obj = subcommand_obj_sp.get();
751ebc09c36SJim Ingham               use_subcommand = true;
752*b9c1b51eSKate Stone               args.Shift(); // Shift the sub_command word off the argument
753*b9c1b51eSKate Stone                             // vector.
754844d2303SCaroline Tice               cmd_obj = sub_cmd_obj;
755*b9c1b51eSKate Stone             } else {
756*b9c1b51eSKate Stone               result.AppendErrorWithFormat(
757*b9c1b51eSKate Stone                   "'%s' is not a valid sub-command of '%s'.  "
758f415eeb4SCaroline Tice                   "Unable to create alias.\n",
759f415eeb4SCaroline Tice                   sub_command.c_str(), actual_command.c_str());
760ebc09c36SJim Ingham               result.SetStatus(eReturnStatusFailed);
761ebc09c36SJim Ingham               return false;
762ebc09c36SJim Ingham             }
763ebc09c36SJim Ingham           }
764ebc09c36SJim Ingham         }
765ebc09c36SJim Ingham 
766ebc09c36SJim Ingham         // Verify & handle any options/arguments passed to the alias command
767ebc09c36SJim Ingham 
768212130acSEnrico Granata         std::string args_string;
769212130acSEnrico Granata 
770*b9c1b51eSKate Stone         if (args.GetArgumentCount() > 0) {
771*b9c1b51eSKate Stone           CommandObjectSP tmp_sp =
772*b9c1b51eSKate Stone               m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
773ebc09c36SJim Ingham           if (use_subcommand)
774*b9c1b51eSKate Stone             tmp_sp = m_interpreter.GetCommandSPExact(
775*b9c1b51eSKate Stone                 sub_cmd_obj->GetCommandName(), false);
776ca90c47eSCaroline Tice 
777ca90c47eSCaroline Tice           args.GetCommandString(args_string);
778867b185dSCaroline Tice         }
779ebc09c36SJim Ingham 
780*b9c1b51eSKate Stone         if (m_interpreter.AliasExists(alias_command.c_str()) ||
781*b9c1b51eSKate Stone             m_interpreter.UserCommandExists(alias_command.c_str())) {
782*b9c1b51eSKate Stone           result.AppendWarningWithFormat(
783*b9c1b51eSKate Stone               "Overwriting existing definition for '%s'.\n",
784ebc09c36SJim Ingham               alias_command.c_str());
785ebc09c36SJim Ingham         }
786ebc09c36SJim Ingham 
787*b9c1b51eSKate Stone         if (CommandAlias *alias = m_interpreter.AddAlias(
788*b9c1b51eSKate Stone                 alias_command.c_str(),
789212130acSEnrico Granata                 use_subcommand ? subcommand_obj_sp : command_obj_sp,
790*b9c1b51eSKate Stone                 args_string.c_str())) {
79145d0e238SEnrico Granata           if (m_command_options.m_help.OptionWasSet())
79245d0e238SEnrico Granata             alias->SetHelp(m_command_options.m_help.GetCurrentValue());
79345d0e238SEnrico Granata           if (m_command_options.m_long_help.OptionWasSet())
79445d0e238SEnrico Granata             alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
795ebc09c36SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishNoResult);
796*b9c1b51eSKate Stone         } else {
797212130acSEnrico Granata           result.AppendError("Unable to create requested alias.\n");
798212130acSEnrico Granata           result.SetStatus(eReturnStatusFailed);
799212130acSEnrico Granata           return false;
800212130acSEnrico Granata         }
801*b9c1b51eSKate Stone       } else {
802*b9c1b51eSKate Stone         result.AppendErrorWithFormat("'%s' is not an existing command.\n",
803*b9c1b51eSKate Stone                                      actual_command.c_str());
804ebc09c36SJim Ingham         result.SetStatus(eReturnStatusFailed);
805e7941795SCaroline Tice         return false;
806ebc09c36SJim Ingham       }
807ebc09c36SJim Ingham     }
808ebc09c36SJim Ingham 
809ebc09c36SJim Ingham     return result.Succeeded();
810ebc09c36SJim Ingham   }
811ebc09c36SJim Ingham };
812ebc09c36SJim Ingham 
813*b9c1b51eSKate Stone OptionDefinition CommandObjectCommandsAlias::CommandOptions::g_option_table[] =
81445d0e238SEnrico Granata     {
815ac9c3a62SKate Stone         // clang-format off
81645d0e238SEnrico Granata   {LLDB_OPT_SET_ALL, false, "help",      'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"},
81745d0e238SEnrico Granata   {LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"},
81845d0e238SEnrico Granata   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
819ac9c3a62SKate Stone         // clang-format on
82045d0e238SEnrico Granata };
82145d0e238SEnrico Granata 
822ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
823ebc09c36SJim Ingham //-------------------------------------------------------------------------
824ebc09c36SJim Ingham // CommandObjectCommandsUnalias
825ebc09c36SJim Ingham //-------------------------------------------------------------------------
826ebc09c36SJim Ingham 
827*b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed {
828ebc09c36SJim Ingham public:
8297428a18cSKate Stone   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
830*b9c1b51eSKate Stone       : CommandObjectParsed(
831*b9c1b51eSKate Stone             interpreter, "command unalias",
832*b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command alias'.",
833*b9c1b51eSKate Stone             nullptr) {
834405fe67fSCaroline Tice     CommandArgumentEntry arg;
835405fe67fSCaroline Tice     CommandArgumentData alias_arg;
836405fe67fSCaroline Tice 
837405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
838405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
839405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
840405fe67fSCaroline Tice 
841*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
842*b9c1b51eSKate Stone     // argument entry.
843405fe67fSCaroline Tice     arg.push_back(alias_arg);
844405fe67fSCaroline Tice 
845405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
846405fe67fSCaroline Tice     m_arguments.push_back(arg);
847ebc09c36SJim Ingham   }
848ebc09c36SJim Ingham 
8496e3d8e7fSEugene Zelenko   ~CommandObjectCommandsUnalias() override = default;
850ebc09c36SJim Ingham 
8515a988416SJim Ingham protected:
852*b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
853ebc09c36SJim Ingham     CommandObject::CommandMap::iterator pos;
854ebc09c36SJim Ingham     CommandObject *cmd_obj;
855ebc09c36SJim Ingham 
856*b9c1b51eSKate Stone     if (args.GetArgumentCount() != 0) {
857ebc09c36SJim Ingham       const char *command_name = args.GetArgumentAtIndex(0);
858a7015092SGreg Clayton       cmd_obj = m_interpreter.GetCommandObject(command_name);
859*b9c1b51eSKate Stone       if (cmd_obj) {
860*b9c1b51eSKate Stone         if (m_interpreter.CommandExists(command_name)) {
861*b9c1b51eSKate Stone           if (cmd_obj->IsRemovable()) {
862*b9c1b51eSKate Stone             result.AppendErrorWithFormat(
863*b9c1b51eSKate Stone                 "'%s' is not an alias, it is a debugger command which can be "
864*b9c1b51eSKate Stone                 "removed using the 'command delete' command.\n",
865b547278cSGreg Clayton                 command_name);
866*b9c1b51eSKate Stone           } else {
867*b9c1b51eSKate Stone             result.AppendErrorWithFormat(
868*b9c1b51eSKate Stone                 "'%s' is a permanent debugger command and cannot be removed.\n",
869ebc09c36SJim Ingham                 command_name);
870b547278cSGreg Clayton           }
871ebc09c36SJim Ingham           result.SetStatus(eReturnStatusFailed);
872*b9c1b51eSKate Stone         } else {
873*b9c1b51eSKate Stone           if (!m_interpreter.RemoveAlias(command_name)) {
874a7015092SGreg Clayton             if (m_interpreter.AliasExists(command_name))
875*b9c1b51eSKate Stone               result.AppendErrorWithFormat(
876*b9c1b51eSKate Stone                   "Error occurred while attempting to unalias '%s'.\n",
877ebc09c36SJim Ingham                   command_name);
878ebc09c36SJim Ingham             else
879*b9c1b51eSKate Stone               result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
880*b9c1b51eSKate Stone                                            command_name);
881ebc09c36SJim Ingham             result.SetStatus(eReturnStatusFailed);
882*b9c1b51eSKate Stone           } else
883ebc09c36SJim Ingham             result.SetStatus(eReturnStatusSuccessFinishNoResult);
884ebc09c36SJim Ingham         }
885*b9c1b51eSKate Stone       } else {
886*b9c1b51eSKate Stone         result.AppendErrorWithFormat(
887*b9c1b51eSKate Stone             "'%s' is not a known command.\nTry 'help' to see a "
888ebc09c36SJim Ingham             "current list of commands.\n",
889ebc09c36SJim Ingham             command_name);
890ebc09c36SJim Ingham         result.SetStatus(eReturnStatusFailed);
891ebc09c36SJim Ingham       }
892*b9c1b51eSKate Stone     } else {
893ebc09c36SJim Ingham       result.AppendError("must call 'unalias' with a valid alias");
894ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
895ebc09c36SJim Ingham     }
896ebc09c36SJim Ingham 
897ebc09c36SJim Ingham     return result.Succeeded();
898ebc09c36SJim Ingham   }
899ebc09c36SJim Ingham };
900ebc09c36SJim Ingham 
901b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete
902b547278cSGreg Clayton //-------------------------------------------------------------------------
903b547278cSGreg Clayton // CommandObjectCommandsDelete
904b547278cSGreg Clayton //-------------------------------------------------------------------------
905b547278cSGreg Clayton 
906*b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed {
907b547278cSGreg Clayton public:
9087428a18cSKate Stone   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
909*b9c1b51eSKate Stone       : CommandObjectParsed(
910*b9c1b51eSKate Stone             interpreter, "command delete",
911*b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command regex'.",
912*b9c1b51eSKate Stone             nullptr) {
913b547278cSGreg Clayton     CommandArgumentEntry arg;
914b547278cSGreg Clayton     CommandArgumentData alias_arg;
915b547278cSGreg Clayton 
916b547278cSGreg Clayton     // Define the first (and only) variant of this arg.
917b547278cSGreg Clayton     alias_arg.arg_type = eArgTypeCommandName;
918b547278cSGreg Clayton     alias_arg.arg_repetition = eArgRepeatPlain;
919b547278cSGreg Clayton 
920*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
921*b9c1b51eSKate Stone     // argument entry.
922b547278cSGreg Clayton     arg.push_back(alias_arg);
923b547278cSGreg Clayton 
924b547278cSGreg Clayton     // Push the data for the first argument into the m_arguments vector.
925b547278cSGreg Clayton     m_arguments.push_back(arg);
926b547278cSGreg Clayton   }
927b547278cSGreg Clayton 
9286e3d8e7fSEugene Zelenko   ~CommandObjectCommandsDelete() override = default;
929b547278cSGreg Clayton 
930b547278cSGreg Clayton protected:
931*b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
932b547278cSGreg Clayton     CommandObject::CommandMap::iterator pos;
933b547278cSGreg Clayton 
934*b9c1b51eSKate Stone     if (args.GetArgumentCount() != 0) {
935b547278cSGreg Clayton       const char *command_name = args.GetArgumentAtIndex(0);
936*b9c1b51eSKate Stone       if (m_interpreter.CommandExists(command_name)) {
937*b9c1b51eSKate Stone         if (m_interpreter.RemoveCommand(command_name)) {
938b547278cSGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishNoResult);
939*b9c1b51eSKate Stone         } else {
940*b9c1b51eSKate Stone           result.AppendErrorWithFormat(
941*b9c1b51eSKate Stone               "'%s' is a permanent debugger command and cannot be removed.\n",
942b547278cSGreg Clayton               command_name);
943b547278cSGreg Clayton           result.SetStatus(eReturnStatusFailed);
944b547278cSGreg Clayton         }
945*b9c1b51eSKate Stone       } else {
94646d4aa21SEnrico Granata         StreamString error_msg_stream;
94746d4aa21SEnrico Granata         const bool generate_apropos = true;
94846d4aa21SEnrico Granata         const bool generate_type_lookup = false;
949*b9c1b51eSKate Stone         CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
950*b9c1b51eSKate Stone             &error_msg_stream, command_name, nullptr, nullptr, generate_apropos,
95146d4aa21SEnrico Granata             generate_type_lookup);
95246d4aa21SEnrico Granata         result.AppendErrorWithFormat("%s", error_msg_stream.GetData());
953b547278cSGreg Clayton         result.SetStatus(eReturnStatusFailed);
954b547278cSGreg Clayton       }
955*b9c1b51eSKate Stone     } else {
956*b9c1b51eSKate Stone       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
957*b9c1b51eSKate Stone                                    "defined regular expression command names",
9587428a18cSKate Stone                                    GetCommandName());
959b547278cSGreg Clayton       result.SetStatus(eReturnStatusFailed);
960b547278cSGreg Clayton     }
961b547278cSGreg Clayton 
962b547278cSGreg Clayton     return result.Succeeded();
963b547278cSGreg Clayton   }
964b547278cSGreg Clayton };
965b547278cSGreg Clayton 
966de164aaaSGreg Clayton //-------------------------------------------------------------------------
967de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
968de164aaaSGreg Clayton //-------------------------------------------------------------------------
9695a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex
970de164aaaSGreg Clayton 
971*b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed,
972*b9c1b51eSKate Stone                                       public IOHandlerDelegateMultiline {
973de164aaaSGreg Clayton public:
9747428a18cSKate Stone   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
975*b9c1b51eSKate Stone       : CommandObjectParsed(
976*b9c1b51eSKate Stone             interpreter, "command regex", "Define a custom command in terms of "
977*b9c1b51eSKate Stone                                           "existing commands by matching "
978*b9c1b51eSKate Stone                                           "regular expressions.",
9790e5e5a79SGreg Clayton             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
980*b9c1b51eSKate Stone         IOHandlerDelegateMultiline("",
981*b9c1b51eSKate Stone                                    IOHandlerDelegate::Completion::LLDBCommand),
982*b9c1b51eSKate Stone         m_options() {
983*b9c1b51eSKate Stone     SetHelpLong(
984*b9c1b51eSKate Stone         R"(
985*b9c1b51eSKate Stone )"
986*b9c1b51eSKate Stone         "This command allows the user to create powerful regular expression commands \
987ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \
988*b9c1b51eSKate Stone using the regular expression substitution format of:"
989*b9c1b51eSKate Stone         R"(
990ea671fbdSKate Stone 
991ea671fbdSKate Stone     s/<regex>/<subst>/
992ea671fbdSKate Stone 
993*b9c1b51eSKate Stone )"
994*b9c1b51eSKate Stone         "<regex> is a regular expression that can use parenthesis to capture regular \
995ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \
996*b9c1b51eSKate Stone for the first match, %2 for the second, and so on."
997*b9c1b51eSKate Stone         R"(
998ea671fbdSKate Stone 
999*b9c1b51eSKate Stone )"
1000*b9c1b51eSKate Stone         "The regular expressions can all be specified on the command line if more than \
1001ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \
1002ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \
1003*b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition."
1004*b9c1b51eSKate Stone         R"(
1005ea671fbdSKate Stone 
1006ea671fbdSKate Stone EXAMPLES
1007ea671fbdSKate Stone 
1008*b9c1b51eSKate Stone )"
1009*b9c1b51eSKate Stone         "The following example will define a regular expression command named 'f' that \
1010ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
1011*b9c1b51eSKate Stone a number follows 'f':"
1012*b9c1b51eSKate Stone         R"(
1013ea671fbdSKate Stone 
1014*b9c1b51eSKate Stone     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1015de164aaaSGreg Clayton   }
1016de164aaaSGreg Clayton 
10176e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAddRegex() override = default;
1018de164aaaSGreg Clayton 
10195a988416SJim Ingham protected:
1020*b9c1b51eSKate Stone   void IOHandlerActivated(IOHandler &io_handler) override {
102144d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1022*b9c1b51eSKate Stone     if (output_sp) {
1023*b9c1b51eSKate Stone       output_sp->PutCString("Enter one of more sed substitution commands in "
1024*b9c1b51eSKate Stone                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
1025*b9c1b51eSKate Stone                             "substitution list with an empty line.\n");
102644d93782SGreg Clayton       output_sp->Flush();
102744d93782SGreg Clayton     }
102844d93782SGreg Clayton   }
102944d93782SGreg Clayton 
1030*b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1031*b9c1b51eSKate Stone                               std::string &data) override {
103244d93782SGreg Clayton     io_handler.SetIsDone(true);
1033*b9c1b51eSKate Stone     if (m_regex_cmd_ap) {
103444d93782SGreg Clayton       StringList lines;
1035*b9c1b51eSKate Stone       if (lines.SplitIntoLines(data)) {
103644d93782SGreg Clayton         const size_t num_lines = lines.GetSize();
103744d93782SGreg Clayton         bool check_only = false;
1038*b9c1b51eSKate Stone         for (size_t i = 0; i < num_lines; ++i) {
103944d93782SGreg Clayton           llvm::StringRef bytes_strref(lines[i]);
104044d93782SGreg Clayton           Error error = AppendRegexSubstitution(bytes_strref, check_only);
1041*b9c1b51eSKate Stone           if (error.Fail()) {
1042*b9c1b51eSKate Stone             if (!m_interpreter.GetDebugger()
1043*b9c1b51eSKate Stone                      .GetCommandInterpreter()
1044*b9c1b51eSKate Stone                      .GetBatchCommandMode()) {
1045*b9c1b51eSKate Stone               StreamSP out_stream =
1046*b9c1b51eSKate Stone                   m_interpreter.GetDebugger().GetAsyncOutputStream();
104744d93782SGreg Clayton               out_stream->Printf("error: %s\n", error.AsCString());
104844d93782SGreg Clayton             }
104944d93782SGreg Clayton           }
105044d93782SGreg Clayton         }
105144d93782SGreg Clayton       }
1052*b9c1b51eSKate Stone       if (m_regex_cmd_ap->HasRegexEntries()) {
105344d93782SGreg Clayton         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
105444d93782SGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
105544d93782SGreg Clayton       }
105644d93782SGreg Clayton     }
105744d93782SGreg Clayton   }
105844d93782SGreg Clayton 
1059*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
10605a988416SJim Ingham     const size_t argc = command.GetArgumentCount();
1061*b9c1b51eSKate Stone     if (argc == 0) {
1062*b9c1b51eSKate Stone       result.AppendError("usage: 'command regex <command-name> "
1063*b9c1b51eSKate Stone                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
10640e5e5a79SGreg Clayton       result.SetStatus(eReturnStatusFailed);
1065*b9c1b51eSKate Stone     } else {
10660e5e5a79SGreg Clayton       Error error;
10675a988416SJim Ingham       const char *name = command.GetArgumentAtIndex(0);
1068*b9c1b51eSKate Stone       m_regex_cmd_ap.reset(new CommandObjectRegexCommand(
1069*b9c1b51eSKate Stone           m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10,
1070*b9c1b51eSKate Stone           0, true));
10710e5e5a79SGreg Clayton 
1072*b9c1b51eSKate Stone       if (argc == 1) {
107344d93782SGreg Clayton         Debugger &debugger = m_interpreter.GetDebugger();
1074e30f11d9SKate Stone         bool color_prompt = debugger.GetUseColor();
107544d93782SGreg Clayton         const bool multiple_lines = true; // Get multiple lines
1076*b9c1b51eSKate Stone         IOHandlerSP io_handler_sp(new IOHandlerEditline(
1077*b9c1b51eSKate Stone             debugger, IOHandler::Type::Other,
107873d80faaSGreg Clayton             "lldb-regex", // Name of input reader for history
1079ea508635SGreg Clayton             "> ",         // Prompt
10806e3d8e7fSEugene Zelenko             nullptr,      // Continuation prompt
1081*b9c1b51eSKate Stone             multiple_lines, color_prompt,
1082f6913cd7SGreg Clayton             0, // Don't show line numbers
108344d93782SGreg Clayton             *this));
108444d93782SGreg Clayton 
1085*b9c1b51eSKate Stone         if (io_handler_sp) {
108644d93782SGreg Clayton           debugger.PushIOHandler(io_handler_sp);
1087de164aaaSGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1088de164aaaSGreg Clayton         }
1089*b9c1b51eSKate Stone       } else {
1090*b9c1b51eSKate Stone         for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) {
10915a988416SJim Ingham           llvm::StringRef arg_strref(command.GetArgumentAtIndex(arg_idx));
109244d93782SGreg Clayton           bool check_only = false;
109344d93782SGreg Clayton           error = AppendRegexSubstitution(arg_strref, check_only);
10940e5e5a79SGreg Clayton           if (error.Fail())
10950e5e5a79SGreg Clayton             break;
10960e5e5a79SGreg Clayton         }
10970e5e5a79SGreg Clayton 
1098*b9c1b51eSKate Stone         if (error.Success()) {
10990e5e5a79SGreg Clayton           AddRegexCommandToInterpreter();
11000e5e5a79SGreg Clayton         }
11010e5e5a79SGreg Clayton       }
1102*b9c1b51eSKate Stone       if (error.Fail()) {
11030e5e5a79SGreg Clayton         result.AppendError(error.AsCString());
1104de164aaaSGreg Clayton         result.SetStatus(eReturnStatusFailed);
1105de164aaaSGreg Clayton       }
11060e5e5a79SGreg Clayton     }
11070e5e5a79SGreg Clayton 
1108de164aaaSGreg Clayton     return result.Succeeded();
1109de164aaaSGreg Clayton   }
1110de164aaaSGreg Clayton 
1111*b9c1b51eSKate Stone   Error AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1112*b9c1b51eSKate Stone                                 bool check_only) {
11130e5e5a79SGreg Clayton     Error error;
11140e5e5a79SGreg Clayton 
1115*b9c1b51eSKate Stone     if (!m_regex_cmd_ap) {
1116*b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1117*b9c1b51eSKate Stone           "invalid regular expression command object for: '%.*s'",
1118*b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11190e5e5a79SGreg Clayton       return error;
1120de164aaaSGreg Clayton     }
11210e5e5a79SGreg Clayton 
11220e5e5a79SGreg Clayton     size_t regex_sed_size = regex_sed.size();
11230e5e5a79SGreg Clayton 
1124*b9c1b51eSKate Stone     if (regex_sed_size <= 1) {
1125*b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1126*b9c1b51eSKate Stone           "regular expression substitution string is too short: '%.*s'",
1127*b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11280e5e5a79SGreg Clayton       return error;
11290e5e5a79SGreg Clayton     }
11300e5e5a79SGreg Clayton 
1131*b9c1b51eSKate Stone     if (regex_sed[0] != 's') {
1132*b9c1b51eSKate Stone       error.SetErrorStringWithFormat("regular expression substitution string "
1133*b9c1b51eSKate Stone                                      "doesn't start with 's': '%.*s'",
1134*b9c1b51eSKate Stone                                      (int)regex_sed.size(), regex_sed.data());
11350e5e5a79SGreg Clayton       return error;
11360e5e5a79SGreg Clayton     }
11370e5e5a79SGreg Clayton     const size_t first_separator_char_pos = 1;
11380e5e5a79SGreg Clayton     // use the char that follows 's' as the regex separator character
11390e5e5a79SGreg Clayton     // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
11400e5e5a79SGreg Clayton     const char separator_char = regex_sed[first_separator_char_pos];
1141*b9c1b51eSKate Stone     const size_t second_separator_char_pos =
1142*b9c1b51eSKate Stone         regex_sed.find(separator_char, first_separator_char_pos + 1);
11430e5e5a79SGreg Clayton 
1144*b9c1b51eSKate Stone     if (second_separator_char_pos == std::string::npos) {
1145*b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1146*b9c1b51eSKate Stone           "missing second '%c' separator char after '%.*s' in '%.*s'",
11470e5e5a79SGreg Clayton           separator_char,
11480e5e5a79SGreg Clayton           (int)(regex_sed.size() - first_separator_char_pos - 1),
1149ea508635SGreg Clayton           regex_sed.data() + (first_separator_char_pos + 1),
1150*b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11510e5e5a79SGreg Clayton       return error;
11520e5e5a79SGreg Clayton     }
11530e5e5a79SGreg Clayton 
1154*b9c1b51eSKate Stone     const size_t third_separator_char_pos =
1155*b9c1b51eSKate Stone         regex_sed.find(separator_char, second_separator_char_pos + 1);
11560e5e5a79SGreg Clayton 
1157*b9c1b51eSKate Stone     if (third_separator_char_pos == std::string::npos) {
1158*b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1159*b9c1b51eSKate Stone           "missing third '%c' separator char after '%.*s' in '%.*s'",
11600e5e5a79SGreg Clayton           separator_char,
11610e5e5a79SGreg Clayton           (int)(regex_sed.size() - second_separator_char_pos - 1),
1162ea508635SGreg Clayton           regex_sed.data() + (second_separator_char_pos + 1),
1163*b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11640e5e5a79SGreg Clayton       return error;
11650e5e5a79SGreg Clayton     }
11660e5e5a79SGreg Clayton 
1167*b9c1b51eSKate Stone     if (third_separator_char_pos != regex_sed_size - 1) {
11680e5e5a79SGreg Clayton       // Make sure that everything that follows the last regex
11690e5e5a79SGreg Clayton       // separator char
1170*b9c1b51eSKate Stone       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1171*b9c1b51eSKate Stone                                       third_separator_char_pos + 1) !=
1172*b9c1b51eSKate Stone           std::string::npos) {
1173*b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
1174*b9c1b51eSKate Stone             "extra data found after the '%.*s' regular expression substitution "
1175*b9c1b51eSKate Stone             "string: '%.*s'",
1176*b9c1b51eSKate Stone             (int)third_separator_char_pos + 1, regex_sed.data(),
11770e5e5a79SGreg Clayton             (int)(regex_sed.size() - third_separator_char_pos - 1),
11780e5e5a79SGreg Clayton             regex_sed.data() + (third_separator_char_pos + 1));
11790e5e5a79SGreg Clayton         return error;
11800e5e5a79SGreg Clayton       }
1181*b9c1b51eSKate Stone     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1182*b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1183*b9c1b51eSKate Stone           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1184*b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
11850e5e5a79SGreg Clayton           regex_sed.data());
11860e5e5a79SGreg Clayton       return error;
1187*b9c1b51eSKate Stone     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1188*b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1189*b9c1b51eSKate Stone           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1190*b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
11910e5e5a79SGreg Clayton           regex_sed.data());
11920e5e5a79SGreg Clayton       return error;
11930e5e5a79SGreg Clayton     }
119444d93782SGreg Clayton 
1195*b9c1b51eSKate Stone     if (!check_only) {
1196*b9c1b51eSKate Stone       std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1197*b9c1b51eSKate Stone                                          second_separator_char_pos -
1198*b9c1b51eSKate Stone                                              first_separator_char_pos - 1));
1199*b9c1b51eSKate Stone       std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1200*b9c1b51eSKate Stone                                          third_separator_char_pos -
1201*b9c1b51eSKate Stone                                              second_separator_char_pos - 1));
1202*b9c1b51eSKate Stone       m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
120344d93782SGreg Clayton     }
12040e5e5a79SGreg Clayton     return error;
1205de164aaaSGreg Clayton   }
1206de164aaaSGreg Clayton 
1207*b9c1b51eSKate Stone   void AddRegexCommandToInterpreter() {
1208*b9c1b51eSKate Stone     if (m_regex_cmd_ap) {
1209*b9c1b51eSKate Stone       if (m_regex_cmd_ap->HasRegexEntries()) {
1210de164aaaSGreg Clayton         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1211de164aaaSGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1212de164aaaSGreg Clayton       }
1213de164aaaSGreg Clayton     }
1214de164aaaSGreg Clayton   }
1215de164aaaSGreg Clayton 
1216de164aaaSGreg Clayton private:
12177b0992d9SGreg Clayton   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1218de164aaaSGreg Clayton 
1219*b9c1b51eSKate Stone   class CommandOptions : public Options {
1220de164aaaSGreg Clayton   public:
1221*b9c1b51eSKate Stone     CommandOptions() : Options() {}
1222de164aaaSGreg Clayton 
12236e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1224de164aaaSGreg Clayton 
1225*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1226*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
1227de164aaaSGreg Clayton       Error error;
12283bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1229de164aaaSGreg Clayton 
1230*b9c1b51eSKate Stone       switch (short_option) {
1231de164aaaSGreg Clayton       case 'h':
1232de164aaaSGreg Clayton         m_help.assign(option_arg);
1233de164aaaSGreg Clayton         break;
1234de164aaaSGreg Clayton       case 's':
1235de164aaaSGreg Clayton         m_syntax.assign(option_arg);
1236de164aaaSGreg Clayton         break;
1237de164aaaSGreg Clayton       default:
1238*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1239*b9c1b51eSKate Stone                                        short_option);
1240de164aaaSGreg Clayton         break;
1241de164aaaSGreg Clayton       }
1242de164aaaSGreg Clayton 
1243de164aaaSGreg Clayton       return error;
1244de164aaaSGreg Clayton     }
1245de164aaaSGreg Clayton 
1246*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1247de164aaaSGreg Clayton       m_help.clear();
1248de164aaaSGreg Clayton       m_syntax.clear();
1249de164aaaSGreg Clayton     }
1250de164aaaSGreg Clayton 
1251*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
1252de164aaaSGreg Clayton 
1253de164aaaSGreg Clayton     // Options table: Required for subclasses of Options.
1254de164aaaSGreg Clayton 
1255de164aaaSGreg Clayton     static OptionDefinition g_option_table[];
1256de164aaaSGreg Clayton 
1257*b9c1b51eSKate Stone     const char *GetHelp() {
12586e3d8e7fSEugene Zelenko       return (m_help.empty() ? nullptr : m_help.c_str());
1259de164aaaSGreg Clayton     }
12606e3d8e7fSEugene Zelenko 
1261*b9c1b51eSKate Stone     const char *GetSyntax() {
12626e3d8e7fSEugene Zelenko       return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1263de164aaaSGreg Clayton     }
12646e3d8e7fSEugene Zelenko 
1265de164aaaSGreg Clayton   protected:
12666e3d8e7fSEugene Zelenko     // Instance variables to hold the values for command options.
12676e3d8e7fSEugene Zelenko 
1268de164aaaSGreg Clayton     std::string m_help;
1269de164aaaSGreg Clayton     std::string m_syntax;
1270de164aaaSGreg Clayton   };
1271de164aaaSGreg Clayton 
1272*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
1273de164aaaSGreg Clayton 
12745a988416SJim Ingham   CommandOptions m_options;
1275de164aaaSGreg Clayton };
1276de164aaaSGreg Clayton 
1277de164aaaSGreg Clayton OptionDefinition
1278*b9c1b51eSKate Stone     CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = {
1279ac9c3a62SKate Stone         // clang-format off
12806e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."},
12816e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
12826e3d8e7fSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
1283ac9c3a62SKate Stone         // clang-format on
1284de164aaaSGreg Clayton };
1285de164aaaSGreg Clayton 
1286*b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw {
1287223383edSEnrico Granata public:
1288*b9c1b51eSKate Stone   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1289*b9c1b51eSKate Stone                               std::string funct, std::string help,
1290*b9c1b51eSKate Stone                               ScriptedCommandSynchronicity synch)
1291*b9c1b51eSKate Stone       : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1292*b9c1b51eSKate Stone         m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1293735152e3SEnrico Granata     if (!help.empty())
1294735152e3SEnrico Granata       SetHelp(help.c_str());
1295*b9c1b51eSKate Stone     else {
1296735152e3SEnrico Granata       StreamString stream;
1297735152e3SEnrico Granata       stream.Printf("For more information run 'help %s'", name.c_str());
1298735152e3SEnrico Granata       SetHelp(stream.GetData());
1299735152e3SEnrico Granata     }
1300223383edSEnrico Granata   }
1301223383edSEnrico Granata 
13026e3d8e7fSEugene Zelenko   ~CommandObjectPythonFunction() override = default;
1303223383edSEnrico Granata 
1304*b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
13055a988416SJim Ingham 
1306*b9c1b51eSKate Stone   const std::string &GetFunctionName() { return m_function_name; }
13075a988416SJim Ingham 
1308*b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
13095a988416SJim Ingham 
1310*b9c1b51eSKate Stone   const char *GetHelpLong() override {
1311*b9c1b51eSKate Stone     if (!m_fetched_help_long) {
1312fac939e9SEnrico Granata       ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1313*b9c1b51eSKate Stone       if (scripter) {
1314fac939e9SEnrico Granata         std::string docstring;
1315*b9c1b51eSKate Stone         m_fetched_help_long = scripter->GetDocumentationForItem(
1316*b9c1b51eSKate Stone             m_function_name.c_str(), docstring);
1317fac939e9SEnrico Granata         if (!docstring.empty())
1318bfb75e9bSEnrico Granata           SetHelpLong(docstring.c_str());
1319fac939e9SEnrico Granata       }
1320fac939e9SEnrico Granata     }
1321fac939e9SEnrico Granata     return CommandObjectRaw::GetHelpLong();
1322fac939e9SEnrico Granata   }
1323fac939e9SEnrico Granata 
13245a988416SJim Ingham protected:
1325*b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
1326*b9c1b51eSKate Stone                  CommandReturnObject &result) override {
1327223383edSEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1328223383edSEnrico Granata 
1329223383edSEnrico Granata     Error error;
1330223383edSEnrico Granata 
133170f11f88SJim Ingham     result.SetStatus(eReturnStatusInvalid);
133270f11f88SJim Ingham 
1333*b9c1b51eSKate Stone     if (!scripter ||
1334*b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1335*b9c1b51eSKate Stone                                          raw_command_line, m_synchro, result,
1336*b9c1b51eSKate Stone                                          error, m_exe_ctx)) {
1337223383edSEnrico Granata       result.AppendError(error.AsCString());
1338223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1339*b9c1b51eSKate Stone     } else {
134070f11f88SJim Ingham       // Don't change the status if the command already set it...
1341*b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1342*b9c1b51eSKate Stone         if (result.GetOutputData() == nullptr ||
1343*b9c1b51eSKate Stone             result.GetOutputData()[0] == '\0')
1344223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
134570f11f88SJim Ingham         else
134670f11f88SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishResult);
134770f11f88SJim Ingham       }
134870f11f88SJim Ingham     }
1349223383edSEnrico Granata 
1350223383edSEnrico Granata     return result.Succeeded();
1351223383edSEnrico Granata   }
1352223383edSEnrico Granata 
13536e3d8e7fSEugene Zelenko private:
13546e3d8e7fSEugene Zelenko   std::string m_function_name;
13556e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
13566e3d8e7fSEugene Zelenko   bool m_fetched_help_long;
1357223383edSEnrico Granata };
1358223383edSEnrico Granata 
1359*b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw {
13609fe00e52SEnrico Granata public:
13619fe00e52SEnrico Granata   CommandObjectScriptingObject(CommandInterpreter &interpreter,
13629fe00e52SEnrico Granata                                std::string name,
13630641ca1aSZachary Turner                                StructuredData::GenericSP cmd_obj_sp,
1364*b9c1b51eSKate Stone                                ScriptedCommandSynchronicity synch)
1365*b9c1b51eSKate Stone       : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1366*b9c1b51eSKate Stone         m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1367*b9c1b51eSKate Stone         m_fetched_help_long(false) {
13689fe00e52SEnrico Granata     StreamString stream;
13699fe00e52SEnrico Granata     stream.Printf("For more information run 'help %s'", name.c_str());
13709fe00e52SEnrico Granata     SetHelp(stream.GetData());
1371e87764f2SEnrico Granata     if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1372e87764f2SEnrico Granata       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
13739fe00e52SEnrico Granata   }
13749fe00e52SEnrico Granata 
13756e3d8e7fSEugene Zelenko   ~CommandObjectScriptingObject() override = default;
13769fe00e52SEnrico Granata 
1377*b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
13789fe00e52SEnrico Granata 
1379*b9c1b51eSKate Stone   StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
13809fe00e52SEnrico Granata 
1381*b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
13829fe00e52SEnrico Granata 
1383*b9c1b51eSKate Stone   const char *GetHelp() override {
1384*b9c1b51eSKate Stone     if (!m_fetched_help_short) {
13856f79bb2dSEnrico Granata       ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1386*b9c1b51eSKate Stone       if (scripter) {
13876f79bb2dSEnrico Granata         std::string docstring;
1388*b9c1b51eSKate Stone         m_fetched_help_short =
1389*b9c1b51eSKate Stone             scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
13906f79bb2dSEnrico Granata         if (!docstring.empty())
1391bfb75e9bSEnrico Granata           SetHelp(docstring.c_str());
13926f79bb2dSEnrico Granata       }
13936f79bb2dSEnrico Granata     }
13946f79bb2dSEnrico Granata     return CommandObjectRaw::GetHelp();
13956f79bb2dSEnrico Granata   }
13966f79bb2dSEnrico Granata 
1397*b9c1b51eSKate Stone   const char *GetHelpLong() override {
1398*b9c1b51eSKate Stone     if (!m_fetched_help_long) {
13996f79bb2dSEnrico Granata       ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1400*b9c1b51eSKate Stone       if (scripter) {
14016f79bb2dSEnrico Granata         std::string docstring;
1402*b9c1b51eSKate Stone         m_fetched_help_long =
1403*b9c1b51eSKate Stone             scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
14046f79bb2dSEnrico Granata         if (!docstring.empty())
1405bfb75e9bSEnrico Granata           SetHelpLong(docstring.c_str());
14066f79bb2dSEnrico Granata       }
14076f79bb2dSEnrico Granata     }
14089fe00e52SEnrico Granata     return CommandObjectRaw::GetHelpLong();
14099fe00e52SEnrico Granata   }
14109fe00e52SEnrico Granata 
14119fe00e52SEnrico Granata protected:
1412*b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
1413*b9c1b51eSKate Stone                  CommandReturnObject &result) override {
14149fe00e52SEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
14159fe00e52SEnrico Granata 
14169fe00e52SEnrico Granata     Error error;
14179fe00e52SEnrico Granata 
14189fe00e52SEnrico Granata     result.SetStatus(eReturnStatusInvalid);
14199fe00e52SEnrico Granata 
1420*b9c1b51eSKate Stone     if (!scripter ||
1421*b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1422*b9c1b51eSKate Stone                                          m_synchro, result, error, m_exe_ctx)) {
14239fe00e52SEnrico Granata       result.AppendError(error.AsCString());
14249fe00e52SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1425*b9c1b51eSKate Stone     } else {
14269fe00e52SEnrico Granata       // Don't change the status if the command already set it...
1427*b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1428*b9c1b51eSKate Stone         if (result.GetOutputData() == nullptr ||
1429*b9c1b51eSKate Stone             result.GetOutputData()[0] == '\0')
14309fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
14319fe00e52SEnrico Granata         else
14329fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishResult);
14339fe00e52SEnrico Granata       }
14349fe00e52SEnrico Granata     }
14359fe00e52SEnrico Granata 
14369fe00e52SEnrico Granata     return result.Succeeded();
14379fe00e52SEnrico Granata   }
14389fe00e52SEnrico Granata 
14396e3d8e7fSEugene Zelenko private:
14406e3d8e7fSEugene Zelenko   StructuredData::GenericSP m_cmd_obj_sp;
14416e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
14426e3d8e7fSEugene Zelenko   bool m_fetched_help_short : 1;
14436e3d8e7fSEugene Zelenko   bool m_fetched_help_long : 1;
14449fe00e52SEnrico Granata };
14459fe00e52SEnrico Granata 
1446a9dbf432SEnrico Granata //-------------------------------------------------------------------------
1447a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport
1448a9dbf432SEnrico Granata //-------------------------------------------------------------------------
1449a9dbf432SEnrico Granata 
1450*b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed {
14515a988416SJim Ingham public:
1452*b9c1b51eSKate Stone   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1453*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script import",
1454*b9c1b51eSKate Stone                             "Import a scripting module in LLDB.", nullptr),
1455*b9c1b51eSKate Stone         m_options() {
14565a988416SJim Ingham     CommandArgumentEntry arg1;
14575a988416SJim Ingham     CommandArgumentData cmd_arg;
14585a988416SJim Ingham 
14595a988416SJim Ingham     // Define the first (and only) variant of this arg.
14605a988416SJim Ingham     cmd_arg.arg_type = eArgTypeFilename;
14613b00e35bSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlus;
14625a988416SJim Ingham 
1463*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1464*b9c1b51eSKate Stone     // argument entry.
14655a988416SJim Ingham     arg1.push_back(cmd_arg);
14665a988416SJim Ingham 
14675a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
14685a988416SJim Ingham     m_arguments.push_back(arg1);
14695a988416SJim Ingham   }
14705a988416SJim Ingham 
14716e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptImport() override = default;
14725a988416SJim Ingham 
1473*b9c1b51eSKate Stone   int HandleArgumentCompletion(Args &input, int &cursor_index,
14745a988416SJim Ingham                                int &cursor_char_position,
14755a988416SJim Ingham                                OptionElementVector &opt_element_vector,
1476*b9c1b51eSKate Stone                                int match_start_point, int max_return_elements,
14775a988416SJim Ingham                                bool &word_complete,
1478*b9c1b51eSKate Stone                                StringList &matches) override {
14795a988416SJim Ingham     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
14805a988416SJim Ingham     completion_str.erase(cursor_char_position);
14815a988416SJim Ingham 
1482*b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
1483*b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1484*b9c1b51eSKate Stone         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1485*b9c1b51eSKate Stone         word_complete, matches);
14865a988416SJim Ingham     return matches.GetSize();
14875a988416SJim Ingham   }
14885a988416SJim Ingham 
1489*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
14905a988416SJim Ingham 
14915a988416SJim Ingham protected:
1492*b9c1b51eSKate Stone   class CommandOptions : public Options {
14930a305db7SEnrico Granata   public:
1494*b9c1b51eSKate Stone     CommandOptions() : Options() {}
14950a305db7SEnrico Granata 
14966e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
14970a305db7SEnrico Granata 
1498*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1499*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
15000a305db7SEnrico Granata       Error error;
15013bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
15020a305db7SEnrico Granata 
1503*b9c1b51eSKate Stone       switch (short_option) {
15040a305db7SEnrico Granata       case 'r':
15050a305db7SEnrico Granata         m_allow_reload = true;
15060a305db7SEnrico Granata         break;
15070a305db7SEnrico Granata       default:
1508*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1509*b9c1b51eSKate Stone                                        short_option);
15100a305db7SEnrico Granata         break;
15110a305db7SEnrico Granata       }
15120a305db7SEnrico Granata 
15130a305db7SEnrico Granata       return error;
15140a305db7SEnrico Granata     }
15150a305db7SEnrico Granata 
1516*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1517e0c70f1bSEnrico Granata       m_allow_reload = true;
15180a305db7SEnrico Granata     }
15190a305db7SEnrico Granata 
1520*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
15210a305db7SEnrico Granata 
15220a305db7SEnrico Granata     // Options table: Required for subclasses of Options.
15230a305db7SEnrico Granata 
15240a305db7SEnrico Granata     static OptionDefinition g_option_table[];
15250a305db7SEnrico Granata 
15260a305db7SEnrico Granata     // Instance variables to hold the values for command options.
15270a305db7SEnrico Granata 
15280a305db7SEnrico Granata     bool m_allow_reload;
15290a305db7SEnrico Granata   };
15300a305db7SEnrico Granata 
1531*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1532*b9c1b51eSKate Stone     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1533*b9c1b51eSKate Stone         lldb::eScriptLanguagePython) {
1534*b9c1b51eSKate Stone       result.AppendError("only scripting language supported for module "
1535*b9c1b51eSKate Stone                          "importing is currently Python");
1536a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1537a9dbf432SEnrico Granata       return false;
1538a9dbf432SEnrico Granata     }
1539a9dbf432SEnrico Granata 
15405a988416SJim Ingham     size_t argc = command.GetArgumentCount();
1541*b9c1b51eSKate Stone     if (0 == argc) {
15423b00e35bSEnrico Granata       result.AppendError("command script import needs one or more arguments");
1543a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1544a9dbf432SEnrico Granata       return false;
1545a9dbf432SEnrico Granata     }
1546a9dbf432SEnrico Granata 
1547*b9c1b51eSKate Stone     for (size_t i = 0; i < argc; i++) {
15483b00e35bSEnrico Granata       std::string path = command.GetArgumentAtIndex(i);
1549a9dbf432SEnrico Granata       Error error;
1550a9dbf432SEnrico Granata 
1551c9d645d3SGreg Clayton       const bool init_session = true;
1552*b9c1b51eSKate Stone       // FIXME: this is necessary because CommandObject::CheckRequirements()
1553*b9c1b51eSKate Stone       // assumes that
1554*b9c1b51eSKate Stone       // commands won't ever be recursively invoked, but it's actually possible
1555*b9c1b51eSKate Stone       // to craft
1556*b9c1b51eSKate Stone       // a Python script that does other "command script imports" in
1557*b9c1b51eSKate Stone       // __lldb_init_module
1558*b9c1b51eSKate Stone       // the real fix is to have recursive commands possible with a
1559*b9c1b51eSKate Stone       // CommandInvocation object
1560*b9c1b51eSKate Stone       // separate from the CommandObject itself, so that recursive command
1561*b9c1b51eSKate Stone       // invocations
1562*b9c1b51eSKate Stone       // won't stomp on each other (wrt to execution contents, options, and
1563*b9c1b51eSKate Stone       // more)
1564078551c7SEnrico Granata       m_exe_ctx.Clear();
1565*b9c1b51eSKate Stone       if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1566*b9c1b51eSKate Stone               path.c_str(), m_options.m_allow_reload, init_session, error)) {
1567a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1568*b9c1b51eSKate Stone       } else {
1569*b9c1b51eSKate Stone         result.AppendErrorWithFormat("module importing failed: %s",
1570*b9c1b51eSKate Stone                                      error.AsCString());
1571a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusFailed);
1572a9dbf432SEnrico Granata       }
15733b00e35bSEnrico Granata     }
1574a9dbf432SEnrico Granata 
1575a9dbf432SEnrico Granata     return result.Succeeded();
1576a9dbf432SEnrico Granata   }
15770a305db7SEnrico Granata 
15785a988416SJim Ingham   CommandOptions m_options;
1579a9dbf432SEnrico Granata };
1580223383edSEnrico Granata 
15810a305db7SEnrico Granata OptionDefinition
1582*b9c1b51eSKate Stone     CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = {
1583ac9c3a62SKate Stone         // clang-format off
15846e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."},
15856e3d8e7fSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
1586ac9c3a62SKate Stone         // clang-format on
15870a305db7SEnrico Granata };
15880a305db7SEnrico Granata 
1589223383edSEnrico Granata //-------------------------------------------------------------------------
1590223383edSEnrico Granata // CommandObjectCommandsScriptAdd
1591223383edSEnrico Granata //-------------------------------------------------------------------------
1592223383edSEnrico Granata 
1593*b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1594*b9c1b51eSKate Stone                                        public IOHandlerDelegateMultiline {
15955a988416SJim Ingham public:
1596*b9c1b51eSKate Stone   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1597*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script add",
15985a988416SJim Ingham                             "Add a scripted function as an LLDB command.",
15996e3d8e7fSEugene Zelenko                             nullptr),
1600*b9c1b51eSKate Stone         IOHandlerDelegateMultiline("DONE"), m_options() {
16015a988416SJim Ingham     CommandArgumentEntry arg1;
16025a988416SJim Ingham     CommandArgumentData cmd_arg;
16035a988416SJim Ingham 
16045a988416SJim Ingham     // Define the first (and only) variant of this arg.
16055a988416SJim Ingham     cmd_arg.arg_type = eArgTypeCommandName;
16065a988416SJim Ingham     cmd_arg.arg_repetition = eArgRepeatPlain;
16075a988416SJim Ingham 
1608*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1609*b9c1b51eSKate Stone     // argument entry.
16105a988416SJim Ingham     arg1.push_back(cmd_arg);
16115a988416SJim Ingham 
16125a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
16135a988416SJim Ingham     m_arguments.push_back(arg1);
16145a988416SJim Ingham   }
16155a988416SJim Ingham 
16166e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptAdd() override = default;
16175a988416SJim Ingham 
1618*b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
16195a988416SJim Ingham 
16205a988416SJim Ingham protected:
1621*b9c1b51eSKate Stone   class CommandOptions : public Options {
1622223383edSEnrico Granata   public:
1623*b9c1b51eSKate Stone     CommandOptions()
1624*b9c1b51eSKate Stone         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1625*b9c1b51eSKate Stone           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1626223383edSEnrico Granata 
16276e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1628223383edSEnrico Granata 
1629*b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1630*b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
1631223383edSEnrico Granata       Error error;
16323bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1633223383edSEnrico Granata 
1634*b9c1b51eSKate Stone       switch (short_option) {
1635223383edSEnrico Granata       case 'f':
1636735152e3SEnrico Granata         if (option_arg)
1637735152e3SEnrico Granata           m_funct_name.assign(option_arg);
1638735152e3SEnrico Granata         break;
16399fe00e52SEnrico Granata       case 'c':
16409fe00e52SEnrico Granata         if (option_arg)
16419fe00e52SEnrico Granata           m_class_name.assign(option_arg);
16429fe00e52SEnrico Granata         break;
1643735152e3SEnrico Granata       case 'h':
1644735152e3SEnrico Granata         if (option_arg)
1645735152e3SEnrico Granata           m_short_help.assign(option_arg);
1646223383edSEnrico Granata         break;
16470a305db7SEnrico Granata       case 's':
1648*b9c1b51eSKate Stone         m_synchronicity =
1649*b9c1b51eSKate Stone             (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
1650*b9c1b51eSKate Stone                 option_arg, g_option_table[option_idx].enum_values, 0, error);
16510a305db7SEnrico Granata         if (!error.Success())
1652*b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1653*b9c1b51eSKate Stone               "unrecognized value for synchronicity '%s'", option_arg);
16540a305db7SEnrico Granata         break;
1655223383edSEnrico Granata       default:
1656*b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1657*b9c1b51eSKate Stone                                        short_option);
1658223383edSEnrico Granata         break;
1659223383edSEnrico Granata       }
1660223383edSEnrico Granata 
1661223383edSEnrico Granata       return error;
1662223383edSEnrico Granata     }
1663223383edSEnrico Granata 
1664*b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
16659fe00e52SEnrico Granata       m_class_name.clear();
1666735152e3SEnrico Granata       m_funct_name.clear();
1667735152e3SEnrico Granata       m_short_help.clear();
166844d93782SGreg Clayton       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1669223383edSEnrico Granata     }
1670223383edSEnrico Granata 
1671*b9c1b51eSKate Stone     const OptionDefinition *GetDefinitions() override { return g_option_table; }
1672223383edSEnrico Granata 
1673223383edSEnrico Granata     // Options table: Required for subclasses of Options.
1674223383edSEnrico Granata 
1675223383edSEnrico Granata     static OptionDefinition g_option_table[];
1676223383edSEnrico Granata 
1677223383edSEnrico Granata     // Instance variables to hold the values for command options.
1678223383edSEnrico Granata 
16799fe00e52SEnrico Granata     std::string m_class_name;
1680223383edSEnrico Granata     std::string m_funct_name;
1681735152e3SEnrico Granata     std::string m_short_help;
168244d93782SGreg Clayton     ScriptedCommandSynchronicity m_synchronicity;
1683223383edSEnrico Granata   };
1684223383edSEnrico Granata 
1685*b9c1b51eSKate Stone   void IOHandlerActivated(IOHandler &io_handler) override {
168644d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1687*b9c1b51eSKate Stone     if (output_sp) {
168844d93782SGreg Clayton       output_sp->PutCString(g_python_command_instructions);
168944d93782SGreg Clayton       output_sp->Flush();
1690223383edSEnrico Granata     }
1691223383edSEnrico Granata   }
1692223383edSEnrico Granata 
1693*b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1694*b9c1b51eSKate Stone                               std::string &data) override {
169544d93782SGreg Clayton     StreamFileSP error_sp = io_handler.GetErrorStreamFile();
169644d93782SGreg Clayton 
169744d93782SGreg Clayton     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1698*b9c1b51eSKate Stone     if (interpreter) {
169944d93782SGreg Clayton 
170044d93782SGreg Clayton       StringList lines;
170144d93782SGreg Clayton       lines.SplitIntoLines(data);
1702*b9c1b51eSKate Stone       if (lines.GetSize() > 0) {
1703a73b7df7SEnrico Granata         std::string funct_name_str;
1704*b9c1b51eSKate Stone         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1705*b9c1b51eSKate Stone           if (funct_name_str.empty()) {
1706*b9c1b51eSKate Stone             error_sp->Printf("error: unable to obtain a function name, didn't "
1707*b9c1b51eSKate Stone                              "add python command.\n");
170844d93782SGreg Clayton             error_sp->Flush();
1709*b9c1b51eSKate Stone           } else {
1710223383edSEnrico Granata             // everything should be fine now, let's add this alias
1711223383edSEnrico Granata 
1712*b9c1b51eSKate Stone             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1713*b9c1b51eSKate Stone                 m_interpreter, m_cmd_name, funct_name_str.c_str(), m_short_help,
171444d93782SGreg Clayton                 m_synchronicity));
1715223383edSEnrico Granata 
1716*b9c1b51eSKate Stone             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1717*b9c1b51eSKate Stone                                               true)) {
1718*b9c1b51eSKate Stone               error_sp->Printf("error: unable to add selected command, didn't "
1719*b9c1b51eSKate Stone                                "add python command.\n");
172044d93782SGreg Clayton               error_sp->Flush();
1721223383edSEnrico Granata             }
1722223383edSEnrico Granata           }
1723*b9c1b51eSKate Stone         } else {
1724*b9c1b51eSKate Stone           error_sp->Printf(
1725*b9c1b51eSKate Stone               "error: unable to create function, didn't add python command.\n");
172644d93782SGreg Clayton           error_sp->Flush();
172744d93782SGreg Clayton         }
1728*b9c1b51eSKate Stone       } else {
172944d93782SGreg Clayton         error_sp->Printf("error: empty function, didn't add python command.\n");
173044d93782SGreg Clayton         error_sp->Flush();
173144d93782SGreg Clayton       }
1732*b9c1b51eSKate Stone     } else {
1733*b9c1b51eSKate Stone       error_sp->Printf(
1734*b9c1b51eSKate Stone           "error: script interpreter missing, didn't add python command.\n");
173544d93782SGreg Clayton       error_sp->Flush();
173644d93782SGreg Clayton     }
173744d93782SGreg Clayton 
173844d93782SGreg Clayton     io_handler.SetIsDone(true);
173944d93782SGreg Clayton   }
1740223383edSEnrico Granata 
17415a988416SJim Ingham protected:
1742*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1743*b9c1b51eSKate Stone     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1744*b9c1b51eSKate Stone         lldb::eScriptLanguagePython) {
1745*b9c1b51eSKate Stone       result.AppendError("only scripting language supported for scripted "
1746*b9c1b51eSKate Stone                          "commands is currently Python");
174799f0b8f9SEnrico Granata       result.SetStatus(eReturnStatusFailed);
174899f0b8f9SEnrico Granata       return false;
174999f0b8f9SEnrico Granata     }
175099f0b8f9SEnrico Granata 
17515a988416SJim Ingham     size_t argc = command.GetArgumentCount();
1752223383edSEnrico Granata 
1753*b9c1b51eSKate Stone     if (argc != 1) {
1754223383edSEnrico Granata       result.AppendError("'command script add' requires one argument");
1755223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1756223383edSEnrico Granata       return false;
1757223383edSEnrico Granata     }
1758223383edSEnrico Granata 
1759735152e3SEnrico Granata     // Store the options in case we get multi-line input
176044d93782SGreg Clayton     m_cmd_name = command.GetArgumentAtIndex(0);
1761735152e3SEnrico Granata     m_short_help.assign(m_options.m_short_help);
176244d93782SGreg Clayton     m_synchronicity = m_options.m_synchronicity;
1763223383edSEnrico Granata 
1764*b9c1b51eSKate Stone     if (m_options.m_class_name.empty()) {
1765*b9c1b51eSKate Stone       if (m_options.m_funct_name.empty()) {
1766*b9c1b51eSKate Stone         m_interpreter.GetPythonCommandsFromIOHandler(
1767*b9c1b51eSKate Stone             "     ",  // Prompt
176844d93782SGreg Clayton             *this,    // IOHandlerDelegate
176944d93782SGreg Clayton             true,     // Run IOHandler in async mode
1770*b9c1b51eSKate Stone             nullptr); // Baton for the "io_handler" that will be passed back
1771*b9c1b51eSKate Stone                       // into our IOHandlerDelegate functions
1772*b9c1b51eSKate Stone       } else {
1773*b9c1b51eSKate Stone         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1774*b9c1b51eSKate Stone             m_interpreter, m_cmd_name, m_options.m_funct_name,
1775*b9c1b51eSKate Stone             m_options.m_short_help, m_synchronicity));
1776*b9c1b51eSKate Stone         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1777223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1778*b9c1b51eSKate Stone         } else {
1779223383edSEnrico Granata           result.AppendError("cannot add command");
1780223383edSEnrico Granata           result.SetStatus(eReturnStatusFailed);
1781223383edSEnrico Granata         }
1782223383edSEnrico Granata       }
1783*b9c1b51eSKate Stone     } else {
1784*b9c1b51eSKate Stone       ScriptInterpreter *interpreter =
1785*b9c1b51eSKate Stone           GetCommandInterpreter().GetScriptInterpreter();
1786*b9c1b51eSKate Stone       if (!interpreter) {
17879fe00e52SEnrico Granata         result.AppendError("cannot find ScriptInterpreter");
17889fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17899fe00e52SEnrico Granata         return false;
17909fe00e52SEnrico Granata       }
17919fe00e52SEnrico Granata 
1792*b9c1b51eSKate Stone       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1793*b9c1b51eSKate Stone           m_options.m_class_name.c_str());
1794*b9c1b51eSKate Stone       if (!cmd_obj_sp) {
17959fe00e52SEnrico Granata         result.AppendError("cannot create helper object");
17969fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17979fe00e52SEnrico Granata         return false;
17989fe00e52SEnrico Granata       }
17999fe00e52SEnrico Granata 
1800*b9c1b51eSKate Stone       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1801*b9c1b51eSKate Stone           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1802*b9c1b51eSKate Stone       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
18039fe00e52SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1804*b9c1b51eSKate Stone       } else {
18059fe00e52SEnrico Granata         result.AppendError("cannot add command");
18069fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
18079fe00e52SEnrico Granata       }
18089fe00e52SEnrico Granata     }
1809223383edSEnrico Granata 
1810223383edSEnrico Granata     return result.Succeeded();
1811223383edSEnrico Granata   }
18125a988416SJim Ingham 
18135a988416SJim Ingham   CommandOptions m_options;
181444d93782SGreg Clayton   std::string m_cmd_name;
1815735152e3SEnrico Granata   std::string m_short_help;
181644d93782SGreg Clayton   ScriptedCommandSynchronicity m_synchronicity;
1817223383edSEnrico Granata };
1818223383edSEnrico Granata 
1819*b9c1b51eSKate Stone static OptionEnumValueElement g_script_synchro_type[] = {
1820*b9c1b51eSKate Stone     {eScriptedCommandSynchronicitySynchronous, "synchronous",
1821*b9c1b51eSKate Stone      "Run synchronous"},
1822*b9c1b51eSKate Stone     {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1823*b9c1b51eSKate Stone      "Run asynchronous"},
1824*b9c1b51eSKate Stone     {eScriptedCommandSynchronicityCurrentValue, "current",
1825*b9c1b51eSKate Stone      "Do not alter current setting"},
1826*b9c1b51eSKate Stone     {0, nullptr, nullptr}};
18270a305db7SEnrico Granata 
1828223383edSEnrico Granata OptionDefinition
1829*b9c1b51eSKate Stone     CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = {
1830ac9c3a62SKate Stone         // clang-format off
18316e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1,   false, "function",      'f', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypePythonFunction,               "Name of the Python function to bind to this command name."},
18326e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_2,   false, "class",         'c', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypePythonClass,                  "Name of the Python class to bind to this command name."},
18336e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_1,   false, "help"  ,        'h', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypeHelpText,                     "The help text to display for this command."},
18346e3d8e7fSEugene Zelenko   {LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."},
18356e3d8e7fSEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
1836ac9c3a62SKate Stone         // clang-format on
1837223383edSEnrico Granata };
1838223383edSEnrico Granata 
1839223383edSEnrico Granata //-------------------------------------------------------------------------
1840223383edSEnrico Granata // CommandObjectCommandsScriptList
1841223383edSEnrico Granata //-------------------------------------------------------------------------
1842223383edSEnrico Granata 
1843*b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed {
1844223383edSEnrico Granata public:
1845*b9c1b51eSKate Stone   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1846*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script list",
1847*b9c1b51eSKate Stone                             "List defined scripted commands.", nullptr) {}
1848223383edSEnrico Granata 
18496e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptList() override = default;
1850223383edSEnrico Granata 
1851*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1852*b9c1b51eSKate Stone     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1853223383edSEnrico Granata 
1854223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1855223383edSEnrico Granata 
1856223383edSEnrico Granata     return true;
1857223383edSEnrico Granata   }
1858223383edSEnrico Granata };
1859223383edSEnrico Granata 
1860223383edSEnrico Granata //-------------------------------------------------------------------------
1861223383edSEnrico Granata // CommandObjectCommandsScriptClear
1862223383edSEnrico Granata //-------------------------------------------------------------------------
1863223383edSEnrico Granata 
1864*b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1865223383edSEnrico Granata public:
1866*b9c1b51eSKate Stone   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1867*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script clear",
1868*b9c1b51eSKate Stone                             "Delete all scripted commands.", nullptr) {}
1869223383edSEnrico Granata 
18706e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptClear() override = default;
1871223383edSEnrico Granata 
18725a988416SJim Ingham protected:
1873*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1874223383edSEnrico Granata     m_interpreter.RemoveAllUser();
1875223383edSEnrico Granata 
1876223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1877223383edSEnrico Granata 
1878223383edSEnrico Granata     return true;
1879223383edSEnrico Granata   }
1880223383edSEnrico Granata };
1881223383edSEnrico Granata 
1882223383edSEnrico Granata //-------------------------------------------------------------------------
1883223383edSEnrico Granata // CommandObjectCommandsScriptDelete
1884223383edSEnrico Granata //-------------------------------------------------------------------------
1885223383edSEnrico Granata 
1886*b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1887223383edSEnrico Granata public:
1888*b9c1b51eSKate Stone   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1889*b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script delete",
1890*b9c1b51eSKate Stone                             "Delete a scripted command.", nullptr) {
1891223383edSEnrico Granata     CommandArgumentEntry arg1;
1892223383edSEnrico Granata     CommandArgumentData cmd_arg;
1893223383edSEnrico Granata 
1894223383edSEnrico Granata     // Define the first (and only) variant of this arg.
1895223383edSEnrico Granata     cmd_arg.arg_type = eArgTypeCommandName;
1896223383edSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlain;
1897223383edSEnrico Granata 
1898*b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1899*b9c1b51eSKate Stone     // argument entry.
1900223383edSEnrico Granata     arg1.push_back(cmd_arg);
1901223383edSEnrico Granata 
1902223383edSEnrico Granata     // Push the data for the first argument into the m_arguments vector.
1903223383edSEnrico Granata     m_arguments.push_back(arg1);
1904223383edSEnrico Granata   }
1905223383edSEnrico Granata 
19066e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptDelete() override = default;
1907223383edSEnrico Granata 
19085a988416SJim Ingham protected:
1909*b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1910223383edSEnrico Granata 
19115a988416SJim Ingham     size_t argc = command.GetArgumentCount();
1912223383edSEnrico Granata 
1913*b9c1b51eSKate Stone     if (argc != 1) {
1914223383edSEnrico Granata       result.AppendError("'command script delete' requires one argument");
1915223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1916223383edSEnrico Granata       return false;
1917223383edSEnrico Granata     }
1918223383edSEnrico Granata 
19195a988416SJim Ingham     const char *cmd_name = command.GetArgumentAtIndex(0);
1920223383edSEnrico Granata 
1921*b9c1b51eSKate Stone     if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() &&
1922*b9c1b51eSKate Stone         m_interpreter.UserCommandExists(cmd_name)) {
1923223383edSEnrico Granata       m_interpreter.RemoveUser(cmd_name);
1924223383edSEnrico Granata       result.SetStatus(eReturnStatusSuccessFinishResult);
1925*b9c1b51eSKate Stone     } else {
1926223383edSEnrico Granata       result.AppendErrorWithFormat("command %s not found", cmd_name);
1927223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1928223383edSEnrico Granata     }
1929223383edSEnrico Granata 
1930223383edSEnrico Granata     return result.Succeeded();
1931223383edSEnrico Granata   }
1932223383edSEnrico Granata };
1933223383edSEnrico Granata 
1934223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript
1935223383edSEnrico Granata 
1936223383edSEnrico Granata //-------------------------------------------------------------------------
1937223383edSEnrico Granata // CommandObjectMultiwordCommandsScript
1938223383edSEnrico Granata //-------------------------------------------------------------------------
1939223383edSEnrico Granata 
1940*b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1941223383edSEnrico Granata public:
19427428a18cSKate Stone   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1943*b9c1b51eSKate Stone       : CommandObjectMultiword(
1944*b9c1b51eSKate Stone             interpreter, "command script", "Commands for managing custom "
1945*b9c1b51eSKate Stone                                            "commands implemented by "
1946*b9c1b51eSKate Stone                                            "interpreter scripts.",
1947*b9c1b51eSKate Stone             "command script <subcommand> [<subcommand-options>]") {
1948*b9c1b51eSKate Stone     LoadSubCommand("add", CommandObjectSP(
1949*b9c1b51eSKate Stone                               new CommandObjectCommandsScriptAdd(interpreter)));
1950*b9c1b51eSKate Stone     LoadSubCommand(
1951*b9c1b51eSKate Stone         "delete",
1952*b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1953*b9c1b51eSKate Stone     LoadSubCommand(
1954*b9c1b51eSKate Stone         "clear",
1955*b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1956*b9c1b51eSKate Stone     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1957*b9c1b51eSKate Stone                                interpreter)));
1958*b9c1b51eSKate Stone     LoadSubCommand(
1959*b9c1b51eSKate Stone         "import",
1960*b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1961223383edSEnrico Granata   }
1962223383edSEnrico Granata 
19636e3d8e7fSEugene Zelenko   ~CommandObjectMultiwordCommandsScript() override = default;
1964223383edSEnrico Granata };
1965223383edSEnrico Granata 
1966ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
1967ebc09c36SJim Ingham 
1968ebc09c36SJim Ingham //-------------------------------------------------------------------------
1969ebc09c36SJim Ingham // CommandObjectMultiwordCommands
1970ebc09c36SJim Ingham //-------------------------------------------------------------------------
1971ebc09c36SJim Ingham 
1972*b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1973*b9c1b51eSKate Stone     CommandInterpreter &interpreter)
1974*b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "command",
1975*b9c1b51eSKate Stone                              "Commands for managing custom LLDB commands.",
1976*b9c1b51eSKate Stone                              "command <subcommand> [<subcommand-options>]") {
1977*b9c1b51eSKate Stone   LoadSubCommand("source",
1978*b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1979*b9c1b51eSKate Stone   LoadSubCommand("alias",
1980*b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1981*b9c1b51eSKate Stone   LoadSubCommand("unalias", CommandObjectSP(
1982*b9c1b51eSKate Stone                                 new CommandObjectCommandsUnalias(interpreter)));
1983*b9c1b51eSKate Stone   LoadSubCommand("delete",
1984*b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1985*b9c1b51eSKate Stone   LoadSubCommand(
1986*b9c1b51eSKate Stone       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1987*b9c1b51eSKate Stone   LoadSubCommand("history", CommandObjectSP(
1988*b9c1b51eSKate Stone                                 new CommandObjectCommandsHistory(interpreter)));
1989*b9c1b51eSKate Stone   LoadSubCommand(
1990*b9c1b51eSKate Stone       "script",
1991*b9c1b51eSKate Stone       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1992ebc09c36SJim Ingham }
1993ebc09c36SJim Ingham 
19946e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1995