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*1f0f5b5bSZachary Turner static OptionDefinition g_history_options[] = {
40*1f0f5b5bSZachary Turner     // clang-format off
41*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "count",       'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
42*1f0f5b5bSZachary Turner   { 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)." },
43*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "end-index",   'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
44*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_2, false, "clear",       'C', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeBoolean,         "Clears the current command history." },
45*1f0f5b5bSZachary Turner     // clang-format on
46*1f0f5b5bSZachary Turner };
47*1f0f5b5bSZachary Turner 
48b9c1b51eSKate Stone class CommandObjectCommandsHistory : public CommandObjectParsed {
495a988416SJim Ingham public:
50b9c1b51eSKate Stone   CommandObjectCommandsHistory(CommandInterpreter &interpreter)
51b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command history",
525a988416SJim Ingham                             "Dump the history of commands in this session.",
536e3d8e7fSEugene Zelenko                             nullptr),
54b9c1b51eSKate Stone         m_options() {}
555a988416SJim Ingham 
566e3d8e7fSEugene Zelenko   ~CommandObjectCommandsHistory() override = default;
575a988416SJim Ingham 
58b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
595a988416SJim Ingham 
605a988416SJim Ingham protected:
61b9c1b51eSKate Stone   class CommandOptions : public Options {
62a5a97ebeSJim Ingham   public:
63b9c1b51eSKate Stone     CommandOptions()
64b9c1b51eSKate Stone         : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
65a5a97ebeSJim Ingham     }
66a5a97ebeSJim Ingham 
676e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
68a5a97ebeSJim Ingham 
69b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
70b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
71a5a97ebeSJim Ingham       Error error;
723bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
73a5a97ebeSJim Ingham 
74b9c1b51eSKate Stone       switch (short_option) {
75a5a97ebeSJim Ingham       case 'c':
76c95f7e2aSPavel Labath         error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
77a5a97ebeSJim Ingham         break;
78a5a97ebeSJim Ingham       case 's':
79b9c1b51eSKate Stone         if (option_arg && strcmp("end", option_arg) == 0) {
807594f14fSEnrico Granata           m_start_idx.SetCurrentValue(UINT64_MAX);
817594f14fSEnrico Granata           m_start_idx.SetOptionWasSet();
82b9c1b51eSKate Stone         } else
83b9c1b51eSKate Stone           error = m_start_idx.SetValueFromString(option_arg,
84b9c1b51eSKate Stone                                                  eVarSetOperationAssign);
857594f14fSEnrico Granata         break;
867594f14fSEnrico Granata       case 'e':
87b9c1b51eSKate Stone         error =
88b9c1b51eSKate Stone             m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
897594f14fSEnrico Granata         break;
9063123b64SEnrico Granata       case 'C':
9163123b64SEnrico Granata         m_clear.SetCurrentValue(true);
9263123b64SEnrico Granata         m_clear.SetOptionWasSet();
93a5a97ebeSJim Ingham         break;
94a5a97ebeSJim Ingham       default:
95b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
96b9c1b51eSKate Stone                                        short_option);
97a5a97ebeSJim Ingham         break;
98a5a97ebeSJim Ingham       }
99a5a97ebeSJim Ingham 
100a5a97ebeSJim Ingham       return error;
101a5a97ebeSJim Ingham     }
102a5a97ebeSJim Ingham 
103b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1047594f14fSEnrico Granata       m_start_idx.Clear();
1057594f14fSEnrico Granata       m_stop_idx.Clear();
1067594f14fSEnrico Granata       m_count.Clear();
10763123b64SEnrico Granata       m_clear.Clear();
108a5a97ebeSJim Ingham     }
109a5a97ebeSJim Ingham 
110*1f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
111*1f0f5b5bSZachary Turner       return g_history_options;
112*1f0f5b5bSZachary Turner     }
113a5a97ebeSJim Ingham 
114a5a97ebeSJim Ingham     // Instance variables to hold the values for command options.
115a5a97ebeSJim Ingham 
1167594f14fSEnrico Granata     OptionValueUInt64 m_start_idx;
1177594f14fSEnrico Granata     OptionValueUInt64 m_stop_idx;
1187594f14fSEnrico Granata     OptionValueUInt64 m_count;
11963123b64SEnrico Granata     OptionValueBoolean m_clear;
120a5a97ebeSJim Ingham   };
121a5a97ebeSJim Ingham 
122b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
123b9c1b51eSKate Stone     if (m_options.m_clear.GetCurrentValue() &&
124b9c1b51eSKate Stone         m_options.m_clear.OptionWasSet()) {
1257594f14fSEnrico Granata       m_interpreter.GetCommandHistory().Clear();
1267594f14fSEnrico Granata       result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
127b9c1b51eSKate Stone     } else {
128b9c1b51eSKate Stone       if (m_options.m_start_idx.OptionWasSet() &&
129b9c1b51eSKate Stone           m_options.m_stop_idx.OptionWasSet() &&
130b9c1b51eSKate Stone           m_options.m_count.OptionWasSet()) {
131b9c1b51eSKate Stone         result.AppendError("--count, --start-index and --end-index cannot be "
132b9c1b51eSKate Stone                            "all specified in the same invocation");
1337594f14fSEnrico Granata         result.SetStatus(lldb::eReturnStatusFailed);
134b9c1b51eSKate Stone       } else {
135b9c1b51eSKate Stone         std::pair<bool, uint64_t> start_idx(
136b9c1b51eSKate Stone             m_options.m_start_idx.OptionWasSet(),
137b9c1b51eSKate Stone             m_options.m_start_idx.GetCurrentValue());
138b9c1b51eSKate Stone         std::pair<bool, uint64_t> stop_idx(
139b9c1b51eSKate Stone             m_options.m_stop_idx.OptionWasSet(),
140b9c1b51eSKate Stone             m_options.m_stop_idx.GetCurrentValue());
141b9c1b51eSKate Stone         std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
142b9c1b51eSKate Stone                                         m_options.m_count.GetCurrentValue());
143a5a97ebeSJim Ingham 
1447594f14fSEnrico Granata         const CommandHistory &history(m_interpreter.GetCommandHistory());
1457594f14fSEnrico Granata 
146b9c1b51eSKate Stone         if (start_idx.first && start_idx.second == UINT64_MAX) {
147b9c1b51eSKate Stone           if (count.first) {
1487594f14fSEnrico Granata             start_idx.second = history.GetSize() - count.second;
1497594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
150b9c1b51eSKate Stone           } else if (stop_idx.first) {
1517594f14fSEnrico Granata             start_idx.second = stop_idx.second;
1527594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
153b9c1b51eSKate Stone           } else {
1547594f14fSEnrico Granata             start_idx.second = 0;
1557594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
1567594f14fSEnrico Granata           }
157b9c1b51eSKate Stone         } else {
158b9c1b51eSKate Stone           if (!start_idx.first && !stop_idx.first && !count.first) {
1597594f14fSEnrico Granata             start_idx.second = 0;
1607594f14fSEnrico Granata             stop_idx.second = history.GetSize() - 1;
161b9c1b51eSKate Stone           } else if (start_idx.first) {
162b9c1b51eSKate Stone             if (count.first) {
1637594f14fSEnrico Granata               stop_idx.second = start_idx.second + count.second - 1;
164b9c1b51eSKate Stone             } else if (!stop_idx.first) {
1657594f14fSEnrico Granata               stop_idx.second = history.GetSize() - 1;
1667594f14fSEnrico Granata             }
167b9c1b51eSKate Stone           } else if (stop_idx.first) {
168b9c1b51eSKate Stone             if (count.first) {
1697594f14fSEnrico Granata               if (stop_idx.second >= count.second)
1707594f14fSEnrico Granata                 start_idx.second = stop_idx.second - count.second + 1;
1717594f14fSEnrico Granata               else
1727594f14fSEnrico Granata                 start_idx.second = 0;
1737594f14fSEnrico Granata             }
174b9c1b51eSKate Stone           } else /* if (count.first) */
1757594f14fSEnrico Granata           {
1767594f14fSEnrico Granata             start_idx.second = 0;
1777594f14fSEnrico Granata             stop_idx.second = count.second - 1;
1787594f14fSEnrico Granata           }
1797594f14fSEnrico Granata         }
180b9c1b51eSKate Stone         history.Dump(result.GetOutputStream(), start_idx.second,
181b9c1b51eSKate Stone                      stop_idx.second);
1827594f14fSEnrico Granata       }
1837594f14fSEnrico Granata     }
184a5a97ebeSJim Ingham     return result.Succeeded();
185a5a97ebeSJim Ingham   }
1865a988416SJim Ingham 
1875a988416SJim Ingham   CommandOptions m_options;
188a5a97ebeSJim Ingham };
189a5a97ebeSJim Ingham 
190a5a97ebeSJim Ingham //-------------------------------------------------------------------------
191a5a97ebeSJim Ingham // CommandObjectCommandsSource
192a5a97ebeSJim Ingham //-------------------------------------------------------------------------
193a5a97ebeSJim Ingham 
194*1f0f5b5bSZachary Turner static OptionDefinition g_source_options[] = {
195*1f0f5b5bSZachary Turner     // clang-format off
196*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "stop-on-error",    'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
197*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
198*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "silent-run",       's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
199*1f0f5b5bSZachary Turner     // clang-format on
200*1f0f5b5bSZachary Turner };
201*1f0f5b5bSZachary Turner 
202b9c1b51eSKate Stone class CommandObjectCommandsSource : public CommandObjectParsed {
2035a988416SJim Ingham public:
2047428a18cSKate Stone   CommandObjectCommandsSource(CommandInterpreter &interpreter)
205b9c1b51eSKate Stone       : CommandObjectParsed(
206b9c1b51eSKate Stone             interpreter, "command source",
207b9c1b51eSKate Stone             "Read and execute LLDB commands from the file <filename>.",
2086e3d8e7fSEugene Zelenko             nullptr),
209b9c1b51eSKate Stone         m_options() {
2105a988416SJim Ingham     CommandArgumentEntry arg;
2115a988416SJim Ingham     CommandArgumentData file_arg;
2125a988416SJim Ingham 
2135a988416SJim Ingham     // Define the first (and only) variant of this arg.
2145a988416SJim Ingham     file_arg.arg_type = eArgTypeFilename;
2155a988416SJim Ingham     file_arg.arg_repetition = eArgRepeatPlain;
2165a988416SJim Ingham 
217b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
218b9c1b51eSKate Stone     // argument entry.
2195a988416SJim Ingham     arg.push_back(file_arg);
2205a988416SJim Ingham 
2215a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
2225a988416SJim Ingham     m_arguments.push_back(arg);
2235a988416SJim Ingham   }
2245a988416SJim Ingham 
2256e3d8e7fSEugene Zelenko   ~CommandObjectCommandsSource() override = default;
2265a988416SJim Ingham 
227b9c1b51eSKate Stone   const char *GetRepeatCommand(Args &current_command_args,
228b9c1b51eSKate Stone                                uint32_t index) override {
2295a988416SJim Ingham     return "";
2305a988416SJim Ingham   }
2315a988416SJim Ingham 
232b9c1b51eSKate Stone   int HandleArgumentCompletion(Args &input, int &cursor_index,
2335a988416SJim Ingham                                int &cursor_char_position,
2345a988416SJim Ingham                                OptionElementVector &opt_element_vector,
235b9c1b51eSKate Stone                                int match_start_point, int max_return_elements,
2365a988416SJim Ingham                                bool &word_complete,
237b9c1b51eSKate Stone                                StringList &matches) override {
2385a988416SJim Ingham     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
2395a988416SJim Ingham     completion_str.erase(cursor_char_position);
2405a988416SJim Ingham 
241b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
242b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
243b9c1b51eSKate Stone         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
244b9c1b51eSKate Stone         word_complete, matches);
2455a988416SJim Ingham     return matches.GetSize();
2465a988416SJim Ingham   }
2475a988416SJim Ingham 
248b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
2495a988416SJim Ingham 
2505a988416SJim Ingham protected:
251b9c1b51eSKate Stone   class CommandOptions : public Options {
252e16c50a1SJim Ingham   public:
253b9c1b51eSKate Stone     CommandOptions()
254b9c1b51eSKate Stone         : Options(), m_stop_on_error(true), m_silent_run(false),
255b9c1b51eSKate Stone           m_stop_on_continue(true) {}
256e16c50a1SJim Ingham 
2576e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
258e16c50a1SJim Ingham 
259b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
260b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
261e16c50a1SJim Ingham       Error error;
2623bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
263e16c50a1SJim Ingham 
264b9c1b51eSKate Stone       switch (short_option) {
265e16c50a1SJim Ingham       case 'e':
266c95f7e2aSPavel Labath         error = m_stop_on_error.SetValueFromString(option_arg);
267e16c50a1SJim Ingham         break;
268340b0309SGreg Clayton 
269e16c50a1SJim Ingham       case 'c':
270c95f7e2aSPavel Labath         error = m_stop_on_continue.SetValueFromString(option_arg);
271e16c50a1SJim Ingham         break;
272340b0309SGreg Clayton 
27360986174SMichael Sartain       case 's':
274c95f7e2aSPavel Labath         error = m_silent_run.SetValueFromString(option_arg);
27560986174SMichael Sartain         break;
276340b0309SGreg Clayton 
277e16c50a1SJim Ingham       default:
278b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
279b9c1b51eSKate Stone                                        short_option);
280e16c50a1SJim Ingham         break;
281e16c50a1SJim Ingham       }
282e16c50a1SJim Ingham 
283e16c50a1SJim Ingham       return error;
284e16c50a1SJim Ingham     }
285e16c50a1SJim Ingham 
286b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
287012d4fcaSEnrico Granata       m_stop_on_error.Clear();
288340b0309SGreg Clayton       m_silent_run.Clear();
289340b0309SGreg Clayton       m_stop_on_continue.Clear();
290e16c50a1SJim Ingham     }
291e16c50a1SJim Ingham 
292*1f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
293*1f0f5b5bSZachary Turner       return g_source_options;
294*1f0f5b5bSZachary Turner     }
295e16c50a1SJim Ingham 
296e16c50a1SJim Ingham     // Instance variables to hold the values for command options.
297e16c50a1SJim Ingham 
298012d4fcaSEnrico Granata     OptionValueBoolean m_stop_on_error;
299340b0309SGreg Clayton     OptionValueBoolean m_silent_run;
300340b0309SGreg Clayton     OptionValueBoolean m_stop_on_continue;
301e16c50a1SJim Ingham   };
302e16c50a1SJim Ingham 
303b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
304c7bece56SGreg Clayton     const size_t argc = command.GetArgumentCount();
305b9c1b51eSKate Stone     if (argc == 1) {
3065a988416SJim Ingham       const char *filename = command.GetArgumentAtIndex(0);
307ebc09c36SJim Ingham 
3081ee3853fSJohnny Chen       FileSpec cmd_file(filename, true);
3096e3d8e7fSEugene Zelenko       ExecutionContext *exe_ctx = nullptr; // Just use the default context.
310ebc09c36SJim Ingham 
311340b0309SGreg Clayton       // If any options were set, then use them
312340b0309SGreg Clayton       if (m_options.m_stop_on_error.OptionWasSet() ||
313340b0309SGreg Clayton           m_options.m_silent_run.OptionWasSet() ||
314b9c1b51eSKate Stone           m_options.m_stop_on_continue.OptionWasSet()) {
315340b0309SGreg Clayton         // Use user set settings
31626c7bf93SJim Ingham         CommandInterpreterRunOptions options;
317b9c1b51eSKate Stone         options.SetStopOnContinue(
318b9c1b51eSKate Stone             m_options.m_stop_on_continue.GetCurrentValue());
31926c7bf93SJim Ingham         options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
3207d8555c4SJim Ingham         options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
3217d8555c4SJim Ingham         options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
32226c7bf93SJim Ingham 
323b9c1b51eSKate Stone         m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
324e16c50a1SJim Ingham                                              result);
325b9c1b51eSKate Stone       } else {
326b9c1b51eSKate Stone         // No options were set, inherit any settings from nested "command
327b9c1b51eSKate Stone         // source" commands,
328340b0309SGreg Clayton         // or set to sane default settings...
32926c7bf93SJim Ingham         CommandInterpreterRunOptions options;
330b9c1b51eSKate Stone         m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
331340b0309SGreg Clayton                                              result);
332340b0309SGreg Clayton       }
333b9c1b51eSKate Stone     } else {
334b9c1b51eSKate Stone       result.AppendErrorWithFormat(
335b9c1b51eSKate Stone           "'%s' takes exactly one executable filename argument.\n",
336b9c1b51eSKate Stone           GetCommandName());
337ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
338ebc09c36SJim Ingham     }
339ebc09c36SJim Ingham     return result.Succeeded();
340ebc09c36SJim Ingham   }
3416e3d8e7fSEugene Zelenko 
3425a988416SJim Ingham   CommandOptions m_options;
343ebc09c36SJim Ingham };
344ebc09c36SJim Ingham 
345ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
346ebc09c36SJim Ingham //-------------------------------------------------------------------------
347ebc09c36SJim Ingham // CommandObjectCommandsAlias
348ebc09c36SJim Ingham //-------------------------------------------------------------------------
349ebc09c36SJim Ingham 
350*1f0f5b5bSZachary Turner static OptionDefinition g_alias_options[] = {
351*1f0f5b5bSZachary Turner     // clang-format off
352*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "help",      'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
353*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
354*1f0f5b5bSZachary Turner     // clang-format on
355*1f0f5b5bSZachary Turner };
356*1f0f5b5bSZachary Turner 
357b9c1b51eSKate Stone static const char *g_python_command_instructions =
358b9c1b51eSKate Stone     "Enter your Python command(s). Type 'DONE' to end.\n"
359be93a35aSEnrico Granata     "You must define a Python function with this signature:\n"
36044d93782SGreg Clayton     "def my_command_impl(debugger, args, result, internal_dict):\n";
361be93a35aSEnrico Granata 
362b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw {
36345d0e238SEnrico Granata protected:
364b9c1b51eSKate Stone   class CommandOptions : public OptionGroup {
365ebc09c36SJim Ingham   public:
366b9c1b51eSKate Stone     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
36745d0e238SEnrico Granata 
36845d0e238SEnrico Granata     ~CommandOptions() override = default;
36945d0e238SEnrico Granata 
370*1f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
371*1f0f5b5bSZachary Turner       return g_alias_options;
372*1f0f5b5bSZachary Turner     }
37345d0e238SEnrico Granata 
374b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_value,
375b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
37645d0e238SEnrico Granata       Error error;
37745d0e238SEnrico Granata 
378*1f0f5b5bSZachary Turner       const int short_option = GetDefinitions()[option_idx].short_option;
37945d0e238SEnrico Granata 
380b9c1b51eSKate Stone       switch (short_option) {
38145d0e238SEnrico Granata       case 'h':
38245d0e238SEnrico Granata         m_help.SetCurrentValue(option_value);
38345d0e238SEnrico Granata         m_help.SetOptionWasSet();
38445d0e238SEnrico Granata         break;
38545d0e238SEnrico Granata 
38645d0e238SEnrico Granata       case 'H':
38745d0e238SEnrico Granata         m_long_help.SetCurrentValue(option_value);
38845d0e238SEnrico Granata         m_long_help.SetOptionWasSet();
38945d0e238SEnrico Granata         break;
39045d0e238SEnrico Granata 
39145d0e238SEnrico Granata       default:
392b9c1b51eSKate Stone         error.SetErrorStringWithFormat("invalid short option character '%c'",
393b9c1b51eSKate Stone                                        short_option);
39445d0e238SEnrico Granata         break;
39545d0e238SEnrico Granata       }
39645d0e238SEnrico Granata 
39745d0e238SEnrico Granata       return error;
39845d0e238SEnrico Granata     }
39945d0e238SEnrico Granata 
400b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
40145d0e238SEnrico Granata       m_help.Clear();
40245d0e238SEnrico Granata       m_long_help.Clear();
40345d0e238SEnrico Granata     }
40445d0e238SEnrico Granata 
40545d0e238SEnrico Granata     OptionValueString m_help;
40645d0e238SEnrico Granata     OptionValueString m_long_help;
40745d0e238SEnrico Granata   };
40845d0e238SEnrico Granata 
40945d0e238SEnrico Granata   OptionGroupOptions m_option_group;
41045d0e238SEnrico Granata   CommandOptions m_command_options;
41145d0e238SEnrico Granata 
41245d0e238SEnrico Granata public:
413b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
41445d0e238SEnrico Granata 
4157428a18cSKate Stone   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
416b9c1b51eSKate Stone       : CommandObjectRaw(
417b9c1b51eSKate Stone             interpreter, "command alias",
418b9c1b51eSKate Stone             "Define a custom command in terms of an existing command.",
41945d0e238SEnrico Granata             nullptr),
420b9c1b51eSKate Stone         m_option_group(), m_command_options() {
42145d0e238SEnrico Granata     m_option_group.Append(&m_command_options);
42245d0e238SEnrico Granata     m_option_group.Finalize();
42345d0e238SEnrico Granata 
424ebc09c36SJim Ingham     SetHelpLong(
425ea671fbdSKate Stone         "'alias' allows the user to create a short-cut or abbreviation for long \
426ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options.  \
427b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:"
428b9c1b51eSKate Stone         R"(
429ea671fbdSKate Stone 
430ea671fbdSKate Stone (lldb) command alias sc script
431ea671fbdSKate Stone 
432ea671fbdSKate Stone     Creates the abbreviation 'sc' for the 'script' command.
433ea671fbdSKate Stone 
434ea671fbdSKate Stone (lldb) command alias bp breakpoint
435ea671fbdSKate Stone 
436b9c1b51eSKate Stone )"
437b9c1b51eSKate Stone         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
438ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \
439b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
440b9c1b51eSKate Stone         R"(
441ea671fbdSKate Stone 
442ea671fbdSKate Stone (lldb) command alias bpl breakpoint list
443ea671fbdSKate Stone 
444ea671fbdSKate Stone     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
445ea671fbdSKate Stone 
446b9c1b51eSKate Stone )"
447b9c1b51eSKate Stone         "An alias can include some options for the command, with the values either \
448ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \
449ea671fbdSKate Stone arguments, to be filled in when the alias is invoked.  The following example \
450b9c1b51eSKate Stone shows how to create aliases with options:"
451b9c1b51eSKate Stone         R"(
452ea671fbdSKate Stone 
453ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
454ea671fbdSKate Stone 
455b9c1b51eSKate Stone )"
456b9c1b51eSKate Stone         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
457ea671fbdSKate Stone options already part of the alias.  So if the user wants to set a breakpoint \
458ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \
459ea671fbdSKate Stone user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
460ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used.  \
461ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \
462ea671fbdSKate Stone occupies when the alias is used.  All the occurrences of '%1' in the alias \
463ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \
464ea671fbdSKate Stone alias will be replaced with the second argument, and so on.  This also allows \
465ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \
466b9c1b51eSKate Stone launch' example below)."
467b9c1b51eSKate Stone         R"(
468ea671fbdSKate Stone 
469b9c1b51eSKate Stone )"
470b9c1b51eSKate Stone         "Note: the positional arguments must substitute as whole words in the resultant \
471ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \
472b9c1b51eSKate Stone \".cpp\":"
473b9c1b51eSKate Stone         R"(
474ea671fbdSKate Stone 
475ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
476ea671fbdSKate Stone 
477b9c1b51eSKate Stone )"
478b9c1b51eSKate Stone         "For more complex aliasing, use the \"command regex\" command instead.  In the \
479ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \
480ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \
481b9c1b51eSKate Stone argument.  The user would use this alias as follows:"
482b9c1b51eSKate Stone         R"(
483ea671fbdSKate Stone 
484ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
485ea671fbdSKate Stone (lldb) bfl my-file.c 137
486ea671fbdSKate Stone 
487ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
488ea671fbdSKate Stone 
489ea671fbdSKate Stone Another example:
490ea671fbdSKate Stone 
491ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1
492ea671fbdSKate Stone (lldb) pltty /dev/tty0
493ea671fbdSKate Stone 
494ea671fbdSKate Stone     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
495ea671fbdSKate Stone 
496b9c1b51eSKate Stone )"
497b9c1b51eSKate Stone         "If the user always wanted to pass the same value to a particular option, the \
498ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \
499b9c1b51eSKate Stone rather than using a positional placeholder:"
500b9c1b51eSKate Stone         R"(
501ea671fbdSKate Stone 
502ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3
503ea671fbdSKate Stone 
504b9c1b51eSKate Stone     Always sets a breakpoint on line 3 of whatever file is indicated.)");
505ebc09c36SJim Ingham 
506405fe67fSCaroline Tice     CommandArgumentEntry arg1;
507405fe67fSCaroline Tice     CommandArgumentEntry arg2;
508405fe67fSCaroline Tice     CommandArgumentEntry arg3;
509405fe67fSCaroline Tice     CommandArgumentData alias_arg;
510405fe67fSCaroline Tice     CommandArgumentData cmd_arg;
511405fe67fSCaroline Tice     CommandArgumentData options_arg;
512405fe67fSCaroline Tice 
513405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
514405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
515405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
516405fe67fSCaroline Tice 
517b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
518b9c1b51eSKate Stone     // argument entry.
519405fe67fSCaroline Tice     arg1.push_back(alias_arg);
520405fe67fSCaroline Tice 
521405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
522405fe67fSCaroline Tice     cmd_arg.arg_type = eArgTypeCommandName;
523405fe67fSCaroline Tice     cmd_arg.arg_repetition = eArgRepeatPlain;
524405fe67fSCaroline Tice 
525b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
526b9c1b51eSKate Stone     // argument entry.
527405fe67fSCaroline Tice     arg2.push_back(cmd_arg);
528405fe67fSCaroline Tice 
529405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
530405fe67fSCaroline Tice     options_arg.arg_type = eArgTypeAliasOptions;
531405fe67fSCaroline Tice     options_arg.arg_repetition = eArgRepeatOptional;
532405fe67fSCaroline Tice 
533b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
534b9c1b51eSKate Stone     // argument entry.
535405fe67fSCaroline Tice     arg3.push_back(options_arg);
536405fe67fSCaroline Tice 
537405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
538405fe67fSCaroline Tice     m_arguments.push_back(arg1);
539405fe67fSCaroline Tice     m_arguments.push_back(arg2);
540405fe67fSCaroline Tice     m_arguments.push_back(arg3);
541ebc09c36SJim Ingham   }
542ebc09c36SJim Ingham 
5436e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAlias() override = default;
544ebc09c36SJim Ingham 
5455a988416SJim Ingham protected:
546b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
547b9c1b51eSKate Stone                  CommandReturnObject &result) override {
548b9c1b51eSKate Stone     if (!raw_command_line || !raw_command_line[0]) {
549d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
55045d0e238SEnrico Granata       return false;
55145d0e238SEnrico Granata     }
55245d0e238SEnrico Granata 
553e1cfbc79STodd Fiala     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
554e1cfbc79STodd Fiala     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
55545d0e238SEnrico Granata 
55645d0e238SEnrico Granata     const char *remainder = nullptr;
55745d0e238SEnrico Granata 
558b9c1b51eSKate Stone     if (raw_command_line[0] == '-') {
55945d0e238SEnrico Granata       // We have some options and these options MUST end with --.
56045d0e238SEnrico Granata       const char *end_options = nullptr;
56145d0e238SEnrico Granata       const char *s = raw_command_line;
562b9c1b51eSKate Stone       while (s && s[0]) {
56345d0e238SEnrico Granata         end_options = ::strstr(s, "--");
564b9c1b51eSKate Stone         if (end_options) {
56545d0e238SEnrico Granata           end_options += 2; // Get past the "--"
566b9c1b51eSKate Stone           if (::isspace(end_options[0])) {
56745d0e238SEnrico Granata             remainder = end_options;
56845d0e238SEnrico Granata             while (::isspace(*remainder))
56945d0e238SEnrico Granata               ++remainder;
57045d0e238SEnrico Granata             break;
57145d0e238SEnrico Granata           }
57245d0e238SEnrico Granata         }
57345d0e238SEnrico Granata         s = end_options;
57445d0e238SEnrico Granata       }
57545d0e238SEnrico Granata 
576b9c1b51eSKate Stone       if (end_options) {
577b9c1b51eSKate Stone         Args args(
578b9c1b51eSKate Stone             llvm::StringRef(raw_command_line, end_options - raw_command_line));
57945d0e238SEnrico Granata         if (!ParseOptions(args, result))
58045d0e238SEnrico Granata           return false;
58145d0e238SEnrico Granata 
582e1cfbc79STodd Fiala         Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
583b9c1b51eSKate Stone         if (error.Fail()) {
58445d0e238SEnrico Granata           result.AppendError(error.AsCString());
58545d0e238SEnrico Granata           result.SetStatus(eReturnStatusFailed);
58645d0e238SEnrico Granata           return false;
58745d0e238SEnrico Granata         }
58845d0e238SEnrico Granata       }
58945d0e238SEnrico Granata     }
59045d0e238SEnrico Granata     if (nullptr == remainder)
59145d0e238SEnrico Granata       remainder = raw_command_line;
59245d0e238SEnrico Granata 
59345d0e238SEnrico Granata     std::string raw_command_string(remainder);
59445d0e238SEnrico Granata     Args args(raw_command_string.c_str());
595844d2303SCaroline Tice 
596844d2303SCaroline Tice     size_t argc = args.GetArgumentCount();
597844d2303SCaroline Tice 
598b9c1b51eSKate Stone     if (argc < 2) {
599d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
600844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
601844d2303SCaroline Tice       return false;
602844d2303SCaroline Tice     }
603844d2303SCaroline Tice 
604844d2303SCaroline Tice     // Get the alias command.
605844d2303SCaroline Tice 
606844d2303SCaroline Tice     const std::string alias_command = args.GetArgumentAtIndex(0);
607b9c1b51eSKate Stone     if (alias_command.size() > 1 && alias_command[0] == '-') {
608d72e412fSEnrico Granata       result.AppendError("aliases starting with a dash are not supported");
609b9c1b51eSKate Stone       if (alias_command == "--help" || alias_command == "--long-help") {
610b9c1b51eSKate Stone         result.AppendWarning("if trying to pass options to 'command alias' add "
611b9c1b51eSKate Stone                              "a -- at the end of the options");
612d72e412fSEnrico Granata       }
613d72e412fSEnrico Granata       result.SetStatus(eReturnStatusFailed);
614d72e412fSEnrico Granata       return false;
615d72e412fSEnrico Granata     }
616844d2303SCaroline Tice 
617b9c1b51eSKate Stone     // Strip the new alias name off 'raw_command_string'  (leave it on args,
618b9c1b51eSKate Stone     // which gets passed to 'Execute', which
619844d2303SCaroline Tice     // does the stripping itself.
620844d2303SCaroline Tice     size_t pos = raw_command_string.find(alias_command);
621b9c1b51eSKate Stone     if (pos == 0) {
622844d2303SCaroline Tice       raw_command_string = raw_command_string.substr(alias_command.size());
623844d2303SCaroline Tice       pos = raw_command_string.find_first_not_of(' ');
624844d2303SCaroline Tice       if ((pos != std::string::npos) && (pos > 0))
625844d2303SCaroline Tice         raw_command_string = raw_command_string.substr(pos);
626b9c1b51eSKate Stone     } else {
627844d2303SCaroline Tice       result.AppendError("Error parsing command string.  No alias created.");
628844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
629844d2303SCaroline Tice       return false;
630844d2303SCaroline Tice     }
631844d2303SCaroline Tice 
632844d2303SCaroline Tice     // Verify that the command is alias-able.
633b9c1b51eSKate Stone     if (m_interpreter.CommandExists(alias_command.c_str())) {
634b9c1b51eSKate Stone       result.AppendErrorWithFormat(
635b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
636844d2303SCaroline Tice           alias_command.c_str());
637844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
638844d2303SCaroline Tice       return false;
639844d2303SCaroline Tice     }
640844d2303SCaroline Tice 
641b9c1b51eSKate Stone     // Get CommandObject that is being aliased. The command name is read from
642b9c1b51eSKate Stone     // the front of raw_command_string.
643b9c1b51eSKate Stone     // raw_command_string is returned with the name of the command object
644b9c1b51eSKate Stone     // stripped off the front.
645d72e412fSEnrico Granata     std::string original_raw_command_string(raw_command_string);
646b9c1b51eSKate Stone     CommandObject *cmd_obj =
647b9c1b51eSKate Stone         m_interpreter.GetCommandObjectForCommand(raw_command_string);
648844d2303SCaroline Tice 
649b9c1b51eSKate Stone     if (!cmd_obj) {
650b9c1b51eSKate Stone       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
651b9c1b51eSKate Stone                                    "'%s' does not begin with a valid command."
652b9c1b51eSKate Stone                                    "  No alias created.",
653b9c1b51eSKate Stone                                    original_raw_command_string.c_str());
654844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
655844d2303SCaroline Tice       return false;
656b9c1b51eSKate Stone     } else if (!cmd_obj->WantsRawCommandString()) {
657b9c1b51eSKate Stone       // Note that args was initialized with the original command, and has not
658b9c1b51eSKate Stone       // been updated to this point.
659b9c1b51eSKate Stone       // Therefore can we pass it to the version of Execute that does not
660b9c1b51eSKate Stone       // need/expect raw input in the alias.
6615a988416SJim Ingham       return HandleAliasingNormalCommand(args, result);
662b9c1b51eSKate Stone     } else {
663b9c1b51eSKate Stone       return HandleAliasingRawCommand(alias_command, raw_command_string,
664b9c1b51eSKate Stone                                       *cmd_obj, result);
6655a988416SJim Ingham     }
6665a988416SJim Ingham     return result.Succeeded();
6675a988416SJim Ingham   }
6685a988416SJim Ingham 
669b9c1b51eSKate Stone   bool HandleAliasingRawCommand(const std::string &alias_command,
670b9c1b51eSKate Stone                                 std::string &raw_command_string,
671b9c1b51eSKate Stone                                 CommandObject &cmd_obj,
672b9c1b51eSKate Stone                                 CommandReturnObject &result) {
673844d2303SCaroline Tice     // Verify & handle any options/arguments passed to the alias command
674844d2303SCaroline Tice 
675b9c1b51eSKate Stone     OptionArgVectorSP option_arg_vector_sp =
676b9c1b51eSKate Stone         OptionArgVectorSP(new OptionArgVector);
677844d2303SCaroline Tice 
678b9c1b51eSKate Stone     if (CommandObjectSP cmd_obj_sp =
679b9c1b51eSKate Stone             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
680b9c1b51eSKate Stone       if (m_interpreter.AliasExists(alias_command.c_str()) ||
681b9c1b51eSKate Stone           m_interpreter.UserCommandExists(alias_command.c_str())) {
682b9c1b51eSKate Stone         result.AppendWarningWithFormat(
683b9c1b51eSKate Stone             "Overwriting existing definition for '%s'.\n",
684844d2303SCaroline Tice             alias_command.c_str());
685844d2303SCaroline Tice       }
686b9c1b51eSKate Stone       if (CommandAlias *alias = m_interpreter.AddAlias(
687b9c1b51eSKate Stone               alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) {
68845d0e238SEnrico Granata         if (m_command_options.m_help.OptionWasSet())
68945d0e238SEnrico Granata           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
69045d0e238SEnrico Granata         if (m_command_options.m_long_help.OptionWasSet())
69145d0e238SEnrico Granata           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
692844d2303SCaroline Tice         result.SetStatus(eReturnStatusSuccessFinishNoResult);
693b9c1b51eSKate Stone       } else {
694472362e6SCaroline Tice         result.AppendError("Unable to create requested alias.\n");
695472362e6SCaroline Tice         result.SetStatus(eReturnStatusFailed);
696472362e6SCaroline Tice       }
697212130acSEnrico Granata 
698b9c1b51eSKate Stone     } else {
699212130acSEnrico Granata       result.AppendError("Unable to create requested alias.\n");
700212130acSEnrico Granata       result.SetStatus(eReturnStatusFailed);
701212130acSEnrico Granata     }
702212130acSEnrico Granata 
703844d2303SCaroline Tice     return result.Succeeded();
704844d2303SCaroline Tice   }
705ebc09c36SJim Ingham 
706b9c1b51eSKate Stone   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
707867b185dSCaroline Tice     size_t argc = args.GetArgumentCount();
708ebc09c36SJim Ingham 
709b9c1b51eSKate Stone     if (argc < 2) {
710d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
711ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
712ebc09c36SJim Ingham       return false;
713ebc09c36SJim Ingham     }
714ebc09c36SJim Ingham 
715ebc09c36SJim Ingham     const std::string alias_command = args.GetArgumentAtIndex(0);
716ebc09c36SJim Ingham     const std::string actual_command = args.GetArgumentAtIndex(1);
717ebc09c36SJim Ingham 
718ebc09c36SJim Ingham     args.Shift(); // Shift the alias command word off the argument vector.
719ebc09c36SJim Ingham     args.Shift(); // Shift the old command word off the argument vector.
720ebc09c36SJim Ingham 
721b9c1b51eSKate Stone     // Verify that the command is alias'able, and get the appropriate command
722b9c1b51eSKate Stone     // object.
723ebc09c36SJim Ingham 
724b9c1b51eSKate Stone     if (m_interpreter.CommandExists(alias_command.c_str())) {
725b9c1b51eSKate Stone       result.AppendErrorWithFormat(
726b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
727ebc09c36SJim Ingham           alias_command.c_str());
728ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
729b9c1b51eSKate Stone     } else {
730b9c1b51eSKate Stone       CommandObjectSP command_obj_sp(
731b9c1b51eSKate Stone           m_interpreter.GetCommandSPExact(actual_command.c_str(), true));
732ebc09c36SJim Ingham       CommandObjectSP subcommand_obj_sp;
733ebc09c36SJim Ingham       bool use_subcommand = false;
734b9c1b51eSKate Stone       if (command_obj_sp) {
735ebc09c36SJim Ingham         CommandObject *cmd_obj = command_obj_sp.get();
7366e3d8e7fSEugene Zelenko         CommandObject *sub_cmd_obj = nullptr;
737b9c1b51eSKate Stone         OptionArgVectorSP option_arg_vector_sp =
738b9c1b51eSKate Stone             OptionArgVectorSP(new OptionArgVector);
739ebc09c36SJim Ingham 
740b9c1b51eSKate Stone         while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) {
741b9c1b51eSKate Stone           if (argc >= 3) {
742ebc09c36SJim Ingham             const std::string sub_command = args.GetArgumentAtIndex(0);
743ebc09c36SJim Ingham             assert(sub_command.length() != 0);
744998255bfSGreg Clayton             subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command.c_str());
745b9c1b51eSKate Stone             if (subcommand_obj_sp) {
746ebc09c36SJim Ingham               sub_cmd_obj = subcommand_obj_sp.get();
747ebc09c36SJim Ingham               use_subcommand = true;
748b9c1b51eSKate Stone               args.Shift(); // Shift the sub_command word off the argument
749b9c1b51eSKate Stone                             // vector.
750844d2303SCaroline Tice               cmd_obj = sub_cmd_obj;
751b9c1b51eSKate Stone             } else {
752b9c1b51eSKate Stone               result.AppendErrorWithFormat(
753b9c1b51eSKate Stone                   "'%s' is not a valid sub-command of '%s'.  "
754f415eeb4SCaroline Tice                   "Unable to create alias.\n",
755f415eeb4SCaroline Tice                   sub_command.c_str(), actual_command.c_str());
756ebc09c36SJim Ingham               result.SetStatus(eReturnStatusFailed);
757ebc09c36SJim Ingham               return false;
758ebc09c36SJim Ingham             }
759ebc09c36SJim Ingham           }
760ebc09c36SJim Ingham         }
761ebc09c36SJim Ingham 
762ebc09c36SJim Ingham         // Verify & handle any options/arguments passed to the alias command
763ebc09c36SJim Ingham 
764212130acSEnrico Granata         std::string args_string;
765212130acSEnrico Granata 
766b9c1b51eSKate Stone         if (args.GetArgumentCount() > 0) {
767b9c1b51eSKate Stone           CommandObjectSP tmp_sp =
768b9c1b51eSKate Stone               m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
769ebc09c36SJim Ingham           if (use_subcommand)
770b9c1b51eSKate Stone             tmp_sp = m_interpreter.GetCommandSPExact(
771b9c1b51eSKate Stone                 sub_cmd_obj->GetCommandName(), false);
772ca90c47eSCaroline Tice 
773ca90c47eSCaroline Tice           args.GetCommandString(args_string);
774867b185dSCaroline Tice         }
775ebc09c36SJim Ingham 
776b9c1b51eSKate Stone         if (m_interpreter.AliasExists(alias_command.c_str()) ||
777b9c1b51eSKate Stone             m_interpreter.UserCommandExists(alias_command.c_str())) {
778b9c1b51eSKate Stone           result.AppendWarningWithFormat(
779b9c1b51eSKate Stone               "Overwriting existing definition for '%s'.\n",
780ebc09c36SJim Ingham               alias_command.c_str());
781ebc09c36SJim Ingham         }
782ebc09c36SJim Ingham 
783b9c1b51eSKate Stone         if (CommandAlias *alias = m_interpreter.AddAlias(
784b9c1b51eSKate Stone                 alias_command.c_str(),
785212130acSEnrico Granata                 use_subcommand ? subcommand_obj_sp : command_obj_sp,
786b9c1b51eSKate Stone                 args_string.c_str())) {
78745d0e238SEnrico Granata           if (m_command_options.m_help.OptionWasSet())
78845d0e238SEnrico Granata             alias->SetHelp(m_command_options.m_help.GetCurrentValue());
78945d0e238SEnrico Granata           if (m_command_options.m_long_help.OptionWasSet())
79045d0e238SEnrico Granata             alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
791ebc09c36SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishNoResult);
792b9c1b51eSKate Stone         } else {
793212130acSEnrico Granata           result.AppendError("Unable to create requested alias.\n");
794212130acSEnrico Granata           result.SetStatus(eReturnStatusFailed);
795212130acSEnrico Granata           return false;
796212130acSEnrico Granata         }
797b9c1b51eSKate Stone       } else {
798b9c1b51eSKate Stone         result.AppendErrorWithFormat("'%s' is not an existing command.\n",
799b9c1b51eSKate Stone                                      actual_command.c_str());
800ebc09c36SJim Ingham         result.SetStatus(eReturnStatusFailed);
801e7941795SCaroline Tice         return false;
802ebc09c36SJim Ingham       }
803ebc09c36SJim Ingham     }
804ebc09c36SJim Ingham 
805ebc09c36SJim Ingham     return result.Succeeded();
806ebc09c36SJim Ingham   }
807ebc09c36SJim Ingham };
808ebc09c36SJim Ingham 
809ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
810ebc09c36SJim Ingham //-------------------------------------------------------------------------
811ebc09c36SJim Ingham // CommandObjectCommandsUnalias
812ebc09c36SJim Ingham //-------------------------------------------------------------------------
813ebc09c36SJim Ingham 
814b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed {
815ebc09c36SJim Ingham public:
8167428a18cSKate Stone   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
817b9c1b51eSKate Stone       : CommandObjectParsed(
818b9c1b51eSKate Stone             interpreter, "command unalias",
819b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command alias'.",
820b9c1b51eSKate Stone             nullptr) {
821405fe67fSCaroline Tice     CommandArgumentEntry arg;
822405fe67fSCaroline Tice     CommandArgumentData alias_arg;
823405fe67fSCaroline Tice 
824405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
825405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
826405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
827405fe67fSCaroline Tice 
828b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
829b9c1b51eSKate Stone     // argument entry.
830405fe67fSCaroline Tice     arg.push_back(alias_arg);
831405fe67fSCaroline Tice 
832405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
833405fe67fSCaroline Tice     m_arguments.push_back(arg);
834ebc09c36SJim Ingham   }
835ebc09c36SJim Ingham 
8366e3d8e7fSEugene Zelenko   ~CommandObjectCommandsUnalias() override = default;
837ebc09c36SJim Ingham 
8385a988416SJim Ingham protected:
839b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
840ebc09c36SJim Ingham     CommandObject::CommandMap::iterator pos;
841ebc09c36SJim Ingham     CommandObject *cmd_obj;
842ebc09c36SJim Ingham 
843b9c1b51eSKate Stone     if (args.GetArgumentCount() != 0) {
844ebc09c36SJim Ingham       const char *command_name = args.GetArgumentAtIndex(0);
845a7015092SGreg Clayton       cmd_obj = m_interpreter.GetCommandObject(command_name);
846b9c1b51eSKate Stone       if (cmd_obj) {
847b9c1b51eSKate Stone         if (m_interpreter.CommandExists(command_name)) {
848b9c1b51eSKate Stone           if (cmd_obj->IsRemovable()) {
849b9c1b51eSKate Stone             result.AppendErrorWithFormat(
850b9c1b51eSKate Stone                 "'%s' is not an alias, it is a debugger command which can be "
851b9c1b51eSKate Stone                 "removed using the 'command delete' command.\n",
852b547278cSGreg Clayton                 command_name);
853b9c1b51eSKate Stone           } else {
854b9c1b51eSKate Stone             result.AppendErrorWithFormat(
855b9c1b51eSKate Stone                 "'%s' is a permanent debugger command and cannot be removed.\n",
856ebc09c36SJim Ingham                 command_name);
857b547278cSGreg Clayton           }
858ebc09c36SJim Ingham           result.SetStatus(eReturnStatusFailed);
859b9c1b51eSKate Stone         } else {
860b9c1b51eSKate Stone           if (!m_interpreter.RemoveAlias(command_name)) {
861a7015092SGreg Clayton             if (m_interpreter.AliasExists(command_name))
862b9c1b51eSKate Stone               result.AppendErrorWithFormat(
863b9c1b51eSKate Stone                   "Error occurred while attempting to unalias '%s'.\n",
864ebc09c36SJim Ingham                   command_name);
865ebc09c36SJim Ingham             else
866b9c1b51eSKate Stone               result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
867b9c1b51eSKate Stone                                            command_name);
868ebc09c36SJim Ingham             result.SetStatus(eReturnStatusFailed);
869b9c1b51eSKate Stone           } else
870ebc09c36SJim Ingham             result.SetStatus(eReturnStatusSuccessFinishNoResult);
871ebc09c36SJim Ingham         }
872b9c1b51eSKate Stone       } else {
873b9c1b51eSKate Stone         result.AppendErrorWithFormat(
874b9c1b51eSKate Stone             "'%s' is not a known command.\nTry 'help' to see a "
875ebc09c36SJim Ingham             "current list of commands.\n",
876ebc09c36SJim Ingham             command_name);
877ebc09c36SJim Ingham         result.SetStatus(eReturnStatusFailed);
878ebc09c36SJim Ingham       }
879b9c1b51eSKate Stone     } else {
880ebc09c36SJim Ingham       result.AppendError("must call 'unalias' with a valid alias");
881ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
882ebc09c36SJim Ingham     }
883ebc09c36SJim Ingham 
884ebc09c36SJim Ingham     return result.Succeeded();
885ebc09c36SJim Ingham   }
886ebc09c36SJim Ingham };
887ebc09c36SJim Ingham 
888b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete
889b547278cSGreg Clayton //-------------------------------------------------------------------------
890b547278cSGreg Clayton // CommandObjectCommandsDelete
891b547278cSGreg Clayton //-------------------------------------------------------------------------
892b547278cSGreg Clayton 
893b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed {
894b547278cSGreg Clayton public:
8957428a18cSKate Stone   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
896b9c1b51eSKate Stone       : CommandObjectParsed(
897b9c1b51eSKate Stone             interpreter, "command delete",
898b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command regex'.",
899b9c1b51eSKate Stone             nullptr) {
900b547278cSGreg Clayton     CommandArgumentEntry arg;
901b547278cSGreg Clayton     CommandArgumentData alias_arg;
902b547278cSGreg Clayton 
903b547278cSGreg Clayton     // Define the first (and only) variant of this arg.
904b547278cSGreg Clayton     alias_arg.arg_type = eArgTypeCommandName;
905b547278cSGreg Clayton     alias_arg.arg_repetition = eArgRepeatPlain;
906b547278cSGreg Clayton 
907b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
908b9c1b51eSKate Stone     // argument entry.
909b547278cSGreg Clayton     arg.push_back(alias_arg);
910b547278cSGreg Clayton 
911b547278cSGreg Clayton     // Push the data for the first argument into the m_arguments vector.
912b547278cSGreg Clayton     m_arguments.push_back(arg);
913b547278cSGreg Clayton   }
914b547278cSGreg Clayton 
9156e3d8e7fSEugene Zelenko   ~CommandObjectCommandsDelete() override = default;
916b547278cSGreg Clayton 
917b547278cSGreg Clayton protected:
918b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
919b547278cSGreg Clayton     CommandObject::CommandMap::iterator pos;
920b547278cSGreg Clayton 
921b9c1b51eSKate Stone     if (args.GetArgumentCount() != 0) {
922b547278cSGreg Clayton       const char *command_name = args.GetArgumentAtIndex(0);
923b9c1b51eSKate Stone       if (m_interpreter.CommandExists(command_name)) {
924b9c1b51eSKate Stone         if (m_interpreter.RemoveCommand(command_name)) {
925b547278cSGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishNoResult);
926b9c1b51eSKate Stone         } else {
927b9c1b51eSKate Stone           result.AppendErrorWithFormat(
928b9c1b51eSKate Stone               "'%s' is a permanent debugger command and cannot be removed.\n",
929b547278cSGreg Clayton               command_name);
930b547278cSGreg Clayton           result.SetStatus(eReturnStatusFailed);
931b547278cSGreg Clayton         }
932b9c1b51eSKate Stone       } else {
93346d4aa21SEnrico Granata         StreamString error_msg_stream;
93446d4aa21SEnrico Granata         const bool generate_apropos = true;
93546d4aa21SEnrico Granata         const bool generate_type_lookup = false;
936b9c1b51eSKate Stone         CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
937b9c1b51eSKate Stone             &error_msg_stream, command_name, nullptr, nullptr, generate_apropos,
93846d4aa21SEnrico Granata             generate_type_lookup);
93946d4aa21SEnrico Granata         result.AppendErrorWithFormat("%s", error_msg_stream.GetData());
940b547278cSGreg Clayton         result.SetStatus(eReturnStatusFailed);
941b547278cSGreg Clayton       }
942b9c1b51eSKate Stone     } else {
943b9c1b51eSKate Stone       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
944b9c1b51eSKate Stone                                    "defined regular expression command names",
9457428a18cSKate Stone                                    GetCommandName());
946b547278cSGreg Clayton       result.SetStatus(eReturnStatusFailed);
947b547278cSGreg Clayton     }
948b547278cSGreg Clayton 
949b547278cSGreg Clayton     return result.Succeeded();
950b547278cSGreg Clayton   }
951b547278cSGreg Clayton };
952b547278cSGreg Clayton 
953de164aaaSGreg Clayton //-------------------------------------------------------------------------
954de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
955de164aaaSGreg Clayton //-------------------------------------------------------------------------
956*1f0f5b5bSZachary Turner 
957*1f0f5b5bSZachary Turner static OptionDefinition g_regex_options[] = {
958*1f0f5b5bSZachary Turner     // clang-format off
959*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
960*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
961*1f0f5b5bSZachary Turner     // clang-format on
962*1f0f5b5bSZachary Turner };
963*1f0f5b5bSZachary Turner 
9645a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex
965de164aaaSGreg Clayton 
966b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed,
967b9c1b51eSKate Stone                                       public IOHandlerDelegateMultiline {
968de164aaaSGreg Clayton public:
9697428a18cSKate Stone   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
970b9c1b51eSKate Stone       : CommandObjectParsed(
971b9c1b51eSKate Stone             interpreter, "command regex", "Define a custom command in terms of "
972b9c1b51eSKate Stone                                           "existing commands by matching "
973b9c1b51eSKate Stone                                           "regular expressions.",
9740e5e5a79SGreg Clayton             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
975b9c1b51eSKate Stone         IOHandlerDelegateMultiline("",
976b9c1b51eSKate Stone                                    IOHandlerDelegate::Completion::LLDBCommand),
977b9c1b51eSKate Stone         m_options() {
978b9c1b51eSKate Stone     SetHelpLong(
979b9c1b51eSKate Stone         R"(
980b9c1b51eSKate Stone )"
981b9c1b51eSKate Stone         "This command allows the user to create powerful regular expression commands \
982ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \
983b9c1b51eSKate Stone using the regular expression substitution format of:"
984b9c1b51eSKate Stone         R"(
985ea671fbdSKate Stone 
986ea671fbdSKate Stone     s/<regex>/<subst>/
987ea671fbdSKate Stone 
988b9c1b51eSKate Stone )"
989b9c1b51eSKate Stone         "<regex> is a regular expression that can use parenthesis to capture regular \
990ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \
991b9c1b51eSKate Stone for the first match, %2 for the second, and so on."
992b9c1b51eSKate Stone         R"(
993ea671fbdSKate Stone 
994b9c1b51eSKate Stone )"
995b9c1b51eSKate Stone         "The regular expressions can all be specified on the command line if more than \
996ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \
997ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \
998b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition."
999b9c1b51eSKate Stone         R"(
1000ea671fbdSKate Stone 
1001ea671fbdSKate Stone EXAMPLES
1002ea671fbdSKate Stone 
1003b9c1b51eSKate Stone )"
1004b9c1b51eSKate Stone         "The following example will define a regular expression command named 'f' that \
1005ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
1006b9c1b51eSKate Stone a number follows 'f':"
1007b9c1b51eSKate Stone         R"(
1008ea671fbdSKate Stone 
1009b9c1b51eSKate Stone     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1010de164aaaSGreg Clayton   }
1011de164aaaSGreg Clayton 
10126e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAddRegex() override = default;
1013de164aaaSGreg Clayton 
10145a988416SJim Ingham protected:
1015b9c1b51eSKate Stone   void IOHandlerActivated(IOHandler &io_handler) override {
101644d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1017b9c1b51eSKate Stone     if (output_sp) {
1018b9c1b51eSKate Stone       output_sp->PutCString("Enter one of more sed substitution commands in "
1019b9c1b51eSKate Stone                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
1020b9c1b51eSKate Stone                             "substitution list with an empty line.\n");
102144d93782SGreg Clayton       output_sp->Flush();
102244d93782SGreg Clayton     }
102344d93782SGreg Clayton   }
102444d93782SGreg Clayton 
1025b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1026b9c1b51eSKate Stone                               std::string &data) override {
102744d93782SGreg Clayton     io_handler.SetIsDone(true);
1028b9c1b51eSKate Stone     if (m_regex_cmd_ap) {
102944d93782SGreg Clayton       StringList lines;
1030b9c1b51eSKate Stone       if (lines.SplitIntoLines(data)) {
103144d93782SGreg Clayton         const size_t num_lines = lines.GetSize();
103244d93782SGreg Clayton         bool check_only = false;
1033b9c1b51eSKate Stone         for (size_t i = 0; i < num_lines; ++i) {
103444d93782SGreg Clayton           llvm::StringRef bytes_strref(lines[i]);
103544d93782SGreg Clayton           Error error = AppendRegexSubstitution(bytes_strref, check_only);
1036b9c1b51eSKate Stone           if (error.Fail()) {
1037b9c1b51eSKate Stone             if (!m_interpreter.GetDebugger()
1038b9c1b51eSKate Stone                      .GetCommandInterpreter()
1039b9c1b51eSKate Stone                      .GetBatchCommandMode()) {
1040b9c1b51eSKate Stone               StreamSP out_stream =
1041b9c1b51eSKate Stone                   m_interpreter.GetDebugger().GetAsyncOutputStream();
104244d93782SGreg Clayton               out_stream->Printf("error: %s\n", error.AsCString());
104344d93782SGreg Clayton             }
104444d93782SGreg Clayton           }
104544d93782SGreg Clayton         }
104644d93782SGreg Clayton       }
1047b9c1b51eSKate Stone       if (m_regex_cmd_ap->HasRegexEntries()) {
104844d93782SGreg Clayton         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
104944d93782SGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
105044d93782SGreg Clayton       }
105144d93782SGreg Clayton     }
105244d93782SGreg Clayton   }
105344d93782SGreg Clayton 
1054b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
10555a988416SJim Ingham     const size_t argc = command.GetArgumentCount();
1056b9c1b51eSKate Stone     if (argc == 0) {
1057b9c1b51eSKate Stone       result.AppendError("usage: 'command regex <command-name> "
1058b9c1b51eSKate Stone                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
10590e5e5a79SGreg Clayton       result.SetStatus(eReturnStatusFailed);
1060b9c1b51eSKate Stone     } else {
10610e5e5a79SGreg Clayton       Error error;
10625a988416SJim Ingham       const char *name = command.GetArgumentAtIndex(0);
1063b9c1b51eSKate Stone       m_regex_cmd_ap.reset(new CommandObjectRegexCommand(
1064b9c1b51eSKate Stone           m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10,
1065b9c1b51eSKate Stone           0, true));
10660e5e5a79SGreg Clayton 
1067b9c1b51eSKate Stone       if (argc == 1) {
106844d93782SGreg Clayton         Debugger &debugger = m_interpreter.GetDebugger();
1069e30f11d9SKate Stone         bool color_prompt = debugger.GetUseColor();
107044d93782SGreg Clayton         const bool multiple_lines = true; // Get multiple lines
1071b9c1b51eSKate Stone         IOHandlerSP io_handler_sp(new IOHandlerEditline(
1072b9c1b51eSKate Stone             debugger, IOHandler::Type::Other,
107373d80faaSGreg Clayton             "lldb-regex", // Name of input reader for history
1074ea508635SGreg Clayton             "> ",         // Prompt
10756e3d8e7fSEugene Zelenko             nullptr,      // Continuation prompt
1076b9c1b51eSKate Stone             multiple_lines, color_prompt,
1077f6913cd7SGreg Clayton             0, // Don't show line numbers
107844d93782SGreg Clayton             *this));
107944d93782SGreg Clayton 
1080b9c1b51eSKate Stone         if (io_handler_sp) {
108144d93782SGreg Clayton           debugger.PushIOHandler(io_handler_sp);
1082de164aaaSGreg Clayton           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1083de164aaaSGreg Clayton         }
1084b9c1b51eSKate Stone       } else {
1085b9c1b51eSKate Stone         for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) {
10865a988416SJim Ingham           llvm::StringRef arg_strref(command.GetArgumentAtIndex(arg_idx));
108744d93782SGreg Clayton           bool check_only = false;
108844d93782SGreg Clayton           error = AppendRegexSubstitution(arg_strref, check_only);
10890e5e5a79SGreg Clayton           if (error.Fail())
10900e5e5a79SGreg Clayton             break;
10910e5e5a79SGreg Clayton         }
10920e5e5a79SGreg Clayton 
1093b9c1b51eSKate Stone         if (error.Success()) {
10940e5e5a79SGreg Clayton           AddRegexCommandToInterpreter();
10950e5e5a79SGreg Clayton         }
10960e5e5a79SGreg Clayton       }
1097b9c1b51eSKate Stone       if (error.Fail()) {
10980e5e5a79SGreg Clayton         result.AppendError(error.AsCString());
1099de164aaaSGreg Clayton         result.SetStatus(eReturnStatusFailed);
1100de164aaaSGreg Clayton       }
11010e5e5a79SGreg Clayton     }
11020e5e5a79SGreg Clayton 
1103de164aaaSGreg Clayton     return result.Succeeded();
1104de164aaaSGreg Clayton   }
1105de164aaaSGreg Clayton 
1106b9c1b51eSKate Stone   Error AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1107b9c1b51eSKate Stone                                 bool check_only) {
11080e5e5a79SGreg Clayton     Error error;
11090e5e5a79SGreg Clayton 
1110b9c1b51eSKate Stone     if (!m_regex_cmd_ap) {
1111b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1112b9c1b51eSKate Stone           "invalid regular expression command object for: '%.*s'",
1113b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11140e5e5a79SGreg Clayton       return error;
1115de164aaaSGreg Clayton     }
11160e5e5a79SGreg Clayton 
11170e5e5a79SGreg Clayton     size_t regex_sed_size = regex_sed.size();
11180e5e5a79SGreg Clayton 
1119b9c1b51eSKate Stone     if (regex_sed_size <= 1) {
1120b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1121b9c1b51eSKate Stone           "regular expression substitution string is too short: '%.*s'",
1122b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11230e5e5a79SGreg Clayton       return error;
11240e5e5a79SGreg Clayton     }
11250e5e5a79SGreg Clayton 
1126b9c1b51eSKate Stone     if (regex_sed[0] != 's') {
1127b9c1b51eSKate Stone       error.SetErrorStringWithFormat("regular expression substitution string "
1128b9c1b51eSKate Stone                                      "doesn't start with 's': '%.*s'",
1129b9c1b51eSKate Stone                                      (int)regex_sed.size(), regex_sed.data());
11300e5e5a79SGreg Clayton       return error;
11310e5e5a79SGreg Clayton     }
11320e5e5a79SGreg Clayton     const size_t first_separator_char_pos = 1;
11330e5e5a79SGreg Clayton     // use the char that follows 's' as the regex separator character
11340e5e5a79SGreg Clayton     // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
11350e5e5a79SGreg Clayton     const char separator_char = regex_sed[first_separator_char_pos];
1136b9c1b51eSKate Stone     const size_t second_separator_char_pos =
1137b9c1b51eSKate Stone         regex_sed.find(separator_char, first_separator_char_pos + 1);
11380e5e5a79SGreg Clayton 
1139b9c1b51eSKate Stone     if (second_separator_char_pos == std::string::npos) {
1140b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1141b9c1b51eSKate Stone           "missing second '%c' separator char after '%.*s' in '%.*s'",
11420e5e5a79SGreg Clayton           separator_char,
11430e5e5a79SGreg Clayton           (int)(regex_sed.size() - first_separator_char_pos - 1),
1144ea508635SGreg Clayton           regex_sed.data() + (first_separator_char_pos + 1),
1145b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11460e5e5a79SGreg Clayton       return error;
11470e5e5a79SGreg Clayton     }
11480e5e5a79SGreg Clayton 
1149b9c1b51eSKate Stone     const size_t third_separator_char_pos =
1150b9c1b51eSKate Stone         regex_sed.find(separator_char, second_separator_char_pos + 1);
11510e5e5a79SGreg Clayton 
1152b9c1b51eSKate Stone     if (third_separator_char_pos == std::string::npos) {
1153b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1154b9c1b51eSKate Stone           "missing third '%c' separator char after '%.*s' in '%.*s'",
11550e5e5a79SGreg Clayton           separator_char,
11560e5e5a79SGreg Clayton           (int)(regex_sed.size() - second_separator_char_pos - 1),
1157ea508635SGreg Clayton           regex_sed.data() + (second_separator_char_pos + 1),
1158b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11590e5e5a79SGreg Clayton       return error;
11600e5e5a79SGreg Clayton     }
11610e5e5a79SGreg Clayton 
1162b9c1b51eSKate Stone     if (third_separator_char_pos != regex_sed_size - 1) {
11630e5e5a79SGreg Clayton       // Make sure that everything that follows the last regex
11640e5e5a79SGreg Clayton       // separator char
1165b9c1b51eSKate Stone       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1166b9c1b51eSKate Stone                                       third_separator_char_pos + 1) !=
1167b9c1b51eSKate Stone           std::string::npos) {
1168b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
1169b9c1b51eSKate Stone             "extra data found after the '%.*s' regular expression substitution "
1170b9c1b51eSKate Stone             "string: '%.*s'",
1171b9c1b51eSKate Stone             (int)third_separator_char_pos + 1, regex_sed.data(),
11720e5e5a79SGreg Clayton             (int)(regex_sed.size() - third_separator_char_pos - 1),
11730e5e5a79SGreg Clayton             regex_sed.data() + (third_separator_char_pos + 1));
11740e5e5a79SGreg Clayton         return error;
11750e5e5a79SGreg Clayton       }
1176b9c1b51eSKate Stone     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1177b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1178b9c1b51eSKate Stone           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1179b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
11800e5e5a79SGreg Clayton           regex_sed.data());
11810e5e5a79SGreg Clayton       return error;
1182b9c1b51eSKate Stone     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1183b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1184b9c1b51eSKate Stone           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1185b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
11860e5e5a79SGreg Clayton           regex_sed.data());
11870e5e5a79SGreg Clayton       return error;
11880e5e5a79SGreg Clayton     }
118944d93782SGreg Clayton 
1190b9c1b51eSKate Stone     if (!check_only) {
1191b9c1b51eSKate Stone       std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1192b9c1b51eSKate Stone                                          second_separator_char_pos -
1193b9c1b51eSKate Stone                                              first_separator_char_pos - 1));
1194b9c1b51eSKate Stone       std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1195b9c1b51eSKate Stone                                          third_separator_char_pos -
1196b9c1b51eSKate Stone                                              second_separator_char_pos - 1));
1197b9c1b51eSKate Stone       m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
119844d93782SGreg Clayton     }
11990e5e5a79SGreg Clayton     return error;
1200de164aaaSGreg Clayton   }
1201de164aaaSGreg Clayton 
1202b9c1b51eSKate Stone   void AddRegexCommandToInterpreter() {
1203b9c1b51eSKate Stone     if (m_regex_cmd_ap) {
1204b9c1b51eSKate Stone       if (m_regex_cmd_ap->HasRegexEntries()) {
1205de164aaaSGreg Clayton         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1206de164aaaSGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1207de164aaaSGreg Clayton       }
1208de164aaaSGreg Clayton     }
1209de164aaaSGreg Clayton   }
1210de164aaaSGreg Clayton 
1211de164aaaSGreg Clayton private:
12127b0992d9SGreg Clayton   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1213de164aaaSGreg Clayton 
1214b9c1b51eSKate Stone   class CommandOptions : public Options {
1215de164aaaSGreg Clayton   public:
1216b9c1b51eSKate Stone     CommandOptions() : Options() {}
1217de164aaaSGreg Clayton 
12186e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1219de164aaaSGreg Clayton 
1220b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1221b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
1222de164aaaSGreg Clayton       Error error;
12233bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1224de164aaaSGreg Clayton 
1225b9c1b51eSKate Stone       switch (short_option) {
1226de164aaaSGreg Clayton       case 'h':
1227de164aaaSGreg Clayton         m_help.assign(option_arg);
1228de164aaaSGreg Clayton         break;
1229de164aaaSGreg Clayton       case 's':
1230de164aaaSGreg Clayton         m_syntax.assign(option_arg);
1231de164aaaSGreg Clayton         break;
1232de164aaaSGreg Clayton       default:
1233b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1234b9c1b51eSKate Stone                                        short_option);
1235de164aaaSGreg Clayton         break;
1236de164aaaSGreg Clayton       }
1237de164aaaSGreg Clayton 
1238de164aaaSGreg Clayton       return error;
1239de164aaaSGreg Clayton     }
1240de164aaaSGreg Clayton 
1241b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1242de164aaaSGreg Clayton       m_help.clear();
1243de164aaaSGreg Clayton       m_syntax.clear();
1244de164aaaSGreg Clayton     }
1245de164aaaSGreg Clayton 
1246*1f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1247*1f0f5b5bSZachary Turner       return g_regex_options;
1248*1f0f5b5bSZachary Turner     }
1249de164aaaSGreg Clayton 
1250b9c1b51eSKate Stone     const char *GetHelp() {
12516e3d8e7fSEugene Zelenko       return (m_help.empty() ? nullptr : m_help.c_str());
1252de164aaaSGreg Clayton     }
12536e3d8e7fSEugene Zelenko 
1254b9c1b51eSKate Stone     const char *GetSyntax() {
12556e3d8e7fSEugene Zelenko       return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1256de164aaaSGreg Clayton     }
12576e3d8e7fSEugene Zelenko 
1258de164aaaSGreg Clayton   protected:
12596e3d8e7fSEugene Zelenko     // Instance variables to hold the values for command options.
12606e3d8e7fSEugene Zelenko 
1261de164aaaSGreg Clayton     std::string m_help;
1262de164aaaSGreg Clayton     std::string m_syntax;
1263de164aaaSGreg Clayton   };
1264de164aaaSGreg Clayton 
1265b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
1266de164aaaSGreg Clayton 
12675a988416SJim Ingham   CommandOptions m_options;
1268de164aaaSGreg Clayton };
1269de164aaaSGreg Clayton 
1270b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw {
1271223383edSEnrico Granata public:
1272b9c1b51eSKate Stone   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1273b9c1b51eSKate Stone                               std::string funct, std::string help,
1274b9c1b51eSKate Stone                               ScriptedCommandSynchronicity synch)
1275b9c1b51eSKate Stone       : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1276b9c1b51eSKate Stone         m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1277735152e3SEnrico Granata     if (!help.empty())
1278735152e3SEnrico Granata       SetHelp(help.c_str());
1279b9c1b51eSKate Stone     else {
1280735152e3SEnrico Granata       StreamString stream;
1281735152e3SEnrico Granata       stream.Printf("For more information run 'help %s'", name.c_str());
1282735152e3SEnrico Granata       SetHelp(stream.GetData());
1283735152e3SEnrico Granata     }
1284223383edSEnrico Granata   }
1285223383edSEnrico Granata 
12866e3d8e7fSEugene Zelenko   ~CommandObjectPythonFunction() override = default;
1287223383edSEnrico Granata 
1288b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
12895a988416SJim Ingham 
1290b9c1b51eSKate Stone   const std::string &GetFunctionName() { return m_function_name; }
12915a988416SJim Ingham 
1292b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
12935a988416SJim Ingham 
1294b9c1b51eSKate Stone   const char *GetHelpLong() override {
1295b9c1b51eSKate Stone     if (!m_fetched_help_long) {
1296fac939e9SEnrico Granata       ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1297b9c1b51eSKate Stone       if (scripter) {
1298fac939e9SEnrico Granata         std::string docstring;
1299b9c1b51eSKate Stone         m_fetched_help_long = scripter->GetDocumentationForItem(
1300b9c1b51eSKate Stone             m_function_name.c_str(), docstring);
1301fac939e9SEnrico Granata         if (!docstring.empty())
1302bfb75e9bSEnrico Granata           SetHelpLong(docstring.c_str());
1303fac939e9SEnrico Granata       }
1304fac939e9SEnrico Granata     }
1305fac939e9SEnrico Granata     return CommandObjectRaw::GetHelpLong();
1306fac939e9SEnrico Granata   }
1307fac939e9SEnrico Granata 
13085a988416SJim Ingham protected:
1309b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
1310b9c1b51eSKate Stone                  CommandReturnObject &result) override {
1311223383edSEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1312223383edSEnrico Granata 
1313223383edSEnrico Granata     Error error;
1314223383edSEnrico Granata 
131570f11f88SJim Ingham     result.SetStatus(eReturnStatusInvalid);
131670f11f88SJim Ingham 
1317b9c1b51eSKate Stone     if (!scripter ||
1318b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1319b9c1b51eSKate Stone                                          raw_command_line, m_synchro, result,
1320b9c1b51eSKate Stone                                          error, m_exe_ctx)) {
1321223383edSEnrico Granata       result.AppendError(error.AsCString());
1322223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1323b9c1b51eSKate Stone     } else {
132470f11f88SJim Ingham       // Don't change the status if the command already set it...
1325b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1326b9c1b51eSKate Stone         if (result.GetOutputData() == nullptr ||
1327b9c1b51eSKate Stone             result.GetOutputData()[0] == '\0')
1328223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
132970f11f88SJim Ingham         else
133070f11f88SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishResult);
133170f11f88SJim Ingham       }
133270f11f88SJim Ingham     }
1333223383edSEnrico Granata 
1334223383edSEnrico Granata     return result.Succeeded();
1335223383edSEnrico Granata   }
1336223383edSEnrico Granata 
13376e3d8e7fSEugene Zelenko private:
13386e3d8e7fSEugene Zelenko   std::string m_function_name;
13396e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
13406e3d8e7fSEugene Zelenko   bool m_fetched_help_long;
1341223383edSEnrico Granata };
1342223383edSEnrico Granata 
1343b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw {
13449fe00e52SEnrico Granata public:
13459fe00e52SEnrico Granata   CommandObjectScriptingObject(CommandInterpreter &interpreter,
13469fe00e52SEnrico Granata                                std::string name,
13470641ca1aSZachary Turner                                StructuredData::GenericSP cmd_obj_sp,
1348b9c1b51eSKate Stone                                ScriptedCommandSynchronicity synch)
1349b9c1b51eSKate Stone       : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1350b9c1b51eSKate Stone         m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1351b9c1b51eSKate Stone         m_fetched_help_long(false) {
13529fe00e52SEnrico Granata     StreamString stream;
13539fe00e52SEnrico Granata     stream.Printf("For more information run 'help %s'", name.c_str());
13549fe00e52SEnrico Granata     SetHelp(stream.GetData());
1355e87764f2SEnrico Granata     if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1356e87764f2SEnrico Granata       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
13579fe00e52SEnrico Granata   }
13589fe00e52SEnrico Granata 
13596e3d8e7fSEugene Zelenko   ~CommandObjectScriptingObject() override = default;
13609fe00e52SEnrico Granata 
1361b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
13629fe00e52SEnrico Granata 
1363b9c1b51eSKate Stone   StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
13649fe00e52SEnrico Granata 
1365b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
13669fe00e52SEnrico Granata 
1367b9c1b51eSKate Stone   const char *GetHelp() override {
1368b9c1b51eSKate Stone     if (!m_fetched_help_short) {
13696f79bb2dSEnrico Granata       ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1370b9c1b51eSKate Stone       if (scripter) {
13716f79bb2dSEnrico Granata         std::string docstring;
1372b9c1b51eSKate Stone         m_fetched_help_short =
1373b9c1b51eSKate Stone             scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
13746f79bb2dSEnrico Granata         if (!docstring.empty())
1375bfb75e9bSEnrico Granata           SetHelp(docstring.c_str());
13766f79bb2dSEnrico Granata       }
13776f79bb2dSEnrico Granata     }
13786f79bb2dSEnrico Granata     return CommandObjectRaw::GetHelp();
13796f79bb2dSEnrico Granata   }
13806f79bb2dSEnrico Granata 
1381b9c1b51eSKate Stone   const char *GetHelpLong() override {
1382b9c1b51eSKate Stone     if (!m_fetched_help_long) {
13836f79bb2dSEnrico Granata       ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1384b9c1b51eSKate Stone       if (scripter) {
13856f79bb2dSEnrico Granata         std::string docstring;
1386b9c1b51eSKate Stone         m_fetched_help_long =
1387b9c1b51eSKate Stone             scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
13886f79bb2dSEnrico Granata         if (!docstring.empty())
1389bfb75e9bSEnrico Granata           SetHelpLong(docstring.c_str());
13906f79bb2dSEnrico Granata       }
13916f79bb2dSEnrico Granata     }
13929fe00e52SEnrico Granata     return CommandObjectRaw::GetHelpLong();
13939fe00e52SEnrico Granata   }
13949fe00e52SEnrico Granata 
13959fe00e52SEnrico Granata protected:
1396b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
1397b9c1b51eSKate Stone                  CommandReturnObject &result) override {
13989fe00e52SEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
13999fe00e52SEnrico Granata 
14009fe00e52SEnrico Granata     Error error;
14019fe00e52SEnrico Granata 
14029fe00e52SEnrico Granata     result.SetStatus(eReturnStatusInvalid);
14039fe00e52SEnrico Granata 
1404b9c1b51eSKate Stone     if (!scripter ||
1405b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1406b9c1b51eSKate Stone                                          m_synchro, result, error, m_exe_ctx)) {
14079fe00e52SEnrico Granata       result.AppendError(error.AsCString());
14089fe00e52SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1409b9c1b51eSKate Stone     } else {
14109fe00e52SEnrico Granata       // Don't change the status if the command already set it...
1411b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1412b9c1b51eSKate Stone         if (result.GetOutputData() == nullptr ||
1413b9c1b51eSKate Stone             result.GetOutputData()[0] == '\0')
14149fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
14159fe00e52SEnrico Granata         else
14169fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishResult);
14179fe00e52SEnrico Granata       }
14189fe00e52SEnrico Granata     }
14199fe00e52SEnrico Granata 
14209fe00e52SEnrico Granata     return result.Succeeded();
14219fe00e52SEnrico Granata   }
14229fe00e52SEnrico Granata 
14236e3d8e7fSEugene Zelenko private:
14246e3d8e7fSEugene Zelenko   StructuredData::GenericSP m_cmd_obj_sp;
14256e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
14266e3d8e7fSEugene Zelenko   bool m_fetched_help_short : 1;
14276e3d8e7fSEugene Zelenko   bool m_fetched_help_long : 1;
14289fe00e52SEnrico Granata };
14299fe00e52SEnrico Granata 
1430a9dbf432SEnrico Granata //-------------------------------------------------------------------------
1431a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport
1432a9dbf432SEnrico Granata //-------------------------------------------------------------------------
1433a9dbf432SEnrico Granata 
1434*1f0f5b5bSZachary Turner OptionDefinition g_script_import_options[] = {
1435*1f0f5b5bSZachary Turner     // clang-format off
1436*1f0f5b5bSZachary Turner   { 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." },
1437*1f0f5b5bSZachary Turner     // clang-format on
1438*1f0f5b5bSZachary Turner };
1439*1f0f5b5bSZachary Turner 
1440b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed {
14415a988416SJim Ingham public:
1442b9c1b51eSKate Stone   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1443b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script import",
1444b9c1b51eSKate Stone                             "Import a scripting module in LLDB.", nullptr),
1445b9c1b51eSKate Stone         m_options() {
14465a988416SJim Ingham     CommandArgumentEntry arg1;
14475a988416SJim Ingham     CommandArgumentData cmd_arg;
14485a988416SJim Ingham 
14495a988416SJim Ingham     // Define the first (and only) variant of this arg.
14505a988416SJim Ingham     cmd_arg.arg_type = eArgTypeFilename;
14513b00e35bSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlus;
14525a988416SJim Ingham 
1453b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1454b9c1b51eSKate Stone     // argument entry.
14555a988416SJim Ingham     arg1.push_back(cmd_arg);
14565a988416SJim Ingham 
14575a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
14585a988416SJim Ingham     m_arguments.push_back(arg1);
14595a988416SJim Ingham   }
14605a988416SJim Ingham 
14616e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptImport() override = default;
14625a988416SJim Ingham 
1463b9c1b51eSKate Stone   int HandleArgumentCompletion(Args &input, int &cursor_index,
14645a988416SJim Ingham                                int &cursor_char_position,
14655a988416SJim Ingham                                OptionElementVector &opt_element_vector,
1466b9c1b51eSKate Stone                                int match_start_point, int max_return_elements,
14675a988416SJim Ingham                                bool &word_complete,
1468b9c1b51eSKate Stone                                StringList &matches) override {
14695a988416SJim Ingham     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
14705a988416SJim Ingham     completion_str.erase(cursor_char_position);
14715a988416SJim Ingham 
1472b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
1473b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1474b9c1b51eSKate Stone         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1475b9c1b51eSKate Stone         word_complete, matches);
14765a988416SJim Ingham     return matches.GetSize();
14775a988416SJim Ingham   }
14785a988416SJim Ingham 
1479b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
14805a988416SJim Ingham 
14815a988416SJim Ingham protected:
1482b9c1b51eSKate Stone   class CommandOptions : public Options {
14830a305db7SEnrico Granata   public:
1484b9c1b51eSKate Stone     CommandOptions() : Options() {}
14850a305db7SEnrico Granata 
14866e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
14870a305db7SEnrico Granata 
1488b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1489b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
14900a305db7SEnrico Granata       Error error;
14913bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
14920a305db7SEnrico Granata 
1493b9c1b51eSKate Stone       switch (short_option) {
14940a305db7SEnrico Granata       case 'r':
14950a305db7SEnrico Granata         m_allow_reload = true;
14960a305db7SEnrico Granata         break;
14970a305db7SEnrico Granata       default:
1498b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1499b9c1b51eSKate Stone                                        short_option);
15000a305db7SEnrico Granata         break;
15010a305db7SEnrico Granata       }
15020a305db7SEnrico Granata 
15030a305db7SEnrico Granata       return error;
15040a305db7SEnrico Granata     }
15050a305db7SEnrico Granata 
1506b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1507e0c70f1bSEnrico Granata       m_allow_reload = true;
15080a305db7SEnrico Granata     }
15090a305db7SEnrico Granata 
1510*1f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1511*1f0f5b5bSZachary Turner       return g_script_import_options;
1512*1f0f5b5bSZachary Turner     }
15130a305db7SEnrico Granata 
15140a305db7SEnrico Granata     // Instance variables to hold the values for command options.
15150a305db7SEnrico Granata 
15160a305db7SEnrico Granata     bool m_allow_reload;
15170a305db7SEnrico Granata   };
15180a305db7SEnrico Granata 
1519b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1520b9c1b51eSKate Stone     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1521b9c1b51eSKate Stone         lldb::eScriptLanguagePython) {
1522b9c1b51eSKate Stone       result.AppendError("only scripting language supported for module "
1523b9c1b51eSKate Stone                          "importing is currently Python");
1524a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1525a9dbf432SEnrico Granata       return false;
1526a9dbf432SEnrico Granata     }
1527a9dbf432SEnrico Granata 
15285a988416SJim Ingham     size_t argc = command.GetArgumentCount();
1529b9c1b51eSKate Stone     if (0 == argc) {
15303b00e35bSEnrico Granata       result.AppendError("command script import needs one or more arguments");
1531a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1532a9dbf432SEnrico Granata       return false;
1533a9dbf432SEnrico Granata     }
1534a9dbf432SEnrico Granata 
1535b9c1b51eSKate Stone     for (size_t i = 0; i < argc; i++) {
15363b00e35bSEnrico Granata       std::string path = command.GetArgumentAtIndex(i);
1537a9dbf432SEnrico Granata       Error error;
1538a9dbf432SEnrico Granata 
1539c9d645d3SGreg Clayton       const bool init_session = true;
1540b9c1b51eSKate Stone       // FIXME: this is necessary because CommandObject::CheckRequirements()
1541b9c1b51eSKate Stone       // assumes that
1542b9c1b51eSKate Stone       // commands won't ever be recursively invoked, but it's actually possible
1543b9c1b51eSKate Stone       // to craft
1544b9c1b51eSKate Stone       // a Python script that does other "command script imports" in
1545b9c1b51eSKate Stone       // __lldb_init_module
1546b9c1b51eSKate Stone       // the real fix is to have recursive commands possible with a
1547b9c1b51eSKate Stone       // CommandInvocation object
1548b9c1b51eSKate Stone       // separate from the CommandObject itself, so that recursive command
1549b9c1b51eSKate Stone       // invocations
1550b9c1b51eSKate Stone       // won't stomp on each other (wrt to execution contents, options, and
1551b9c1b51eSKate Stone       // more)
1552078551c7SEnrico Granata       m_exe_ctx.Clear();
1553b9c1b51eSKate Stone       if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1554b9c1b51eSKate Stone               path.c_str(), m_options.m_allow_reload, init_session, error)) {
1555a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1556b9c1b51eSKate Stone       } else {
1557b9c1b51eSKate Stone         result.AppendErrorWithFormat("module importing failed: %s",
1558b9c1b51eSKate Stone                                      error.AsCString());
1559a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusFailed);
1560a9dbf432SEnrico Granata       }
15613b00e35bSEnrico Granata     }
1562a9dbf432SEnrico Granata 
1563a9dbf432SEnrico Granata     return result.Succeeded();
1564a9dbf432SEnrico Granata   }
15650a305db7SEnrico Granata 
15665a988416SJim Ingham   CommandOptions m_options;
1567a9dbf432SEnrico Granata };
1568223383edSEnrico Granata 
1569223383edSEnrico Granata //-------------------------------------------------------------------------
1570223383edSEnrico Granata // CommandObjectCommandsScriptAdd
1571223383edSEnrico Granata //-------------------------------------------------------------------------
1572223383edSEnrico Granata 
1573*1f0f5b5bSZachary Turner static OptionEnumValueElement g_script_synchro_type[] = {
1574*1f0f5b5bSZachary Turner     {eScriptedCommandSynchronicitySynchronous, "synchronous",
1575*1f0f5b5bSZachary Turner      "Run synchronous"},
1576*1f0f5b5bSZachary Turner     {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1577*1f0f5b5bSZachary Turner      "Run asynchronous"},
1578*1f0f5b5bSZachary Turner     {eScriptedCommandSynchronicityCurrentValue, "current",
1579*1f0f5b5bSZachary Turner      "Do not alter current setting"},
1580*1f0f5b5bSZachary Turner     {0, nullptr, nullptr}};
1581*1f0f5b5bSZachary Turner 
1582*1f0f5b5bSZachary Turner static OptionDefinition g_script_add_options[] = {
1583*1f0f5b5bSZachary Turner     // clang-format off
1584*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_1,   false, "function",      'f', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypePythonFunction,               "Name of the Python function to bind to this command name." },
1585*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_2,   false, "class",         'c', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypePythonClass,                  "Name of the Python class to bind to this command name." },
1586*1f0f5b5bSZachary Turner   { LLDB_OPT_SET_1,   false, "help"  ,        'h', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypeHelpText,                     "The help text to display for this command." },
1587*1f0f5b5bSZachary Turner   { 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." },
1588*1f0f5b5bSZachary Turner     // clang-format on
1589*1f0f5b5bSZachary Turner };
1590*1f0f5b5bSZachary Turner 
1591b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1592b9c1b51eSKate Stone                                        public IOHandlerDelegateMultiline {
15935a988416SJim Ingham public:
1594b9c1b51eSKate Stone   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1595b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script add",
15965a988416SJim Ingham                             "Add a scripted function as an LLDB command.",
15976e3d8e7fSEugene Zelenko                             nullptr),
1598b9c1b51eSKate Stone         IOHandlerDelegateMultiline("DONE"), m_options() {
15995a988416SJim Ingham     CommandArgumentEntry arg1;
16005a988416SJim Ingham     CommandArgumentData cmd_arg;
16015a988416SJim Ingham 
16025a988416SJim Ingham     // Define the first (and only) variant of this arg.
16035a988416SJim Ingham     cmd_arg.arg_type = eArgTypeCommandName;
16045a988416SJim Ingham     cmd_arg.arg_repetition = eArgRepeatPlain;
16055a988416SJim Ingham 
1606b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1607b9c1b51eSKate Stone     // argument entry.
16085a988416SJim Ingham     arg1.push_back(cmd_arg);
16095a988416SJim Ingham 
16105a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
16115a988416SJim Ingham     m_arguments.push_back(arg1);
16125a988416SJim Ingham   }
16135a988416SJim Ingham 
16146e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptAdd() override = default;
16155a988416SJim Ingham 
1616b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
16175a988416SJim Ingham 
16185a988416SJim Ingham protected:
1619b9c1b51eSKate Stone   class CommandOptions : public Options {
1620223383edSEnrico Granata   public:
1621b9c1b51eSKate Stone     CommandOptions()
1622b9c1b51eSKate Stone         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1623b9c1b51eSKate Stone           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1624223383edSEnrico Granata 
16256e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1626223383edSEnrico Granata 
1627b9c1b51eSKate Stone     Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1628b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
1629223383edSEnrico Granata       Error error;
16303bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1631223383edSEnrico Granata 
1632b9c1b51eSKate Stone       switch (short_option) {
1633223383edSEnrico Granata       case 'f':
1634735152e3SEnrico Granata         if (option_arg)
1635735152e3SEnrico Granata           m_funct_name.assign(option_arg);
1636735152e3SEnrico Granata         break;
16379fe00e52SEnrico Granata       case 'c':
16389fe00e52SEnrico Granata         if (option_arg)
16399fe00e52SEnrico Granata           m_class_name.assign(option_arg);
16409fe00e52SEnrico Granata         break;
1641735152e3SEnrico Granata       case 'h':
1642735152e3SEnrico Granata         if (option_arg)
1643735152e3SEnrico Granata           m_short_help.assign(option_arg);
1644223383edSEnrico Granata         break;
16450a305db7SEnrico Granata       case 's':
1646b9c1b51eSKate Stone         m_synchronicity =
1647b9c1b51eSKate Stone             (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
1648*1f0f5b5bSZachary Turner                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
16490a305db7SEnrico Granata         if (!error.Success())
1650b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1651b9c1b51eSKate Stone               "unrecognized value for synchronicity '%s'", option_arg);
16520a305db7SEnrico Granata         break;
1653223383edSEnrico Granata       default:
1654b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1655b9c1b51eSKate Stone                                        short_option);
1656223383edSEnrico Granata         break;
1657223383edSEnrico Granata       }
1658223383edSEnrico Granata 
1659223383edSEnrico Granata       return error;
1660223383edSEnrico Granata     }
1661223383edSEnrico Granata 
1662b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
16639fe00e52SEnrico Granata       m_class_name.clear();
1664735152e3SEnrico Granata       m_funct_name.clear();
1665735152e3SEnrico Granata       m_short_help.clear();
166644d93782SGreg Clayton       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1667223383edSEnrico Granata     }
1668223383edSEnrico Granata 
1669*1f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1670*1f0f5b5bSZachary Turner       return g_script_add_options;
1671*1f0f5b5bSZachary Turner     }
1672223383edSEnrico Granata 
1673223383edSEnrico Granata     // Instance variables to hold the values for command options.
1674223383edSEnrico Granata 
16759fe00e52SEnrico Granata     std::string m_class_name;
1676223383edSEnrico Granata     std::string m_funct_name;
1677735152e3SEnrico Granata     std::string m_short_help;
167844d93782SGreg Clayton     ScriptedCommandSynchronicity m_synchronicity;
1679223383edSEnrico Granata   };
1680223383edSEnrico Granata 
1681b9c1b51eSKate Stone   void IOHandlerActivated(IOHandler &io_handler) override {
168244d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1683b9c1b51eSKate Stone     if (output_sp) {
168444d93782SGreg Clayton       output_sp->PutCString(g_python_command_instructions);
168544d93782SGreg Clayton       output_sp->Flush();
1686223383edSEnrico Granata     }
1687223383edSEnrico Granata   }
1688223383edSEnrico Granata 
1689b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1690b9c1b51eSKate Stone                               std::string &data) override {
169144d93782SGreg Clayton     StreamFileSP error_sp = io_handler.GetErrorStreamFile();
169244d93782SGreg Clayton 
169344d93782SGreg Clayton     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1694b9c1b51eSKate Stone     if (interpreter) {
169544d93782SGreg Clayton 
169644d93782SGreg Clayton       StringList lines;
169744d93782SGreg Clayton       lines.SplitIntoLines(data);
1698b9c1b51eSKate Stone       if (lines.GetSize() > 0) {
1699a73b7df7SEnrico Granata         std::string funct_name_str;
1700b9c1b51eSKate Stone         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1701b9c1b51eSKate Stone           if (funct_name_str.empty()) {
1702b9c1b51eSKate Stone             error_sp->Printf("error: unable to obtain a function name, didn't "
1703b9c1b51eSKate Stone                              "add python command.\n");
170444d93782SGreg Clayton             error_sp->Flush();
1705b9c1b51eSKate Stone           } else {
1706223383edSEnrico Granata             // everything should be fine now, let's add this alias
1707223383edSEnrico Granata 
1708b9c1b51eSKate Stone             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1709b9c1b51eSKate Stone                 m_interpreter, m_cmd_name, funct_name_str.c_str(), m_short_help,
171044d93782SGreg Clayton                 m_synchronicity));
1711223383edSEnrico Granata 
1712b9c1b51eSKate Stone             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1713b9c1b51eSKate Stone                                               true)) {
1714b9c1b51eSKate Stone               error_sp->Printf("error: unable to add selected command, didn't "
1715b9c1b51eSKate Stone                                "add python command.\n");
171644d93782SGreg Clayton               error_sp->Flush();
1717223383edSEnrico Granata             }
1718223383edSEnrico Granata           }
1719b9c1b51eSKate Stone         } else {
1720b9c1b51eSKate Stone           error_sp->Printf(
1721b9c1b51eSKate Stone               "error: unable to create function, didn't add python command.\n");
172244d93782SGreg Clayton           error_sp->Flush();
172344d93782SGreg Clayton         }
1724b9c1b51eSKate Stone       } else {
172544d93782SGreg Clayton         error_sp->Printf("error: empty function, didn't add python command.\n");
172644d93782SGreg Clayton         error_sp->Flush();
172744d93782SGreg Clayton       }
1728b9c1b51eSKate Stone     } else {
1729b9c1b51eSKate Stone       error_sp->Printf(
1730b9c1b51eSKate Stone           "error: script interpreter missing, didn't add python command.\n");
173144d93782SGreg Clayton       error_sp->Flush();
173244d93782SGreg Clayton     }
173344d93782SGreg Clayton 
173444d93782SGreg Clayton     io_handler.SetIsDone(true);
173544d93782SGreg Clayton   }
1736223383edSEnrico Granata 
17375a988416SJim Ingham protected:
1738b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1739b9c1b51eSKate Stone     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1740b9c1b51eSKate Stone         lldb::eScriptLanguagePython) {
1741b9c1b51eSKate Stone       result.AppendError("only scripting language supported for scripted "
1742b9c1b51eSKate Stone                          "commands is currently Python");
174399f0b8f9SEnrico Granata       result.SetStatus(eReturnStatusFailed);
174499f0b8f9SEnrico Granata       return false;
174599f0b8f9SEnrico Granata     }
174699f0b8f9SEnrico Granata 
17475a988416SJim Ingham     size_t argc = command.GetArgumentCount();
1748223383edSEnrico Granata 
1749b9c1b51eSKate Stone     if (argc != 1) {
1750223383edSEnrico Granata       result.AppendError("'command script add' requires one argument");
1751223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1752223383edSEnrico Granata       return false;
1753223383edSEnrico Granata     }
1754223383edSEnrico Granata 
1755735152e3SEnrico Granata     // Store the options in case we get multi-line input
175644d93782SGreg Clayton     m_cmd_name = command.GetArgumentAtIndex(0);
1757735152e3SEnrico Granata     m_short_help.assign(m_options.m_short_help);
175844d93782SGreg Clayton     m_synchronicity = m_options.m_synchronicity;
1759223383edSEnrico Granata 
1760b9c1b51eSKate Stone     if (m_options.m_class_name.empty()) {
1761b9c1b51eSKate Stone       if (m_options.m_funct_name.empty()) {
1762b9c1b51eSKate Stone         m_interpreter.GetPythonCommandsFromIOHandler(
1763b9c1b51eSKate Stone             "     ",  // Prompt
176444d93782SGreg Clayton             *this,    // IOHandlerDelegate
176544d93782SGreg Clayton             true,     // Run IOHandler in async mode
1766b9c1b51eSKate Stone             nullptr); // Baton for the "io_handler" that will be passed back
1767b9c1b51eSKate Stone                       // into our IOHandlerDelegate functions
1768b9c1b51eSKate Stone       } else {
1769b9c1b51eSKate Stone         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1770b9c1b51eSKate Stone             m_interpreter, m_cmd_name, m_options.m_funct_name,
1771b9c1b51eSKate Stone             m_options.m_short_help, m_synchronicity));
1772b9c1b51eSKate Stone         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1773223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1774b9c1b51eSKate Stone         } else {
1775223383edSEnrico Granata           result.AppendError("cannot add command");
1776223383edSEnrico Granata           result.SetStatus(eReturnStatusFailed);
1777223383edSEnrico Granata         }
1778223383edSEnrico Granata       }
1779b9c1b51eSKate Stone     } else {
1780b9c1b51eSKate Stone       ScriptInterpreter *interpreter =
1781b9c1b51eSKate Stone           GetCommandInterpreter().GetScriptInterpreter();
1782b9c1b51eSKate Stone       if (!interpreter) {
17839fe00e52SEnrico Granata         result.AppendError("cannot find ScriptInterpreter");
17849fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17859fe00e52SEnrico Granata         return false;
17869fe00e52SEnrico Granata       }
17879fe00e52SEnrico Granata 
1788b9c1b51eSKate Stone       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1789b9c1b51eSKate Stone           m_options.m_class_name.c_str());
1790b9c1b51eSKate Stone       if (!cmd_obj_sp) {
17919fe00e52SEnrico Granata         result.AppendError("cannot create helper object");
17929fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17939fe00e52SEnrico Granata         return false;
17949fe00e52SEnrico Granata       }
17959fe00e52SEnrico Granata 
1796b9c1b51eSKate Stone       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1797b9c1b51eSKate Stone           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1798b9c1b51eSKate Stone       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
17999fe00e52SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1800b9c1b51eSKate Stone       } else {
18019fe00e52SEnrico Granata         result.AppendError("cannot add command");
18029fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
18039fe00e52SEnrico Granata       }
18049fe00e52SEnrico Granata     }
1805223383edSEnrico Granata 
1806223383edSEnrico Granata     return result.Succeeded();
1807223383edSEnrico Granata   }
18085a988416SJim Ingham 
18095a988416SJim Ingham   CommandOptions m_options;
181044d93782SGreg Clayton   std::string m_cmd_name;
1811735152e3SEnrico Granata   std::string m_short_help;
181244d93782SGreg Clayton   ScriptedCommandSynchronicity m_synchronicity;
1813223383edSEnrico Granata };
1814223383edSEnrico Granata 
1815223383edSEnrico Granata //-------------------------------------------------------------------------
1816223383edSEnrico Granata // CommandObjectCommandsScriptList
1817223383edSEnrico Granata //-------------------------------------------------------------------------
1818223383edSEnrico Granata 
1819b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed {
1820223383edSEnrico Granata public:
1821b9c1b51eSKate Stone   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1822b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script list",
1823b9c1b51eSKate Stone                             "List defined scripted commands.", nullptr) {}
1824223383edSEnrico Granata 
18256e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptList() override = default;
1826223383edSEnrico Granata 
1827b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1828b9c1b51eSKate Stone     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1829223383edSEnrico Granata 
1830223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1831223383edSEnrico Granata 
1832223383edSEnrico Granata     return true;
1833223383edSEnrico Granata   }
1834223383edSEnrico Granata };
1835223383edSEnrico Granata 
1836223383edSEnrico Granata //-------------------------------------------------------------------------
1837223383edSEnrico Granata // CommandObjectCommandsScriptClear
1838223383edSEnrico Granata //-------------------------------------------------------------------------
1839223383edSEnrico Granata 
1840b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1841223383edSEnrico Granata public:
1842b9c1b51eSKate Stone   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1843b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script clear",
1844b9c1b51eSKate Stone                             "Delete all scripted commands.", nullptr) {}
1845223383edSEnrico Granata 
18466e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptClear() override = default;
1847223383edSEnrico Granata 
18485a988416SJim Ingham protected:
1849b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1850223383edSEnrico Granata     m_interpreter.RemoveAllUser();
1851223383edSEnrico Granata 
1852223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1853223383edSEnrico Granata 
1854223383edSEnrico Granata     return true;
1855223383edSEnrico Granata   }
1856223383edSEnrico Granata };
1857223383edSEnrico Granata 
1858223383edSEnrico Granata //-------------------------------------------------------------------------
1859223383edSEnrico Granata // CommandObjectCommandsScriptDelete
1860223383edSEnrico Granata //-------------------------------------------------------------------------
1861223383edSEnrico Granata 
1862b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1863223383edSEnrico Granata public:
1864b9c1b51eSKate Stone   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1865b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script delete",
1866b9c1b51eSKate Stone                             "Delete a scripted command.", nullptr) {
1867223383edSEnrico Granata     CommandArgumentEntry arg1;
1868223383edSEnrico Granata     CommandArgumentData cmd_arg;
1869223383edSEnrico Granata 
1870223383edSEnrico Granata     // Define the first (and only) variant of this arg.
1871223383edSEnrico Granata     cmd_arg.arg_type = eArgTypeCommandName;
1872223383edSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlain;
1873223383edSEnrico Granata 
1874b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1875b9c1b51eSKate Stone     // argument entry.
1876223383edSEnrico Granata     arg1.push_back(cmd_arg);
1877223383edSEnrico Granata 
1878223383edSEnrico Granata     // Push the data for the first argument into the m_arguments vector.
1879223383edSEnrico Granata     m_arguments.push_back(arg1);
1880223383edSEnrico Granata   }
1881223383edSEnrico Granata 
18826e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptDelete() override = default;
1883223383edSEnrico Granata 
18845a988416SJim Ingham protected:
1885b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1886223383edSEnrico Granata 
18875a988416SJim Ingham     size_t argc = command.GetArgumentCount();
1888223383edSEnrico Granata 
1889b9c1b51eSKate Stone     if (argc != 1) {
1890223383edSEnrico Granata       result.AppendError("'command script delete' requires one argument");
1891223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1892223383edSEnrico Granata       return false;
1893223383edSEnrico Granata     }
1894223383edSEnrico Granata 
18955a988416SJim Ingham     const char *cmd_name = command.GetArgumentAtIndex(0);
1896223383edSEnrico Granata 
1897b9c1b51eSKate Stone     if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() &&
1898b9c1b51eSKate Stone         m_interpreter.UserCommandExists(cmd_name)) {
1899223383edSEnrico Granata       m_interpreter.RemoveUser(cmd_name);
1900223383edSEnrico Granata       result.SetStatus(eReturnStatusSuccessFinishResult);
1901b9c1b51eSKate Stone     } else {
1902223383edSEnrico Granata       result.AppendErrorWithFormat("command %s not found", cmd_name);
1903223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1904223383edSEnrico Granata     }
1905223383edSEnrico Granata 
1906223383edSEnrico Granata     return result.Succeeded();
1907223383edSEnrico Granata   }
1908223383edSEnrico Granata };
1909223383edSEnrico Granata 
1910223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript
1911223383edSEnrico Granata 
1912223383edSEnrico Granata //-------------------------------------------------------------------------
1913223383edSEnrico Granata // CommandObjectMultiwordCommandsScript
1914223383edSEnrico Granata //-------------------------------------------------------------------------
1915223383edSEnrico Granata 
1916b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1917223383edSEnrico Granata public:
19187428a18cSKate Stone   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1919b9c1b51eSKate Stone       : CommandObjectMultiword(
1920b9c1b51eSKate Stone             interpreter, "command script", "Commands for managing custom "
1921b9c1b51eSKate Stone                                            "commands implemented by "
1922b9c1b51eSKate Stone                                            "interpreter scripts.",
1923b9c1b51eSKate Stone             "command script <subcommand> [<subcommand-options>]") {
1924b9c1b51eSKate Stone     LoadSubCommand("add", CommandObjectSP(
1925b9c1b51eSKate Stone                               new CommandObjectCommandsScriptAdd(interpreter)));
1926b9c1b51eSKate Stone     LoadSubCommand(
1927b9c1b51eSKate Stone         "delete",
1928b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1929b9c1b51eSKate Stone     LoadSubCommand(
1930b9c1b51eSKate Stone         "clear",
1931b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1932b9c1b51eSKate Stone     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1933b9c1b51eSKate Stone                                interpreter)));
1934b9c1b51eSKate Stone     LoadSubCommand(
1935b9c1b51eSKate Stone         "import",
1936b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1937223383edSEnrico Granata   }
1938223383edSEnrico Granata 
19396e3d8e7fSEugene Zelenko   ~CommandObjectMultiwordCommandsScript() override = default;
1940223383edSEnrico Granata };
1941223383edSEnrico Granata 
1942ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
1943ebc09c36SJim Ingham 
1944ebc09c36SJim Ingham //-------------------------------------------------------------------------
1945ebc09c36SJim Ingham // CommandObjectMultiwordCommands
1946ebc09c36SJim Ingham //-------------------------------------------------------------------------
1947ebc09c36SJim Ingham 
1948b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1949b9c1b51eSKate Stone     CommandInterpreter &interpreter)
1950b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "command",
1951b9c1b51eSKate Stone                              "Commands for managing custom LLDB commands.",
1952b9c1b51eSKate Stone                              "command <subcommand> [<subcommand-options>]") {
1953b9c1b51eSKate Stone   LoadSubCommand("source",
1954b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1955b9c1b51eSKate Stone   LoadSubCommand("alias",
1956b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1957b9c1b51eSKate Stone   LoadSubCommand("unalias", CommandObjectSP(
1958b9c1b51eSKate Stone                                 new CommandObjectCommandsUnalias(interpreter)));
1959b9c1b51eSKate Stone   LoadSubCommand("delete",
1960b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1961b9c1b51eSKate Stone   LoadSubCommand(
1962b9c1b51eSKate Stone       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1963b9c1b51eSKate Stone   LoadSubCommand("history", CommandObjectSP(
1964b9c1b51eSKate Stone                                 new CommandObjectCommandsHistory(interpreter)));
1965b9c1b51eSKate Stone   LoadSubCommand(
1966b9c1b51eSKate Stone       "script",
1967b9c1b51eSKate Stone       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1968ebc09c36SJim Ingham }
1969ebc09c36SJim Ingham 
19706e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1971