1696bd635SAlexander Shaposhnikov //===-- CommandObjectCommands.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 
391f0f5b5bSZachary Turner static OptionDefinition g_history_options[] = {
401f0f5b5bSZachary Turner     // clang-format off
411f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "count",       'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
421f0f5b5bSZachary 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)." },
431f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "end-index",   'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
441f0f5b5bSZachary Turner   { LLDB_OPT_SET_2, false, "clear",       'C', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeBoolean,         "Clears the current command history." },
451f0f5b5bSZachary Turner     // clang-format on
461f0f5b5bSZachary Turner };
471f0f5b5bSZachary 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 
69fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef 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':
76fe11483bSZachary Turner         error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
77a5a97ebeSJim Ingham         break;
78a5a97ebeSJim Ingham       case 's':
79fe11483bSZachary Turner         if (option_arg == "end") {
807594f14fSEnrico Granata           m_start_idx.SetCurrentValue(UINT64_MAX);
817594f14fSEnrico Granata           m_start_idx.SetOptionWasSet();
82b9c1b51eSKate Stone         } else
83fe11483bSZachary Turner           error = m_start_idx.SetValueFromString(option_arg,
84b9c1b51eSKate Stone                                                  eVarSetOperationAssign);
857594f14fSEnrico Granata         break;
867594f14fSEnrico Granata       case 'e':
87fe11483bSZachary Turner         error =
88fe11483bSZachary Turner             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 
1101f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
11170602439SZachary Turner       return llvm::makeArrayRef(g_history_options);
1121f0f5b5bSZachary 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 
1941f0f5b5bSZachary Turner static OptionDefinition g_source_options[] = {
1951f0f5b5bSZachary Turner     // clang-format off
1961f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "stop-on-error",    'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
1971f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
1981f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "silent-run",       's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
1991f0f5b5bSZachary Turner     // clang-format on
2001f0f5b5bSZachary Turner };
2011f0f5b5bSZachary 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 {
2384574a890SZachary Turner     auto completion_str = input[cursor_index].ref;
2394574a890SZachary Turner     completion_str = completion_str.take_front(cursor_char_position);
2405a988416SJim Ingham 
241b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
242b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2434574a890SZachary Turner         completion_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 
259fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef 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':
266fe11483bSZachary Turner         error = m_stop_on_error.SetValueFromString(option_arg);
267e16c50a1SJim Ingham         break;
268340b0309SGreg Clayton 
269e16c50a1SJim Ingham       case 'c':
270fe11483bSZachary Turner         error = m_stop_on_continue.SetValueFromString(option_arg);
271e16c50a1SJim Ingham         break;
272340b0309SGreg Clayton 
27360986174SMichael Sartain       case 's':
274fe11483bSZachary Turner         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 
2921f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
29370602439SZachary Turner       return llvm::makeArrayRef(g_source_options);
2941f0f5b5bSZachary 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 {
3044574a890SZachary Turner     if (command.GetArgumentCount() != 1) {
3054574a890SZachary Turner       result.AppendErrorWithFormat(
3064574a890SZachary Turner           "'%s' takes exactly one executable filename argument.\n",
3074574a890SZachary Turner           GetCommandName().str().c_str());
3084574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
3094574a890SZachary Turner       return false;
3104574a890SZachary Turner     }
311ebc09c36SJim Ingham 
3124574a890SZachary Turner     FileSpec cmd_file(command[0].ref, true);
3136e3d8e7fSEugene Zelenko     ExecutionContext *exe_ctx = nullptr; // Just use the default context.
314ebc09c36SJim Ingham 
315340b0309SGreg Clayton     // If any options were set, then use them
316340b0309SGreg Clayton     if (m_options.m_stop_on_error.OptionWasSet() ||
317340b0309SGreg Clayton         m_options.m_silent_run.OptionWasSet() ||
318b9c1b51eSKate Stone         m_options.m_stop_on_continue.OptionWasSet()) {
319340b0309SGreg Clayton       // Use user set settings
32026c7bf93SJim Ingham       CommandInterpreterRunOptions options;
3214574a890SZachary Turner       options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
32226c7bf93SJim Ingham       options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
3237d8555c4SJim Ingham       options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
3247d8555c4SJim Ingham       options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
32526c7bf93SJim Ingham 
3264574a890SZachary Turner       m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
327b9c1b51eSKate Stone     } else {
328b9c1b51eSKate Stone       // No options were set, inherit any settings from nested "command
329b9c1b51eSKate Stone       // source" commands,
330340b0309SGreg Clayton       // or set to sane default settings...
33126c7bf93SJim Ingham       CommandInterpreterRunOptions options;
3324574a890SZachary Turner       m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
333ebc09c36SJim Ingham     }
334ebc09c36SJim Ingham     return result.Succeeded();
335ebc09c36SJim Ingham   }
3366e3d8e7fSEugene Zelenko 
3375a988416SJim Ingham   CommandOptions m_options;
338ebc09c36SJim Ingham };
339ebc09c36SJim Ingham 
340ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
341ebc09c36SJim Ingham //-------------------------------------------------------------------------
342ebc09c36SJim Ingham // CommandObjectCommandsAlias
343ebc09c36SJim Ingham //-------------------------------------------------------------------------
344ebc09c36SJim Ingham 
3451f0f5b5bSZachary Turner static OptionDefinition g_alias_options[] = {
3461f0f5b5bSZachary Turner     // clang-format off
3471f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "help",      'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
3481f0f5b5bSZachary Turner   { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
3491f0f5b5bSZachary Turner     // clang-format on
3501f0f5b5bSZachary Turner };
3511f0f5b5bSZachary Turner 
352b9c1b51eSKate Stone static const char *g_python_command_instructions =
353b9c1b51eSKate Stone     "Enter your Python command(s). Type 'DONE' to end.\n"
354be93a35aSEnrico Granata     "You must define a Python function with this signature:\n"
35544d93782SGreg Clayton     "def my_command_impl(debugger, args, result, internal_dict):\n";
356be93a35aSEnrico Granata 
357b9c1b51eSKate Stone class CommandObjectCommandsAlias : public CommandObjectRaw {
35845d0e238SEnrico Granata protected:
359b9c1b51eSKate Stone   class CommandOptions : public OptionGroup {
360ebc09c36SJim Ingham   public:
361b9c1b51eSKate Stone     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
36245d0e238SEnrico Granata 
36345d0e238SEnrico Granata     ~CommandOptions() override = default;
36445d0e238SEnrico Granata 
3651f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
36670602439SZachary Turner       return llvm::makeArrayRef(g_alias_options);
3671f0f5b5bSZachary Turner     }
36845d0e238SEnrico Granata 
3698cef4b0bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
370b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
37145d0e238SEnrico Granata       Error error;
37245d0e238SEnrico Granata 
3731f0f5b5bSZachary Turner       const int short_option = GetDefinitions()[option_idx].short_option;
3748cef4b0bSZachary Turner       std::string option_str(option_value);
37545d0e238SEnrico Granata 
376b9c1b51eSKate Stone       switch (short_option) {
37745d0e238SEnrico Granata       case 'h':
3788cef4b0bSZachary Turner         m_help.SetCurrentValue(option_str);
37945d0e238SEnrico Granata         m_help.SetOptionWasSet();
38045d0e238SEnrico Granata         break;
38145d0e238SEnrico Granata 
38245d0e238SEnrico Granata       case 'H':
3838cef4b0bSZachary Turner         m_long_help.SetCurrentValue(option_str);
38445d0e238SEnrico Granata         m_long_help.SetOptionWasSet();
38545d0e238SEnrico Granata         break;
38645d0e238SEnrico Granata 
38745d0e238SEnrico Granata       default:
388b9c1b51eSKate Stone         error.SetErrorStringWithFormat("invalid short option character '%c'",
389b9c1b51eSKate Stone                                        short_option);
39045d0e238SEnrico Granata         break;
39145d0e238SEnrico Granata       }
39245d0e238SEnrico Granata 
39345d0e238SEnrico Granata       return error;
39445d0e238SEnrico Granata     }
39545d0e238SEnrico Granata 
396b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
39745d0e238SEnrico Granata       m_help.Clear();
39845d0e238SEnrico Granata       m_long_help.Clear();
39945d0e238SEnrico Granata     }
40045d0e238SEnrico Granata 
40145d0e238SEnrico Granata     OptionValueString m_help;
40245d0e238SEnrico Granata     OptionValueString m_long_help;
40345d0e238SEnrico Granata   };
40445d0e238SEnrico Granata 
40545d0e238SEnrico Granata   OptionGroupOptions m_option_group;
40645d0e238SEnrico Granata   CommandOptions m_command_options;
40745d0e238SEnrico Granata 
40845d0e238SEnrico Granata public:
409b9c1b51eSKate Stone   Options *GetOptions() override { return &m_option_group; }
41045d0e238SEnrico Granata 
4117428a18cSKate Stone   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
412b9c1b51eSKate Stone       : CommandObjectRaw(
413b9c1b51eSKate Stone             interpreter, "command alias",
414a449698cSZachary Turner             "Define a custom command in terms of an existing command."),
415b9c1b51eSKate Stone         m_option_group(), m_command_options() {
41645d0e238SEnrico Granata     m_option_group.Append(&m_command_options);
41745d0e238SEnrico Granata     m_option_group.Finalize();
41845d0e238SEnrico Granata 
419ebc09c36SJim Ingham     SetHelpLong(
420ea671fbdSKate Stone         "'alias' allows the user to create a short-cut or abbreviation for long \
421ea671fbdSKate Stone commands, multi-word commands, and commands that take particular options.  \
422b9c1b51eSKate Stone Below are some simple examples of how one might use the 'alias' command:"
423b9c1b51eSKate Stone         R"(
424ea671fbdSKate Stone 
425ea671fbdSKate Stone (lldb) command alias sc script
426ea671fbdSKate Stone 
427ea671fbdSKate Stone     Creates the abbreviation 'sc' for the 'script' command.
428ea671fbdSKate Stone 
429ea671fbdSKate Stone (lldb) command alias bp breakpoint
430ea671fbdSKate Stone 
431b9c1b51eSKate Stone )"
432b9c1b51eSKate Stone         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
433ea671fbdSKate Stone breakpoint commands are two-word commands, the user would still need to \
434b9c1b51eSKate Stone enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
435b9c1b51eSKate Stone         R"(
436ea671fbdSKate Stone 
437ea671fbdSKate Stone (lldb) command alias bpl breakpoint list
438ea671fbdSKate Stone 
439ea671fbdSKate Stone     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
440ea671fbdSKate Stone 
441b9c1b51eSKate Stone )"
442b9c1b51eSKate Stone         "An alias can include some options for the command, with the values either \
443ea671fbdSKate Stone filled in at the time the alias is created, or specified as positional \
444ea671fbdSKate Stone arguments, to be filled in when the alias is invoked.  The following example \
445b9c1b51eSKate Stone shows how to create aliases with options:"
446b9c1b51eSKate Stone         R"(
447ea671fbdSKate Stone 
448ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
449ea671fbdSKate Stone 
450b9c1b51eSKate Stone )"
451b9c1b51eSKate Stone         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
452ea671fbdSKate Stone options already part of the alias.  So if the user wants to set a breakpoint \
453ea671fbdSKate Stone by file and line without explicitly having to use the -f and -l options, the \
454ea671fbdSKate Stone user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
455ea671fbdSKate Stone for the actual arguments that will be passed when the alias command is used.  \
456ea671fbdSKate Stone The number in the placeholder refers to the position/order the actual value \
457ea671fbdSKate Stone occupies when the alias is used.  All the occurrences of '%1' in the alias \
458ea671fbdSKate Stone will be replaced with the first argument, all the occurrences of '%2' in the \
459ea671fbdSKate Stone alias will be replaced with the second argument, and so on.  This also allows \
460ea671fbdSKate Stone actual arguments to be used multiple times within an alias (see 'process \
461b9c1b51eSKate Stone launch' example below)."
462b9c1b51eSKate Stone         R"(
463ea671fbdSKate Stone 
464b9c1b51eSKate Stone )"
465b9c1b51eSKate Stone         "Note: the positional arguments must substitute as whole words in the resultant \
466ea671fbdSKate Stone command, so you can't at present do something like this to append the file extension \
467b9c1b51eSKate Stone \".cpp\":"
468b9c1b51eSKate Stone         R"(
469ea671fbdSKate Stone 
470ea671fbdSKate Stone (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
471ea671fbdSKate Stone 
472b9c1b51eSKate Stone )"
473b9c1b51eSKate Stone         "For more complex aliasing, use the \"command regex\" command instead.  In the \
474ea671fbdSKate Stone 'bfl' case above, the actual file value will be filled in with the first argument \
475ea671fbdSKate Stone following 'bfl' and the actual line number value will be filled in with the second \
476b9c1b51eSKate Stone argument.  The user would use this alias as follows:"
477b9c1b51eSKate Stone         R"(
478ea671fbdSKate Stone 
479ea671fbdSKate Stone (lldb) command alias bfl breakpoint set -f %1 -l %2
480ea671fbdSKate Stone (lldb) bfl my-file.c 137
481ea671fbdSKate Stone 
482ea671fbdSKate Stone This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
483ea671fbdSKate Stone 
484ea671fbdSKate Stone Another example:
485ea671fbdSKate Stone 
486ea671fbdSKate Stone (lldb) command alias pltty process launch -s -o %1 -e %1
487ea671fbdSKate Stone (lldb) pltty /dev/tty0
488ea671fbdSKate Stone 
489ea671fbdSKate Stone     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
490ea671fbdSKate Stone 
491b9c1b51eSKate Stone )"
492b9c1b51eSKate Stone         "If the user always wanted to pass the same value to a particular option, the \
493ea671fbdSKate Stone alias could be defined with that value directly in the alias as a constant, \
494b9c1b51eSKate Stone rather than using a positional placeholder:"
495b9c1b51eSKate Stone         R"(
496ea671fbdSKate Stone 
497ea671fbdSKate Stone (lldb) command alias bl3 breakpoint set -f %1 -l 3
498ea671fbdSKate Stone 
499b9c1b51eSKate Stone     Always sets a breakpoint on line 3 of whatever file is indicated.)");
500ebc09c36SJim Ingham 
501405fe67fSCaroline Tice     CommandArgumentEntry arg1;
502405fe67fSCaroline Tice     CommandArgumentEntry arg2;
503405fe67fSCaroline Tice     CommandArgumentEntry arg3;
504405fe67fSCaroline Tice     CommandArgumentData alias_arg;
505405fe67fSCaroline Tice     CommandArgumentData cmd_arg;
506405fe67fSCaroline Tice     CommandArgumentData options_arg;
507405fe67fSCaroline Tice 
508405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
509405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
510405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
511405fe67fSCaroline Tice 
512b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
513b9c1b51eSKate Stone     // argument entry.
514405fe67fSCaroline Tice     arg1.push_back(alias_arg);
515405fe67fSCaroline Tice 
516405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
517405fe67fSCaroline Tice     cmd_arg.arg_type = eArgTypeCommandName;
518405fe67fSCaroline Tice     cmd_arg.arg_repetition = eArgRepeatPlain;
519405fe67fSCaroline Tice 
520b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
521b9c1b51eSKate Stone     // argument entry.
522405fe67fSCaroline Tice     arg2.push_back(cmd_arg);
523405fe67fSCaroline Tice 
524405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
525405fe67fSCaroline Tice     options_arg.arg_type = eArgTypeAliasOptions;
526405fe67fSCaroline Tice     options_arg.arg_repetition = eArgRepeatOptional;
527405fe67fSCaroline Tice 
528b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
529b9c1b51eSKate Stone     // argument entry.
530405fe67fSCaroline Tice     arg3.push_back(options_arg);
531405fe67fSCaroline Tice 
532405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
533405fe67fSCaroline Tice     m_arguments.push_back(arg1);
534405fe67fSCaroline Tice     m_arguments.push_back(arg2);
535405fe67fSCaroline Tice     m_arguments.push_back(arg3);
536ebc09c36SJim Ingham   }
537ebc09c36SJim Ingham 
5386e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAlias() override = default;
539ebc09c36SJim Ingham 
5405a988416SJim Ingham protected:
541b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
542b9c1b51eSKate Stone                  CommandReturnObject &result) override {
543b9c1b51eSKate Stone     if (!raw_command_line || !raw_command_line[0]) {
544d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
54545d0e238SEnrico Granata       return false;
54645d0e238SEnrico Granata     }
54745d0e238SEnrico Granata 
548e1cfbc79STodd Fiala     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
549e1cfbc79STodd Fiala     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
55045d0e238SEnrico Granata 
55145d0e238SEnrico Granata     const char *remainder = nullptr;
55245d0e238SEnrico Granata 
553b9c1b51eSKate Stone     if (raw_command_line[0] == '-') {
55445d0e238SEnrico Granata       // We have some options and these options MUST end with --.
55545d0e238SEnrico Granata       const char *end_options = nullptr;
55645d0e238SEnrico Granata       const char *s = raw_command_line;
557b9c1b51eSKate Stone       while (s && s[0]) {
55845d0e238SEnrico Granata         end_options = ::strstr(s, "--");
559b9c1b51eSKate Stone         if (end_options) {
56045d0e238SEnrico Granata           end_options += 2; // Get past the "--"
561b9c1b51eSKate Stone           if (::isspace(end_options[0])) {
56245d0e238SEnrico Granata             remainder = end_options;
56345d0e238SEnrico Granata             while (::isspace(*remainder))
56445d0e238SEnrico Granata               ++remainder;
56545d0e238SEnrico Granata             break;
56645d0e238SEnrico Granata           }
56745d0e238SEnrico Granata         }
56845d0e238SEnrico Granata         s = end_options;
56945d0e238SEnrico Granata       }
57045d0e238SEnrico Granata 
571b9c1b51eSKate Stone       if (end_options) {
572b9c1b51eSKate Stone         Args args(
573b9c1b51eSKate Stone             llvm::StringRef(raw_command_line, end_options - raw_command_line));
57445d0e238SEnrico Granata         if (!ParseOptions(args, result))
57545d0e238SEnrico Granata           return false;
57645d0e238SEnrico Granata 
577e1cfbc79STodd Fiala         Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
578b9c1b51eSKate Stone         if (error.Fail()) {
57945d0e238SEnrico Granata           result.AppendError(error.AsCString());
58045d0e238SEnrico Granata           result.SetStatus(eReturnStatusFailed);
58145d0e238SEnrico Granata           return false;
58245d0e238SEnrico Granata         }
58345d0e238SEnrico Granata       }
58445d0e238SEnrico Granata     }
58545d0e238SEnrico Granata     if (nullptr == remainder)
58645d0e238SEnrico Granata       remainder = raw_command_line;
58745d0e238SEnrico Granata 
588a01bccdbSZachary Turner     llvm::StringRef raw_command_string(remainder);
589a01bccdbSZachary Turner     Args args(raw_command_string);
590844d2303SCaroline Tice 
59111eb9c64SZachary Turner     if (args.GetArgumentCount() < 2) {
592d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
593844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
594844d2303SCaroline Tice       return false;
595844d2303SCaroline Tice     }
596844d2303SCaroline Tice 
597844d2303SCaroline Tice     // Get the alias command.
598844d2303SCaroline Tice 
5994574a890SZachary Turner     auto alias_command = args[0].ref;
6004574a890SZachary Turner     if (alias_command.startswith("-")) {
601d72e412fSEnrico Granata       result.AppendError("aliases starting with a dash are not supported");
602b9c1b51eSKate Stone       if (alias_command == "--help" || alias_command == "--long-help") {
603b9c1b51eSKate Stone         result.AppendWarning("if trying to pass options to 'command alias' add "
604b9c1b51eSKate Stone                              "a -- at the end of the options");
605d72e412fSEnrico Granata       }
606d72e412fSEnrico Granata       result.SetStatus(eReturnStatusFailed);
607d72e412fSEnrico Granata       return false;
608d72e412fSEnrico Granata     }
609844d2303SCaroline Tice 
610b9c1b51eSKate Stone     // Strip the new alias name off 'raw_command_string'  (leave it on args,
611b9c1b51eSKate Stone     // which gets passed to 'Execute', which
612844d2303SCaroline Tice     // does the stripping itself.
613844d2303SCaroline Tice     size_t pos = raw_command_string.find(alias_command);
614b9c1b51eSKate Stone     if (pos == 0) {
615844d2303SCaroline Tice       raw_command_string = raw_command_string.substr(alias_command.size());
616844d2303SCaroline Tice       pos = raw_command_string.find_first_not_of(' ');
617844d2303SCaroline Tice       if ((pos != std::string::npos) && (pos > 0))
618844d2303SCaroline Tice         raw_command_string = raw_command_string.substr(pos);
619b9c1b51eSKate Stone     } else {
620844d2303SCaroline Tice       result.AppendError("Error parsing command string.  No alias created.");
621844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
622844d2303SCaroline Tice       return false;
623844d2303SCaroline Tice     }
624844d2303SCaroline Tice 
625844d2303SCaroline Tice     // Verify that the command is alias-able.
626771ef6d4SMalcolm Parsons     if (m_interpreter.CommandExists(alias_command)) {
627b9c1b51eSKate Stone       result.AppendErrorWithFormat(
628b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
6294574a890SZachary Turner           args[0].c_str());
630844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
631844d2303SCaroline Tice       return false;
632844d2303SCaroline Tice     }
633844d2303SCaroline Tice 
634b9c1b51eSKate Stone     // Get CommandObject that is being aliased. The command name is read from
635a01bccdbSZachary Turner     // the front of raw_command_string. raw_command_string is returned with the
636a01bccdbSZachary Turner     // name of the command object stripped off the front.
637a01bccdbSZachary Turner     llvm::StringRef original_raw_command_string = raw_command_string;
638b9c1b51eSKate Stone     CommandObject *cmd_obj =
639b9c1b51eSKate Stone         m_interpreter.GetCommandObjectForCommand(raw_command_string);
640844d2303SCaroline Tice 
641b9c1b51eSKate Stone     if (!cmd_obj) {
642b9c1b51eSKate Stone       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
643b9c1b51eSKate Stone                                    "'%s' does not begin with a valid command."
644b9c1b51eSKate Stone                                    "  No alias created.",
645a01bccdbSZachary Turner                                    original_raw_command_string.str().c_str());
646844d2303SCaroline Tice       result.SetStatus(eReturnStatusFailed);
647844d2303SCaroline Tice       return false;
648b9c1b51eSKate Stone     } else if (!cmd_obj->WantsRawCommandString()) {
649b9c1b51eSKate Stone       // Note that args was initialized with the original command, and has not
650b9c1b51eSKate Stone       // been updated to this point.
651b9c1b51eSKate Stone       // Therefore can we pass it to the version of Execute that does not
652b9c1b51eSKate Stone       // need/expect raw input in the alias.
6535a988416SJim Ingham       return HandleAliasingNormalCommand(args, result);
654b9c1b51eSKate Stone     } else {
655b9c1b51eSKate Stone       return HandleAliasingRawCommand(alias_command, raw_command_string,
656b9c1b51eSKate Stone                                       *cmd_obj, result);
6575a988416SJim Ingham     }
6585a988416SJim Ingham     return result.Succeeded();
6595a988416SJim Ingham   }
6605a988416SJim Ingham 
661a01bccdbSZachary Turner   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
662a01bccdbSZachary Turner                                 llvm::StringRef raw_command_string,
663b9c1b51eSKate Stone                                 CommandObject &cmd_obj,
664b9c1b51eSKate Stone                                 CommandReturnObject &result) {
665844d2303SCaroline Tice     // Verify & handle any options/arguments passed to the alias command
666844d2303SCaroline Tice 
667b9c1b51eSKate Stone     OptionArgVectorSP option_arg_vector_sp =
668b9c1b51eSKate Stone         OptionArgVectorSP(new OptionArgVector);
669844d2303SCaroline Tice 
670b9c1b51eSKate Stone     if (CommandObjectSP cmd_obj_sp =
671b9c1b51eSKate Stone             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
672a01bccdbSZachary Turner       if (m_interpreter.AliasExists(alias_command) ||
673a01bccdbSZachary Turner           m_interpreter.UserCommandExists(alias_command)) {
674b9c1b51eSKate Stone         result.AppendWarningWithFormat(
675b9c1b51eSKate Stone             "Overwriting existing definition for '%s'.\n",
676a01bccdbSZachary Turner             alias_command.str().c_str());
677844d2303SCaroline Tice       }
678b9c1b51eSKate Stone       if (CommandAlias *alias = m_interpreter.AddAlias(
679a01bccdbSZachary Turner               alias_command, cmd_obj_sp, raw_command_string)) {
68045d0e238SEnrico Granata         if (m_command_options.m_help.OptionWasSet())
68145d0e238SEnrico Granata           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
68245d0e238SEnrico Granata         if (m_command_options.m_long_help.OptionWasSet())
68345d0e238SEnrico Granata           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
684844d2303SCaroline Tice         result.SetStatus(eReturnStatusSuccessFinishNoResult);
685b9c1b51eSKate Stone       } else {
686472362e6SCaroline Tice         result.AppendError("Unable to create requested alias.\n");
687472362e6SCaroline Tice         result.SetStatus(eReturnStatusFailed);
688472362e6SCaroline Tice       }
689212130acSEnrico Granata 
690b9c1b51eSKate Stone     } else {
691212130acSEnrico Granata       result.AppendError("Unable to create requested alias.\n");
692212130acSEnrico Granata       result.SetStatus(eReturnStatusFailed);
693212130acSEnrico Granata     }
694212130acSEnrico Granata 
695844d2303SCaroline Tice     return result.Succeeded();
696844d2303SCaroline Tice   }
697ebc09c36SJim Ingham 
698b9c1b51eSKate Stone   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
699867b185dSCaroline Tice     size_t argc = args.GetArgumentCount();
700ebc09c36SJim Ingham 
701b9c1b51eSKate Stone     if (argc < 2) {
702d72e412fSEnrico Granata       result.AppendError("'command alias' requires at least two arguments");
703ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
704ebc09c36SJim Ingham       return false;
705ebc09c36SJim Ingham     }
706ebc09c36SJim Ingham 
7074574a890SZachary Turner     // Save these in std::strings since we're going to shift them off.
7084574a890SZachary Turner     const std::string alias_command(args[0].ref);
7094574a890SZachary Turner     const std::string actual_command(args[1].ref);
710ebc09c36SJim Ingham 
711ebc09c36SJim Ingham     args.Shift(); // Shift the alias command word off the argument vector.
712ebc09c36SJim Ingham     args.Shift(); // Shift the old command word off the argument vector.
713ebc09c36SJim Ingham 
714b9c1b51eSKate Stone     // Verify that the command is alias'able, and get the appropriate command
715b9c1b51eSKate Stone     // object.
716ebc09c36SJim Ingham 
717771ef6d4SMalcolm Parsons     if (m_interpreter.CommandExists(alias_command)) {
718b9c1b51eSKate Stone       result.AppendErrorWithFormat(
719b9c1b51eSKate Stone           "'%s' is a permanent debugger command and cannot be redefined.\n",
720ebc09c36SJim Ingham           alias_command.c_str());
721ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
7224574a890SZachary Turner       return false;
7234574a890SZachary Turner     }
7244574a890SZachary Turner 
725b9c1b51eSKate Stone     CommandObjectSP command_obj_sp(
726a449698cSZachary Turner         m_interpreter.GetCommandSPExact(actual_command, true));
727ebc09c36SJim Ingham     CommandObjectSP subcommand_obj_sp;
728ebc09c36SJim Ingham     bool use_subcommand = false;
7294574a890SZachary Turner     if (!command_obj_sp) {
7304574a890SZachary Turner       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
7314574a890SZachary Turner                                    actual_command.c_str());
7324574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
7334574a890SZachary Turner       return false;
7344574a890SZachary Turner     }
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 
74011eb9c64SZachary Turner     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
7414574a890SZachary Turner       auto sub_command = args[0].ref;
74211eb9c64SZachary Turner       assert(!sub_command.empty());
7434574a890SZachary Turner       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
7444574a890SZachary Turner       if (!subcommand_obj_sp) {
745b9c1b51eSKate Stone         result.AppendErrorWithFormat(
746b9c1b51eSKate Stone             "'%s' is not a valid sub-command of '%s'.  "
747f415eeb4SCaroline Tice             "Unable to create alias.\n",
7484574a890SZachary Turner             args[0].c_str(), actual_command.c_str());
749ebc09c36SJim Ingham         result.SetStatus(eReturnStatusFailed);
750ebc09c36SJim Ingham         return false;
751ebc09c36SJim Ingham       }
7524574a890SZachary Turner 
7534574a890SZachary Turner       sub_cmd_obj = subcommand_obj_sp.get();
7544574a890SZachary Turner       use_subcommand = true;
7554574a890SZachary Turner       args.Shift(); // Shift the sub_command word off the argument vector.
7564574a890SZachary Turner       cmd_obj = sub_cmd_obj;
757ebc09c36SJim Ingham     }
758ebc09c36SJim Ingham 
759ebc09c36SJim Ingham     // Verify & handle any options/arguments passed to the alias command
760ebc09c36SJim Ingham 
761212130acSEnrico Granata     std::string args_string;
762212130acSEnrico Granata 
76311eb9c64SZachary Turner     if (!args.empty()) {
764b9c1b51eSKate Stone       CommandObjectSP tmp_sp =
765b9c1b51eSKate Stone           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
766ebc09c36SJim Ingham       if (use_subcommand)
7674574a890SZachary Turner         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
7684574a890SZachary Turner                                                  false);
769ca90c47eSCaroline Tice 
770ca90c47eSCaroline Tice       args.GetCommandString(args_string);
771867b185dSCaroline Tice     }
772ebc09c36SJim Ingham 
773771ef6d4SMalcolm Parsons     if (m_interpreter.AliasExists(alias_command) ||
774771ef6d4SMalcolm Parsons         m_interpreter.UserCommandExists(alias_command)) {
775b9c1b51eSKate Stone       result.AppendWarningWithFormat(
7764574a890SZachary Turner           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
777ebc09c36SJim Ingham     }
778ebc09c36SJim Ingham 
779b9c1b51eSKate Stone     if (CommandAlias *alias = m_interpreter.AddAlias(
7804574a890SZachary Turner             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
781771ef6d4SMalcolm Parsons             args_string)) {
78245d0e238SEnrico Granata       if (m_command_options.m_help.OptionWasSet())
78345d0e238SEnrico Granata         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
78445d0e238SEnrico Granata       if (m_command_options.m_long_help.OptionWasSet())
78545d0e238SEnrico Granata         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
786ebc09c36SJim Ingham       result.SetStatus(eReturnStatusSuccessFinishNoResult);
787b9c1b51eSKate Stone     } else {
788212130acSEnrico Granata       result.AppendError("Unable to create requested alias.\n");
789212130acSEnrico Granata       result.SetStatus(eReturnStatusFailed);
790212130acSEnrico Granata       return false;
791212130acSEnrico Granata     }
792ebc09c36SJim Ingham 
793ebc09c36SJim Ingham     return result.Succeeded();
794ebc09c36SJim Ingham   }
795ebc09c36SJim Ingham };
796ebc09c36SJim Ingham 
797ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
798ebc09c36SJim Ingham //-------------------------------------------------------------------------
799ebc09c36SJim Ingham // CommandObjectCommandsUnalias
800ebc09c36SJim Ingham //-------------------------------------------------------------------------
801ebc09c36SJim Ingham 
802b9c1b51eSKate Stone class CommandObjectCommandsUnalias : public CommandObjectParsed {
803ebc09c36SJim Ingham public:
8047428a18cSKate Stone   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
805b9c1b51eSKate Stone       : CommandObjectParsed(
806b9c1b51eSKate Stone             interpreter, "command unalias",
807b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command alias'.",
808b9c1b51eSKate Stone             nullptr) {
809405fe67fSCaroline Tice     CommandArgumentEntry arg;
810405fe67fSCaroline Tice     CommandArgumentData alias_arg;
811405fe67fSCaroline Tice 
812405fe67fSCaroline Tice     // Define the first (and only) variant of this arg.
813405fe67fSCaroline Tice     alias_arg.arg_type = eArgTypeAliasName;
814405fe67fSCaroline Tice     alias_arg.arg_repetition = eArgRepeatPlain;
815405fe67fSCaroline Tice 
816b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
817b9c1b51eSKate Stone     // argument entry.
818405fe67fSCaroline Tice     arg.push_back(alias_arg);
819405fe67fSCaroline Tice 
820405fe67fSCaroline Tice     // Push the data for the first argument into the m_arguments vector.
821405fe67fSCaroline Tice     m_arguments.push_back(arg);
822ebc09c36SJim Ingham   }
823ebc09c36SJim Ingham 
8246e3d8e7fSEugene Zelenko   ~CommandObjectCommandsUnalias() override = default;
825ebc09c36SJim Ingham 
8265a988416SJim Ingham protected:
827b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
828ebc09c36SJim Ingham     CommandObject::CommandMap::iterator pos;
829ebc09c36SJim Ingham     CommandObject *cmd_obj;
830ebc09c36SJim Ingham 
83111eb9c64SZachary Turner     if (args.empty()) {
83211eb9c64SZachary Turner       result.AppendError("must call 'unalias' with a valid alias");
83311eb9c64SZachary Turner       result.SetStatus(eReturnStatusFailed);
83411eb9c64SZachary Turner       return false;
83511eb9c64SZachary Turner     }
83611eb9c64SZachary Turner 
8374574a890SZachary Turner     auto command_name = args[0].ref;
838a7015092SGreg Clayton     cmd_obj = m_interpreter.GetCommandObject(command_name);
8394574a890SZachary Turner     if (!cmd_obj) {
8404574a890SZachary Turner       result.AppendErrorWithFormat(
8414574a890SZachary Turner           "'%s' is not a known command.\nTry 'help' to see a "
8424574a890SZachary Turner           "current list of commands.\n",
843*867e7d17SZachary Turner           args[0].c_str());
8444574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
8454574a890SZachary Turner       return false;
8464574a890SZachary Turner     }
8474574a890SZachary Turner 
848b9c1b51eSKate Stone     if (m_interpreter.CommandExists(command_name)) {
849b9c1b51eSKate Stone       if (cmd_obj->IsRemovable()) {
850b9c1b51eSKate Stone         result.AppendErrorWithFormat(
851b9c1b51eSKate Stone             "'%s' is not an alias, it is a debugger command which can be "
852b9c1b51eSKate Stone             "removed using the 'command delete' command.\n",
853*867e7d17SZachary Turner             args[0].c_str());
854b9c1b51eSKate Stone       } else {
855b9c1b51eSKate Stone         result.AppendErrorWithFormat(
856b9c1b51eSKate Stone             "'%s' is a permanent debugger command and cannot be removed.\n",
857*867e7d17SZachary Turner             args[0].c_str());
858b547278cSGreg Clayton       }
859ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
8604574a890SZachary Turner       return false;
8614574a890SZachary Turner     }
8624574a890SZachary Turner 
863b9c1b51eSKate Stone     if (!m_interpreter.RemoveAlias(command_name)) {
864a7015092SGreg Clayton       if (m_interpreter.AliasExists(command_name))
865b9c1b51eSKate Stone         result.AppendErrorWithFormat(
866*867e7d17SZachary Turner             "Error occurred while attempting to unalias '%s'.\n",
867*867e7d17SZachary Turner             args[0].c_str());
868ebc09c36SJim Ingham       else
869b9c1b51eSKate Stone         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
870*867e7d17SZachary Turner                                      args[0].c_str());
871ebc09c36SJim Ingham       result.SetStatus(eReturnStatusFailed);
8724574a890SZachary Turner       return false;
873ebc09c36SJim Ingham     }
874ebc09c36SJim Ingham 
8754574a890SZachary Turner     result.SetStatus(eReturnStatusSuccessFinishNoResult);
876ebc09c36SJim Ingham     return result.Succeeded();
877ebc09c36SJim Ingham   }
878ebc09c36SJim Ingham };
879ebc09c36SJim Ingham 
880b547278cSGreg Clayton #pragma mark CommandObjectCommandsDelete
881b547278cSGreg Clayton //-------------------------------------------------------------------------
882b547278cSGreg Clayton // CommandObjectCommandsDelete
883b547278cSGreg Clayton //-------------------------------------------------------------------------
884b547278cSGreg Clayton 
885b9c1b51eSKate Stone class CommandObjectCommandsDelete : public CommandObjectParsed {
886b547278cSGreg Clayton public:
8877428a18cSKate Stone   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
888b9c1b51eSKate Stone       : CommandObjectParsed(
889b9c1b51eSKate Stone             interpreter, "command delete",
890b9c1b51eSKate Stone             "Delete one or more custom commands defined by 'command regex'.",
891b9c1b51eSKate Stone             nullptr) {
892b547278cSGreg Clayton     CommandArgumentEntry arg;
893b547278cSGreg Clayton     CommandArgumentData alias_arg;
894b547278cSGreg Clayton 
895b547278cSGreg Clayton     // Define the first (and only) variant of this arg.
896b547278cSGreg Clayton     alias_arg.arg_type = eArgTypeCommandName;
897b547278cSGreg Clayton     alias_arg.arg_repetition = eArgRepeatPlain;
898b547278cSGreg Clayton 
899b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
900b9c1b51eSKate Stone     // argument entry.
901b547278cSGreg Clayton     arg.push_back(alias_arg);
902b547278cSGreg Clayton 
903b547278cSGreg Clayton     // Push the data for the first argument into the m_arguments vector.
904b547278cSGreg Clayton     m_arguments.push_back(arg);
905b547278cSGreg Clayton   }
906b547278cSGreg Clayton 
9076e3d8e7fSEugene Zelenko   ~CommandObjectCommandsDelete() override = default;
908b547278cSGreg Clayton 
909b547278cSGreg Clayton protected:
910b9c1b51eSKate Stone   bool DoExecute(Args &args, CommandReturnObject &result) override {
911b547278cSGreg Clayton     CommandObject::CommandMap::iterator pos;
912b547278cSGreg Clayton 
91311eb9c64SZachary Turner     if (args.empty()) {
91411eb9c64SZachary Turner       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
91511eb9c64SZachary Turner                                    "defined regular expression command names",
916a449698cSZachary Turner                                    GetCommandName().str().c_str());
91711eb9c64SZachary Turner       result.SetStatus(eReturnStatusFailed);
91811eb9c64SZachary Turner     }
91911eb9c64SZachary Turner 
9204574a890SZachary Turner     auto command_name = args[0].ref;
9214574a890SZachary Turner     if (!m_interpreter.CommandExists(command_name)) {
92246d4aa21SEnrico Granata       StreamString error_msg_stream;
92346d4aa21SEnrico Granata       const bool generate_apropos = true;
92446d4aa21SEnrico Granata       const bool generate_type_lookup = false;
925b9c1b51eSKate Stone       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
9264574a890SZachary Turner           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
9274574a890SZachary Turner           generate_apropos, generate_type_lookup);
928c156427dSZachary Turner       result.AppendError(error_msg_stream.GetString());
929b547278cSGreg Clayton       result.SetStatus(eReturnStatusFailed);
9304574a890SZachary Turner       return false;
931b547278cSGreg Clayton     }
932b547278cSGreg Clayton 
9334574a890SZachary Turner     if (!m_interpreter.RemoveCommand(command_name)) {
9344574a890SZachary Turner       result.AppendErrorWithFormat(
9354574a890SZachary Turner           "'%s' is a permanent debugger command and cannot be removed.\n",
936*867e7d17SZachary Turner           args[0].c_str());
9374574a890SZachary Turner       result.SetStatus(eReturnStatusFailed);
9384574a890SZachary Turner       return false;
9394574a890SZachary Turner     }
9404574a890SZachary Turner 
9414574a890SZachary Turner     result.SetStatus(eReturnStatusSuccessFinishNoResult);
9424574a890SZachary Turner     return true;
943b547278cSGreg Clayton   }
944b547278cSGreg Clayton };
945b547278cSGreg Clayton 
946de164aaaSGreg Clayton //-------------------------------------------------------------------------
947de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
948de164aaaSGreg Clayton //-------------------------------------------------------------------------
9491f0f5b5bSZachary Turner 
9501f0f5b5bSZachary Turner static OptionDefinition g_regex_options[] = {
9511f0f5b5bSZachary Turner     // clang-format off
9521f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
9531f0f5b5bSZachary Turner   { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
9541f0f5b5bSZachary Turner     // clang-format on
9551f0f5b5bSZachary Turner };
9561f0f5b5bSZachary Turner 
9575a988416SJim Ingham #pragma mark CommandObjectCommandsAddRegex
958de164aaaSGreg Clayton 
959b9c1b51eSKate Stone class CommandObjectCommandsAddRegex : public CommandObjectParsed,
960b9c1b51eSKate Stone                                       public IOHandlerDelegateMultiline {
961de164aaaSGreg Clayton public:
9627428a18cSKate Stone   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
963b9c1b51eSKate Stone       : CommandObjectParsed(
964b9c1b51eSKate Stone             interpreter, "command regex", "Define a custom command in terms of "
965b9c1b51eSKate Stone                                           "existing commands by matching "
966b9c1b51eSKate Stone                                           "regular expressions.",
9670e5e5a79SGreg Clayton             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
968b9c1b51eSKate Stone         IOHandlerDelegateMultiline("",
969b9c1b51eSKate Stone                                    IOHandlerDelegate::Completion::LLDBCommand),
970b9c1b51eSKate Stone         m_options() {
971b9c1b51eSKate Stone     SetHelpLong(
972b9c1b51eSKate Stone         R"(
973b9c1b51eSKate Stone )"
974b9c1b51eSKate Stone         "This command allows the user to create powerful regular expression commands \
975ea671fbdSKate Stone with substitutions. The regular expressions and substitutions are specified \
976b9c1b51eSKate Stone using the regular expression substitution format of:"
977b9c1b51eSKate Stone         R"(
978ea671fbdSKate Stone 
979ea671fbdSKate Stone     s/<regex>/<subst>/
980ea671fbdSKate Stone 
981b9c1b51eSKate Stone )"
982b9c1b51eSKate Stone         "<regex> is a regular expression that can use parenthesis to capture regular \
983ea671fbdSKate Stone expression input and substitute the captured matches in the output using %1 \
984b9c1b51eSKate Stone for the first match, %2 for the second, and so on."
985b9c1b51eSKate Stone         R"(
986ea671fbdSKate Stone 
987b9c1b51eSKate Stone )"
988b9c1b51eSKate Stone         "The regular expressions can all be specified on the command line if more than \
989ea671fbdSKate Stone one argument is provided. If just the command name is provided on the command \
990ea671fbdSKate Stone line, then the regular expressions and substitutions can be entered on separate \
991b9c1b51eSKate Stone lines, followed by an empty line to terminate the command definition."
992b9c1b51eSKate Stone         R"(
993ea671fbdSKate Stone 
994ea671fbdSKate Stone EXAMPLES
995ea671fbdSKate Stone 
996b9c1b51eSKate Stone )"
997b9c1b51eSKate Stone         "The following example will define a regular expression command named 'f' that \
998ea671fbdSKate Stone will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
999b9c1b51eSKate Stone a number follows 'f':"
1000b9c1b51eSKate Stone         R"(
1001ea671fbdSKate Stone 
1002b9c1b51eSKate Stone     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1003de164aaaSGreg Clayton   }
1004de164aaaSGreg Clayton 
10056e3d8e7fSEugene Zelenko   ~CommandObjectCommandsAddRegex() override = default;
1006de164aaaSGreg Clayton 
10075a988416SJim Ingham protected:
1008b9c1b51eSKate Stone   void IOHandlerActivated(IOHandler &io_handler) override {
100944d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1010b9c1b51eSKate Stone     if (output_sp) {
1011b9c1b51eSKate Stone       output_sp->PutCString("Enter one of more sed substitution commands in "
1012b9c1b51eSKate Stone                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
1013b9c1b51eSKate Stone                             "substitution list with an empty line.\n");
101444d93782SGreg Clayton       output_sp->Flush();
101544d93782SGreg Clayton     }
101644d93782SGreg Clayton   }
101744d93782SGreg Clayton 
1018b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1019b9c1b51eSKate Stone                               std::string &data) override {
102044d93782SGreg Clayton     io_handler.SetIsDone(true);
1021b9c1b51eSKate Stone     if (m_regex_cmd_ap) {
102244d93782SGreg Clayton       StringList lines;
1023b9c1b51eSKate Stone       if (lines.SplitIntoLines(data)) {
102444d93782SGreg Clayton         const size_t num_lines = lines.GetSize();
102544d93782SGreg Clayton         bool check_only = false;
1026b9c1b51eSKate Stone         for (size_t i = 0; i < num_lines; ++i) {
102744d93782SGreg Clayton           llvm::StringRef bytes_strref(lines[i]);
102844d93782SGreg Clayton           Error error = AppendRegexSubstitution(bytes_strref, check_only);
1029b9c1b51eSKate Stone           if (error.Fail()) {
1030b9c1b51eSKate Stone             if (!m_interpreter.GetDebugger()
1031b9c1b51eSKate Stone                      .GetCommandInterpreter()
1032b9c1b51eSKate Stone                      .GetBatchCommandMode()) {
1033b9c1b51eSKate Stone               StreamSP out_stream =
1034b9c1b51eSKate Stone                   m_interpreter.GetDebugger().GetAsyncOutputStream();
103544d93782SGreg Clayton               out_stream->Printf("error: %s\n", error.AsCString());
103644d93782SGreg Clayton             }
103744d93782SGreg Clayton           }
103844d93782SGreg Clayton         }
103944d93782SGreg Clayton       }
1040b9c1b51eSKate Stone       if (m_regex_cmd_ap->HasRegexEntries()) {
104144d93782SGreg Clayton         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
104244d93782SGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
104344d93782SGreg Clayton       }
104444d93782SGreg Clayton     }
104544d93782SGreg Clayton   }
104644d93782SGreg Clayton 
1047b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
10485a988416SJim Ingham     const size_t argc = command.GetArgumentCount();
1049b9c1b51eSKate Stone     if (argc == 0) {
1050b9c1b51eSKate Stone       result.AppendError("usage: 'command regex <command-name> "
1051b9c1b51eSKate Stone                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
10520e5e5a79SGreg Clayton       result.SetStatus(eReturnStatusFailed);
105311eb9c64SZachary Turner       return false;
105411eb9c64SZachary Turner     }
105511eb9c64SZachary Turner 
10560e5e5a79SGreg Clayton     Error error;
10574574a890SZachary Turner     auto name = command[0].ref;
10584574a890SZachary Turner     m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>(
10594574a890SZachary Turner         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
10604574a890SZachary Turner         true);
10610e5e5a79SGreg Clayton 
1062b9c1b51eSKate Stone     if (argc == 1) {
106344d93782SGreg Clayton       Debugger &debugger = m_interpreter.GetDebugger();
1064e30f11d9SKate Stone       bool color_prompt = debugger.GetUseColor();
106544d93782SGreg Clayton       const bool multiple_lines = true; // Get multiple lines
1066b9c1b51eSKate Stone       IOHandlerSP io_handler_sp(new IOHandlerEditline(
1067b9c1b51eSKate Stone           debugger, IOHandler::Type::Other,
106873d80faaSGreg Clayton           "lldb-regex",          // Name of input reader for history
1069514d8cd8SZachary Turner           llvm::StringRef("> "), // Prompt
1070514d8cd8SZachary Turner           llvm::StringRef(),     // Continuation prompt
1071b9c1b51eSKate Stone           multiple_lines, color_prompt,
1072f6913cd7SGreg Clayton           0, // Don't show line numbers
107344d93782SGreg Clayton           *this));
107444d93782SGreg Clayton 
1075b9c1b51eSKate Stone       if (io_handler_sp) {
107644d93782SGreg Clayton         debugger.PushIOHandler(io_handler_sp);
1077de164aaaSGreg Clayton         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1078de164aaaSGreg Clayton       }
1079b9c1b51eSKate Stone     } else {
108097d2c401SZachary Turner       for (auto &entry : command.entries().drop_front()) {
108144d93782SGreg Clayton         bool check_only = false;
108297d2c401SZachary Turner         error = AppendRegexSubstitution(entry.ref, check_only);
10830e5e5a79SGreg Clayton         if (error.Fail())
10840e5e5a79SGreg Clayton           break;
10850e5e5a79SGreg Clayton       }
10860e5e5a79SGreg Clayton 
1087b9c1b51eSKate Stone       if (error.Success()) {
10880e5e5a79SGreg Clayton         AddRegexCommandToInterpreter();
10890e5e5a79SGreg Clayton       }
10900e5e5a79SGreg Clayton     }
1091b9c1b51eSKate Stone     if (error.Fail()) {
10920e5e5a79SGreg Clayton       result.AppendError(error.AsCString());
1093de164aaaSGreg Clayton       result.SetStatus(eReturnStatusFailed);
1094de164aaaSGreg Clayton     }
10950e5e5a79SGreg Clayton 
1096de164aaaSGreg Clayton     return result.Succeeded();
1097de164aaaSGreg Clayton   }
1098de164aaaSGreg Clayton 
1099b9c1b51eSKate Stone   Error AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1100b9c1b51eSKate Stone                                 bool check_only) {
11010e5e5a79SGreg Clayton     Error error;
11020e5e5a79SGreg Clayton 
1103b9c1b51eSKate Stone     if (!m_regex_cmd_ap) {
1104b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1105b9c1b51eSKate Stone           "invalid regular expression command object for: '%.*s'",
1106b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11070e5e5a79SGreg Clayton       return error;
1108de164aaaSGreg Clayton     }
11090e5e5a79SGreg Clayton 
11100e5e5a79SGreg Clayton     size_t regex_sed_size = regex_sed.size();
11110e5e5a79SGreg Clayton 
1112b9c1b51eSKate Stone     if (regex_sed_size <= 1) {
1113b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1114b9c1b51eSKate Stone           "regular expression substitution string is too short: '%.*s'",
1115b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11160e5e5a79SGreg Clayton       return error;
11170e5e5a79SGreg Clayton     }
11180e5e5a79SGreg Clayton 
1119b9c1b51eSKate Stone     if (regex_sed[0] != 's') {
1120b9c1b51eSKate Stone       error.SetErrorStringWithFormat("regular expression substitution string "
1121b9c1b51eSKate Stone                                      "doesn't start with 's': '%.*s'",
1122b9c1b51eSKate Stone                                      (int)regex_sed.size(), regex_sed.data());
11230e5e5a79SGreg Clayton       return error;
11240e5e5a79SGreg Clayton     }
11250e5e5a79SGreg Clayton     const size_t first_separator_char_pos = 1;
11260e5e5a79SGreg Clayton     // use the char that follows 's' as the regex separator character
11270e5e5a79SGreg Clayton     // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
11280e5e5a79SGreg Clayton     const char separator_char = regex_sed[first_separator_char_pos];
1129b9c1b51eSKate Stone     const size_t second_separator_char_pos =
1130b9c1b51eSKate Stone         regex_sed.find(separator_char, first_separator_char_pos + 1);
11310e5e5a79SGreg Clayton 
1132b9c1b51eSKate Stone     if (second_separator_char_pos == std::string::npos) {
1133b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1134b9c1b51eSKate Stone           "missing second '%c' separator char after '%.*s' in '%.*s'",
11350e5e5a79SGreg Clayton           separator_char,
11360e5e5a79SGreg Clayton           (int)(regex_sed.size() - first_separator_char_pos - 1),
1137ea508635SGreg Clayton           regex_sed.data() + (first_separator_char_pos + 1),
1138b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11390e5e5a79SGreg Clayton       return error;
11400e5e5a79SGreg Clayton     }
11410e5e5a79SGreg Clayton 
1142b9c1b51eSKate Stone     const size_t third_separator_char_pos =
1143b9c1b51eSKate Stone         regex_sed.find(separator_char, second_separator_char_pos + 1);
11440e5e5a79SGreg Clayton 
1145b9c1b51eSKate Stone     if (third_separator_char_pos == std::string::npos) {
1146b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1147b9c1b51eSKate Stone           "missing third '%c' separator char after '%.*s' in '%.*s'",
11480e5e5a79SGreg Clayton           separator_char,
11490e5e5a79SGreg Clayton           (int)(regex_sed.size() - second_separator_char_pos - 1),
1150ea508635SGreg Clayton           regex_sed.data() + (second_separator_char_pos + 1),
1151b9c1b51eSKate Stone           (int)regex_sed.size(), regex_sed.data());
11520e5e5a79SGreg Clayton       return error;
11530e5e5a79SGreg Clayton     }
11540e5e5a79SGreg Clayton 
1155b9c1b51eSKate Stone     if (third_separator_char_pos != regex_sed_size - 1) {
11560e5e5a79SGreg Clayton       // Make sure that everything that follows the last regex
11570e5e5a79SGreg Clayton       // separator char
1158b9c1b51eSKate Stone       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1159b9c1b51eSKate Stone                                       third_separator_char_pos + 1) !=
1160b9c1b51eSKate Stone           std::string::npos) {
1161b9c1b51eSKate Stone         error.SetErrorStringWithFormat(
1162b9c1b51eSKate Stone             "extra data found after the '%.*s' regular expression substitution "
1163b9c1b51eSKate Stone             "string: '%.*s'",
1164b9c1b51eSKate Stone             (int)third_separator_char_pos + 1, regex_sed.data(),
11650e5e5a79SGreg Clayton             (int)(regex_sed.size() - third_separator_char_pos - 1),
11660e5e5a79SGreg Clayton             regex_sed.data() + (third_separator_char_pos + 1));
11670e5e5a79SGreg Clayton         return error;
11680e5e5a79SGreg Clayton       }
1169b9c1b51eSKate Stone     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1170b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1171b9c1b51eSKate Stone           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1172b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
11730e5e5a79SGreg Clayton           regex_sed.data());
11740e5e5a79SGreg Clayton       return error;
1175b9c1b51eSKate Stone     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1176b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
1177b9c1b51eSKate Stone           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1178b9c1b51eSKate Stone           separator_char, separator_char, separator_char, (int)regex_sed.size(),
11790e5e5a79SGreg Clayton           regex_sed.data());
11800e5e5a79SGreg Clayton       return error;
11810e5e5a79SGreg Clayton     }
118244d93782SGreg Clayton 
1183b9c1b51eSKate Stone     if (!check_only) {
1184b9c1b51eSKate Stone       std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1185b9c1b51eSKate Stone                                          second_separator_char_pos -
1186b9c1b51eSKate Stone                                              first_separator_char_pos - 1));
1187b9c1b51eSKate Stone       std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1188b9c1b51eSKate Stone                                          third_separator_char_pos -
1189b9c1b51eSKate Stone                                              second_separator_char_pos - 1));
1190b9c1b51eSKate Stone       m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
119144d93782SGreg Clayton     }
11920e5e5a79SGreg Clayton     return error;
1193de164aaaSGreg Clayton   }
1194de164aaaSGreg Clayton 
1195b9c1b51eSKate Stone   void AddRegexCommandToInterpreter() {
1196b9c1b51eSKate Stone     if (m_regex_cmd_ap) {
1197b9c1b51eSKate Stone       if (m_regex_cmd_ap->HasRegexEntries()) {
1198de164aaaSGreg Clayton         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1199de164aaaSGreg Clayton         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1200de164aaaSGreg Clayton       }
1201de164aaaSGreg Clayton     }
1202de164aaaSGreg Clayton   }
1203de164aaaSGreg Clayton 
1204de164aaaSGreg Clayton private:
12057b0992d9SGreg Clayton   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1206de164aaaSGreg Clayton 
1207b9c1b51eSKate Stone   class CommandOptions : public Options {
1208de164aaaSGreg Clayton   public:
1209b9c1b51eSKate Stone     CommandOptions() : Options() {}
1210de164aaaSGreg Clayton 
12116e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1212de164aaaSGreg Clayton 
1213fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1214b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
1215de164aaaSGreg Clayton       Error error;
12163bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1217de164aaaSGreg Clayton 
1218b9c1b51eSKate Stone       switch (short_option) {
1219de164aaaSGreg Clayton       case 'h':
1220de164aaaSGreg Clayton         m_help.assign(option_arg);
1221de164aaaSGreg Clayton         break;
1222de164aaaSGreg Clayton       case 's':
1223de164aaaSGreg Clayton         m_syntax.assign(option_arg);
1224de164aaaSGreg Clayton         break;
1225de164aaaSGreg Clayton       default:
1226b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1227b9c1b51eSKate Stone                                        short_option);
1228de164aaaSGreg Clayton         break;
1229de164aaaSGreg Clayton       }
1230de164aaaSGreg Clayton 
1231de164aaaSGreg Clayton       return error;
1232de164aaaSGreg Clayton     }
1233de164aaaSGreg Clayton 
1234b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1235de164aaaSGreg Clayton       m_help.clear();
1236de164aaaSGreg Clayton       m_syntax.clear();
1237de164aaaSGreg Clayton     }
1238de164aaaSGreg Clayton 
12391f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
124070602439SZachary Turner       return llvm::makeArrayRef(g_regex_options);
12411f0f5b5bSZachary Turner     }
1242de164aaaSGreg Clayton 
124311eb9c64SZachary Turner     // TODO: Convert these functions to return StringRefs.
1244b9c1b51eSKate Stone     const char *GetHelp() {
12456e3d8e7fSEugene Zelenko       return (m_help.empty() ? nullptr : m_help.c_str());
1246de164aaaSGreg Clayton     }
12476e3d8e7fSEugene Zelenko 
1248b9c1b51eSKate Stone     const char *GetSyntax() {
12496e3d8e7fSEugene Zelenko       return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1250de164aaaSGreg Clayton     }
12516e3d8e7fSEugene Zelenko 
1252de164aaaSGreg Clayton   protected:
12536e3d8e7fSEugene Zelenko     // Instance variables to hold the values for command options.
12546e3d8e7fSEugene Zelenko 
1255de164aaaSGreg Clayton     std::string m_help;
1256de164aaaSGreg Clayton     std::string m_syntax;
1257de164aaaSGreg Clayton   };
1258de164aaaSGreg Clayton 
1259b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
1260de164aaaSGreg Clayton 
12615a988416SJim Ingham   CommandOptions m_options;
1262de164aaaSGreg Clayton };
1263de164aaaSGreg Clayton 
1264b9c1b51eSKate Stone class CommandObjectPythonFunction : public CommandObjectRaw {
1265223383edSEnrico Granata public:
1266b9c1b51eSKate Stone   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1267b9c1b51eSKate Stone                               std::string funct, std::string help,
1268b9c1b51eSKate Stone                               ScriptedCommandSynchronicity synch)
1269a449698cSZachary Turner       : CommandObjectRaw(interpreter, name),
1270b9c1b51eSKate Stone         m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1271735152e3SEnrico Granata     if (!help.empty())
1272442f6530SZachary Turner       SetHelp(help);
1273b9c1b51eSKate Stone     else {
1274735152e3SEnrico Granata       StreamString stream;
1275735152e3SEnrico Granata       stream.Printf("For more information run 'help %s'", name.c_str());
1276c156427dSZachary Turner       SetHelp(stream.GetString());
1277735152e3SEnrico Granata     }
1278223383edSEnrico Granata   }
1279223383edSEnrico Granata 
12806e3d8e7fSEugene Zelenko   ~CommandObjectPythonFunction() override = default;
1281223383edSEnrico Granata 
1282b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
12835a988416SJim Ingham 
1284b9c1b51eSKate Stone   const std::string &GetFunctionName() { return m_function_name; }
12855a988416SJim Ingham 
1286b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
12875a988416SJim Ingham 
1288442f6530SZachary Turner   llvm::StringRef GetHelpLong() override {
1289442f6530SZachary Turner     if (m_fetched_help_long)
1290442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1291442f6530SZachary Turner 
1292fac939e9SEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1293442f6530SZachary Turner     if (!scripter)
1294442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1295442f6530SZachary Turner 
1296fac939e9SEnrico Granata     std::string docstring;
1297442f6530SZachary Turner     m_fetched_help_long =
1298442f6530SZachary Turner         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1299fac939e9SEnrico Granata     if (!docstring.empty())
1300442f6530SZachary Turner       SetHelpLong(docstring);
1301fac939e9SEnrico Granata     return CommandObjectRaw::GetHelpLong();
1302fac939e9SEnrico Granata   }
1303fac939e9SEnrico Granata 
13045a988416SJim Ingham protected:
1305b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
1306b9c1b51eSKate Stone                  CommandReturnObject &result) override {
1307223383edSEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1308223383edSEnrico Granata 
1309223383edSEnrico Granata     Error error;
1310223383edSEnrico Granata 
131170f11f88SJim Ingham     result.SetStatus(eReturnStatusInvalid);
131270f11f88SJim Ingham 
1313b9c1b51eSKate Stone     if (!scripter ||
1314b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1315b9c1b51eSKate Stone                                          raw_command_line, m_synchro, result,
1316b9c1b51eSKate Stone                                          error, m_exe_ctx)) {
1317223383edSEnrico Granata       result.AppendError(error.AsCString());
1318223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1319b9c1b51eSKate Stone     } else {
132070f11f88SJim Ingham       // Don't change the status if the command already set it...
1321b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1322c156427dSZachary Turner         if (result.GetOutputData().empty())
1323223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
132470f11f88SJim Ingham         else
132570f11f88SJim Ingham           result.SetStatus(eReturnStatusSuccessFinishResult);
132670f11f88SJim Ingham       }
132770f11f88SJim Ingham     }
1328223383edSEnrico Granata 
1329223383edSEnrico Granata     return result.Succeeded();
1330223383edSEnrico Granata   }
1331223383edSEnrico Granata 
13326e3d8e7fSEugene Zelenko private:
13336e3d8e7fSEugene Zelenko   std::string m_function_name;
13346e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
13356e3d8e7fSEugene Zelenko   bool m_fetched_help_long;
1336223383edSEnrico Granata };
1337223383edSEnrico Granata 
1338b9c1b51eSKate Stone class CommandObjectScriptingObject : public CommandObjectRaw {
13399fe00e52SEnrico Granata public:
13409fe00e52SEnrico Granata   CommandObjectScriptingObject(CommandInterpreter &interpreter,
13419fe00e52SEnrico Granata                                std::string name,
13420641ca1aSZachary Turner                                StructuredData::GenericSP cmd_obj_sp,
1343b9c1b51eSKate Stone                                ScriptedCommandSynchronicity synch)
1344a449698cSZachary Turner       : CommandObjectRaw(interpreter, name),
1345b9c1b51eSKate Stone         m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1346b9c1b51eSKate Stone         m_fetched_help_long(false) {
13479fe00e52SEnrico Granata     StreamString stream;
13489fe00e52SEnrico Granata     stream.Printf("For more information run 'help %s'", name.c_str());
1349c156427dSZachary Turner     SetHelp(stream.GetString());
1350e87764f2SEnrico Granata     if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1351e87764f2SEnrico Granata       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
13529fe00e52SEnrico Granata   }
13539fe00e52SEnrico Granata 
13546e3d8e7fSEugene Zelenko   ~CommandObjectScriptingObject() override = default;
13559fe00e52SEnrico Granata 
1356b9c1b51eSKate Stone   bool IsRemovable() const override { return true; }
13579fe00e52SEnrico Granata 
1358b9c1b51eSKate Stone   StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
13599fe00e52SEnrico Granata 
1360b9c1b51eSKate Stone   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
13619fe00e52SEnrico Granata 
1362442f6530SZachary Turner   llvm::StringRef GetHelp() override {
1363442f6530SZachary Turner     if (m_fetched_help_short)
1364442f6530SZachary Turner       return CommandObjectRaw::GetHelp();
13656f79bb2dSEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1366442f6530SZachary Turner     if (!scripter)
1367442f6530SZachary Turner       return CommandObjectRaw::GetHelp();
13686f79bb2dSEnrico Granata     std::string docstring;
1369b9c1b51eSKate Stone     m_fetched_help_short =
1370b9c1b51eSKate Stone         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
13716f79bb2dSEnrico Granata     if (!docstring.empty())
1372442f6530SZachary Turner       SetHelp(docstring);
1373442f6530SZachary Turner 
13746f79bb2dSEnrico Granata     return CommandObjectRaw::GetHelp();
13756f79bb2dSEnrico Granata   }
13766f79bb2dSEnrico Granata 
1377442f6530SZachary Turner   llvm::StringRef GetHelpLong() override {
1378442f6530SZachary Turner     if (m_fetched_help_long)
1379442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1380442f6530SZachary Turner 
13816f79bb2dSEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1382442f6530SZachary Turner     if (!scripter)
1383442f6530SZachary Turner       return CommandObjectRaw::GetHelpLong();
1384442f6530SZachary Turner 
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())
1389442f6530SZachary Turner       SetHelpLong(docstring);
13909fe00e52SEnrico Granata     return CommandObjectRaw::GetHelpLong();
13919fe00e52SEnrico Granata   }
13929fe00e52SEnrico Granata 
13939fe00e52SEnrico Granata protected:
1394b9c1b51eSKate Stone   bool DoExecute(const char *raw_command_line,
1395b9c1b51eSKate Stone                  CommandReturnObject &result) override {
13969fe00e52SEnrico Granata     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
13979fe00e52SEnrico Granata 
13989fe00e52SEnrico Granata     Error error;
13999fe00e52SEnrico Granata 
14009fe00e52SEnrico Granata     result.SetStatus(eReturnStatusInvalid);
14019fe00e52SEnrico Granata 
1402b9c1b51eSKate Stone     if (!scripter ||
1403b9c1b51eSKate Stone         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1404b9c1b51eSKate Stone                                          m_synchro, result, error, m_exe_ctx)) {
14059fe00e52SEnrico Granata       result.AppendError(error.AsCString());
14069fe00e52SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1407b9c1b51eSKate Stone     } else {
14089fe00e52SEnrico Granata       // Don't change the status if the command already set it...
1409b9c1b51eSKate Stone       if (result.GetStatus() == eReturnStatusInvalid) {
1410c156427dSZachary Turner         if (result.GetOutputData().empty())
14119fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
14129fe00e52SEnrico Granata         else
14139fe00e52SEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishResult);
14149fe00e52SEnrico Granata       }
14159fe00e52SEnrico Granata     }
14169fe00e52SEnrico Granata 
14179fe00e52SEnrico Granata     return result.Succeeded();
14189fe00e52SEnrico Granata   }
14199fe00e52SEnrico Granata 
14206e3d8e7fSEugene Zelenko private:
14216e3d8e7fSEugene Zelenko   StructuredData::GenericSP m_cmd_obj_sp;
14226e3d8e7fSEugene Zelenko   ScriptedCommandSynchronicity m_synchro;
14236e3d8e7fSEugene Zelenko   bool m_fetched_help_short : 1;
14246e3d8e7fSEugene Zelenko   bool m_fetched_help_long : 1;
14259fe00e52SEnrico Granata };
14269fe00e52SEnrico Granata 
1427a9dbf432SEnrico Granata //-------------------------------------------------------------------------
1428a9dbf432SEnrico Granata // CommandObjectCommandsScriptImport
1429a9dbf432SEnrico Granata //-------------------------------------------------------------------------
1430a9dbf432SEnrico Granata 
14311f0f5b5bSZachary Turner OptionDefinition g_script_import_options[] = {
14321f0f5b5bSZachary Turner     // clang-format off
14331f0f5b5bSZachary 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." },
14341f0f5b5bSZachary Turner     // clang-format on
14351f0f5b5bSZachary Turner };
14361f0f5b5bSZachary Turner 
1437b9c1b51eSKate Stone class CommandObjectCommandsScriptImport : public CommandObjectParsed {
14385a988416SJim Ingham public:
1439b9c1b51eSKate Stone   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1440b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script import",
1441b9c1b51eSKate Stone                             "Import a scripting module in LLDB.", nullptr),
1442b9c1b51eSKate Stone         m_options() {
14435a988416SJim Ingham     CommandArgumentEntry arg1;
14445a988416SJim Ingham     CommandArgumentData cmd_arg;
14455a988416SJim Ingham 
14465a988416SJim Ingham     // Define the first (and only) variant of this arg.
14475a988416SJim Ingham     cmd_arg.arg_type = eArgTypeFilename;
14483b00e35bSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlus;
14495a988416SJim Ingham 
1450b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1451b9c1b51eSKate Stone     // argument entry.
14525a988416SJim Ingham     arg1.push_back(cmd_arg);
14535a988416SJim Ingham 
14545a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
14555a988416SJim Ingham     m_arguments.push_back(arg1);
14565a988416SJim Ingham   }
14575a988416SJim Ingham 
14586e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptImport() override = default;
14595a988416SJim Ingham 
1460b9c1b51eSKate Stone   int HandleArgumentCompletion(Args &input, int &cursor_index,
14615a988416SJim Ingham                                int &cursor_char_position,
14625a988416SJim Ingham                                OptionElementVector &opt_element_vector,
1463b9c1b51eSKate Stone                                int match_start_point, int max_return_elements,
14645a988416SJim Ingham                                bool &word_complete,
1465b9c1b51eSKate Stone                                StringList &matches) override {
1466d6a24757SZachary Turner     llvm::StringRef completion_str = input[cursor_index].ref;
1467d6a24757SZachary Turner     completion_str = completion_str.take_front(cursor_char_position);
14685a988416SJim Ingham 
1469b9c1b51eSKate Stone     CommandCompletions::InvokeCommonCompletionCallbacks(
1470b9c1b51eSKate Stone         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1471d6a24757SZachary Turner         completion_str, match_start_point, max_return_elements, nullptr,
1472b9c1b51eSKate Stone         word_complete, matches);
14735a988416SJim Ingham     return matches.GetSize();
14745a988416SJim Ingham   }
14755a988416SJim Ingham 
1476b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
14775a988416SJim Ingham 
14785a988416SJim Ingham protected:
1479b9c1b51eSKate Stone   class CommandOptions : public Options {
14800a305db7SEnrico Granata   public:
1481b9c1b51eSKate Stone     CommandOptions() : Options() {}
14820a305db7SEnrico Granata 
14836e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
14840a305db7SEnrico Granata 
1485fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1486b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
14870a305db7SEnrico Granata       Error error;
14883bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
14890a305db7SEnrico Granata 
1490b9c1b51eSKate Stone       switch (short_option) {
14910a305db7SEnrico Granata       case 'r':
14920a305db7SEnrico Granata         m_allow_reload = true;
14930a305db7SEnrico Granata         break;
14940a305db7SEnrico Granata       default:
1495b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1496b9c1b51eSKate Stone                                        short_option);
14970a305db7SEnrico Granata         break;
14980a305db7SEnrico Granata       }
14990a305db7SEnrico Granata 
15000a305db7SEnrico Granata       return error;
15010a305db7SEnrico Granata     }
15020a305db7SEnrico Granata 
1503b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
1504e0c70f1bSEnrico Granata       m_allow_reload = true;
15050a305db7SEnrico Granata     }
15060a305db7SEnrico Granata 
15071f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
150870602439SZachary Turner       return llvm::makeArrayRef(g_script_import_options);
15091f0f5b5bSZachary Turner     }
15100a305db7SEnrico Granata 
15110a305db7SEnrico Granata     // Instance variables to hold the values for command options.
15120a305db7SEnrico Granata 
15130a305db7SEnrico Granata     bool m_allow_reload;
15140a305db7SEnrico Granata   };
15150a305db7SEnrico Granata 
1516b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1517b9c1b51eSKate Stone     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1518b9c1b51eSKate Stone         lldb::eScriptLanguagePython) {
1519b9c1b51eSKate Stone       result.AppendError("only scripting language supported for module "
1520b9c1b51eSKate Stone                          "importing is currently Python");
1521a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1522a9dbf432SEnrico Granata       return false;
1523a9dbf432SEnrico Granata     }
1524a9dbf432SEnrico Granata 
152511eb9c64SZachary Turner     if (command.empty()) {
15263b00e35bSEnrico Granata       result.AppendError("command script import needs one or more arguments");
1527a9dbf432SEnrico Granata       result.SetStatus(eReturnStatusFailed);
1528a9dbf432SEnrico Granata       return false;
1529a9dbf432SEnrico Granata     }
1530a9dbf432SEnrico Granata 
153111eb9c64SZachary Turner     for (auto &entry : command.entries()) {
1532a9dbf432SEnrico Granata       Error error;
1533a9dbf432SEnrico Granata 
1534c9d645d3SGreg Clayton       const bool init_session = true;
1535b9c1b51eSKate Stone       // FIXME: this is necessary because CommandObject::CheckRequirements()
153611eb9c64SZachary Turner       // assumes that commands won't ever be recursively invoked, but it's
153711eb9c64SZachary Turner       // actually possible to craft a Python script that does other "command
153811eb9c64SZachary Turner       // script imports" in __lldb_init_module the real fix is to have recursive
153911eb9c64SZachary Turner       // commands possible with a CommandInvocation object separate from the
154011eb9c64SZachary Turner       // CommandObject itself, so that recursive command invocations won't stomp
154111eb9c64SZachary Turner       // on each other (wrt to execution contents, options, and more)
1542078551c7SEnrico Granata       m_exe_ctx.Clear();
1543b9c1b51eSKate Stone       if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
154411eb9c64SZachary Turner               entry.c_str(), m_options.m_allow_reload, init_session, error)) {
1545a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1546b9c1b51eSKate Stone       } else {
1547b9c1b51eSKate Stone         result.AppendErrorWithFormat("module importing failed: %s",
1548b9c1b51eSKate Stone                                      error.AsCString());
1549a9dbf432SEnrico Granata         result.SetStatus(eReturnStatusFailed);
1550a9dbf432SEnrico Granata       }
15513b00e35bSEnrico Granata     }
1552a9dbf432SEnrico Granata 
1553a9dbf432SEnrico Granata     return result.Succeeded();
1554a9dbf432SEnrico Granata   }
15550a305db7SEnrico Granata 
15565a988416SJim Ingham   CommandOptions m_options;
1557a9dbf432SEnrico Granata };
1558223383edSEnrico Granata 
1559223383edSEnrico Granata //-------------------------------------------------------------------------
1560223383edSEnrico Granata // CommandObjectCommandsScriptAdd
1561223383edSEnrico Granata //-------------------------------------------------------------------------
1562223383edSEnrico Granata 
15631f0f5b5bSZachary Turner static OptionEnumValueElement g_script_synchro_type[] = {
15641f0f5b5bSZachary Turner     {eScriptedCommandSynchronicitySynchronous, "synchronous",
15651f0f5b5bSZachary Turner      "Run synchronous"},
15661f0f5b5bSZachary Turner     {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
15671f0f5b5bSZachary Turner      "Run asynchronous"},
15681f0f5b5bSZachary Turner     {eScriptedCommandSynchronicityCurrentValue, "current",
15691f0f5b5bSZachary Turner      "Do not alter current setting"},
15701f0f5b5bSZachary Turner     {0, nullptr, nullptr}};
15711f0f5b5bSZachary Turner 
15721f0f5b5bSZachary Turner static OptionDefinition g_script_add_options[] = {
15731f0f5b5bSZachary Turner     // clang-format off
15741f0f5b5bSZachary 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." },
15751f0f5b5bSZachary 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." },
15761f0f5b5bSZachary Turner   { LLDB_OPT_SET_1,   false, "help"  ,        'h', OptionParser::eRequiredArgument, nullptr, nullptr,               0, eArgTypeHelpText,                     "The help text to display for this command." },
15771f0f5b5bSZachary 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." },
15781f0f5b5bSZachary Turner     // clang-format on
15791f0f5b5bSZachary Turner };
15801f0f5b5bSZachary Turner 
1581b9c1b51eSKate Stone class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1582b9c1b51eSKate Stone                                        public IOHandlerDelegateMultiline {
15835a988416SJim Ingham public:
1584b9c1b51eSKate Stone   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1585b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script add",
15865a988416SJim Ingham                             "Add a scripted function as an LLDB command.",
15876e3d8e7fSEugene Zelenko                             nullptr),
1588b9c1b51eSKate Stone         IOHandlerDelegateMultiline("DONE"), m_options() {
15895a988416SJim Ingham     CommandArgumentEntry arg1;
15905a988416SJim Ingham     CommandArgumentData cmd_arg;
15915a988416SJim Ingham 
15925a988416SJim Ingham     // Define the first (and only) variant of this arg.
15935a988416SJim Ingham     cmd_arg.arg_type = eArgTypeCommandName;
15945a988416SJim Ingham     cmd_arg.arg_repetition = eArgRepeatPlain;
15955a988416SJim Ingham 
1596b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1597b9c1b51eSKate Stone     // argument entry.
15985a988416SJim Ingham     arg1.push_back(cmd_arg);
15995a988416SJim Ingham 
16005a988416SJim Ingham     // Push the data for the first argument into the m_arguments vector.
16015a988416SJim Ingham     m_arguments.push_back(arg1);
16025a988416SJim Ingham   }
16035a988416SJim Ingham 
16046e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptAdd() override = default;
16055a988416SJim Ingham 
1606b9c1b51eSKate Stone   Options *GetOptions() override { return &m_options; }
16075a988416SJim Ingham 
16085a988416SJim Ingham protected:
1609b9c1b51eSKate Stone   class CommandOptions : public Options {
1610223383edSEnrico Granata   public:
1611b9c1b51eSKate Stone     CommandOptions()
1612b9c1b51eSKate Stone         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1613b9c1b51eSKate Stone           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1614223383edSEnrico Granata 
16156e3d8e7fSEugene Zelenko     ~CommandOptions() override = default;
1616223383edSEnrico Granata 
1617fe11483bSZachary Turner     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1618b9c1b51eSKate Stone                          ExecutionContext *execution_context) override {
1619223383edSEnrico Granata       Error error;
16203bcdfc0eSGreg Clayton       const int short_option = m_getopt_table[option_idx].val;
1621223383edSEnrico Granata 
1622b9c1b51eSKate Stone       switch (short_option) {
1623223383edSEnrico Granata       case 'f':
1624fe11483bSZachary Turner         if (!option_arg.empty())
1625fe11483bSZachary Turner           m_funct_name = option_arg;
1626735152e3SEnrico Granata         break;
16279fe00e52SEnrico Granata       case 'c':
1628fe11483bSZachary Turner         if (!option_arg.empty())
1629fe11483bSZachary Turner           m_class_name = option_arg;
16309fe00e52SEnrico Granata         break;
1631735152e3SEnrico Granata       case 'h':
1632fe11483bSZachary Turner         if (!option_arg.empty())
1633fe11483bSZachary Turner           m_short_help = option_arg;
1634223383edSEnrico Granata         break;
16350a305db7SEnrico Granata       case 's':
1636b9c1b51eSKate Stone         m_synchronicity =
1637b9c1b51eSKate Stone             (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
1638fe11483bSZachary Turner                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
16390a305db7SEnrico Granata         if (!error.Success())
1640b9c1b51eSKate Stone           error.SetErrorStringWithFormat(
1641fe11483bSZachary Turner               "unrecognized value for synchronicity '%s'",
1642fe11483bSZachary Turner               option_arg.str().c_str());
16430a305db7SEnrico Granata         break;
1644223383edSEnrico Granata       default:
1645b9c1b51eSKate Stone         error.SetErrorStringWithFormat("unrecognized option '%c'",
1646b9c1b51eSKate Stone                                        short_option);
1647223383edSEnrico Granata         break;
1648223383edSEnrico Granata       }
1649223383edSEnrico Granata 
1650223383edSEnrico Granata       return error;
1651223383edSEnrico Granata     }
1652223383edSEnrico Granata 
1653b9c1b51eSKate Stone     void OptionParsingStarting(ExecutionContext *execution_context) override {
16549fe00e52SEnrico Granata       m_class_name.clear();
1655735152e3SEnrico Granata       m_funct_name.clear();
1656735152e3SEnrico Granata       m_short_help.clear();
165744d93782SGreg Clayton       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1658223383edSEnrico Granata     }
1659223383edSEnrico Granata 
16601f0f5b5bSZachary Turner     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
166170602439SZachary Turner       return llvm::makeArrayRef(g_script_add_options);
16621f0f5b5bSZachary Turner     }
1663223383edSEnrico Granata 
1664223383edSEnrico Granata     // Instance variables to hold the values for command options.
1665223383edSEnrico Granata 
16669fe00e52SEnrico Granata     std::string m_class_name;
1667223383edSEnrico Granata     std::string m_funct_name;
1668735152e3SEnrico Granata     std::string m_short_help;
166944d93782SGreg Clayton     ScriptedCommandSynchronicity m_synchronicity;
1670223383edSEnrico Granata   };
1671223383edSEnrico Granata 
1672b9c1b51eSKate Stone   void IOHandlerActivated(IOHandler &io_handler) override {
167344d93782SGreg Clayton     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1674b9c1b51eSKate Stone     if (output_sp) {
167544d93782SGreg Clayton       output_sp->PutCString(g_python_command_instructions);
167644d93782SGreg Clayton       output_sp->Flush();
1677223383edSEnrico Granata     }
1678223383edSEnrico Granata   }
1679223383edSEnrico Granata 
1680b9c1b51eSKate Stone   void IOHandlerInputComplete(IOHandler &io_handler,
1681b9c1b51eSKate Stone                               std::string &data) override {
168244d93782SGreg Clayton     StreamFileSP error_sp = io_handler.GetErrorStreamFile();
168344d93782SGreg Clayton 
168444d93782SGreg Clayton     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1685b9c1b51eSKate Stone     if (interpreter) {
168644d93782SGreg Clayton 
168744d93782SGreg Clayton       StringList lines;
168844d93782SGreg Clayton       lines.SplitIntoLines(data);
1689b9c1b51eSKate Stone       if (lines.GetSize() > 0) {
1690a73b7df7SEnrico Granata         std::string funct_name_str;
1691b9c1b51eSKate Stone         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1692b9c1b51eSKate Stone           if (funct_name_str.empty()) {
1693b9c1b51eSKate Stone             error_sp->Printf("error: unable to obtain a function name, didn't "
1694b9c1b51eSKate Stone                              "add python command.\n");
169544d93782SGreg Clayton             error_sp->Flush();
1696b9c1b51eSKate Stone           } else {
1697223383edSEnrico Granata             // everything should be fine now, let's add this alias
1698223383edSEnrico Granata 
1699b9c1b51eSKate Stone             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1700771ef6d4SMalcolm Parsons                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
170144d93782SGreg Clayton                 m_synchronicity));
1702223383edSEnrico Granata 
1703b9c1b51eSKate Stone             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1704b9c1b51eSKate Stone                                               true)) {
1705b9c1b51eSKate Stone               error_sp->Printf("error: unable to add selected command, didn't "
1706b9c1b51eSKate Stone                                "add python command.\n");
170744d93782SGreg Clayton               error_sp->Flush();
1708223383edSEnrico Granata             }
1709223383edSEnrico Granata           }
1710b9c1b51eSKate Stone         } else {
1711b9c1b51eSKate Stone           error_sp->Printf(
1712b9c1b51eSKate Stone               "error: unable to create function, didn't add python command.\n");
171344d93782SGreg Clayton           error_sp->Flush();
171444d93782SGreg Clayton         }
1715b9c1b51eSKate Stone       } else {
171644d93782SGreg Clayton         error_sp->Printf("error: empty function, didn't add python command.\n");
171744d93782SGreg Clayton         error_sp->Flush();
171844d93782SGreg Clayton       }
1719b9c1b51eSKate Stone     } else {
1720b9c1b51eSKate Stone       error_sp->Printf(
1721b9c1b51eSKate Stone           "error: script interpreter missing, didn't add python command.\n");
172244d93782SGreg Clayton       error_sp->Flush();
172344d93782SGreg Clayton     }
172444d93782SGreg Clayton 
172544d93782SGreg Clayton     io_handler.SetIsDone(true);
172644d93782SGreg Clayton   }
1727223383edSEnrico Granata 
17285a988416SJim Ingham protected:
1729b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1730b9c1b51eSKate Stone     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1731b9c1b51eSKate Stone         lldb::eScriptLanguagePython) {
1732b9c1b51eSKate Stone       result.AppendError("only scripting language supported for scripted "
1733b9c1b51eSKate Stone                          "commands is currently Python");
173499f0b8f9SEnrico Granata       result.SetStatus(eReturnStatusFailed);
173599f0b8f9SEnrico Granata       return false;
173699f0b8f9SEnrico Granata     }
173799f0b8f9SEnrico Granata 
173811eb9c64SZachary Turner     if (command.GetArgumentCount() != 1) {
1739223383edSEnrico Granata       result.AppendError("'command script add' requires one argument");
1740223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1741223383edSEnrico Granata       return false;
1742223383edSEnrico Granata     }
1743223383edSEnrico Granata 
1744735152e3SEnrico Granata     // Store the options in case we get multi-line input
17454574a890SZachary Turner     m_cmd_name = command[0].ref;
1746735152e3SEnrico Granata     m_short_help.assign(m_options.m_short_help);
174744d93782SGreg Clayton     m_synchronicity = m_options.m_synchronicity;
1748223383edSEnrico Granata 
1749b9c1b51eSKate Stone     if (m_options.m_class_name.empty()) {
1750b9c1b51eSKate Stone       if (m_options.m_funct_name.empty()) {
1751b9c1b51eSKate Stone         m_interpreter.GetPythonCommandsFromIOHandler(
1752b9c1b51eSKate Stone             "     ",  // Prompt
175344d93782SGreg Clayton             *this,    // IOHandlerDelegate
175444d93782SGreg Clayton             true,     // Run IOHandler in async mode
1755b9c1b51eSKate Stone             nullptr); // Baton for the "io_handler" that will be passed back
1756b9c1b51eSKate Stone                       // into our IOHandlerDelegate functions
1757b9c1b51eSKate Stone       } else {
1758b9c1b51eSKate Stone         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1759b9c1b51eSKate Stone             m_interpreter, m_cmd_name, m_options.m_funct_name,
1760b9c1b51eSKate Stone             m_options.m_short_help, m_synchronicity));
1761b9c1b51eSKate Stone         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1762223383edSEnrico Granata           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1763b9c1b51eSKate Stone         } else {
1764223383edSEnrico Granata           result.AppendError("cannot add command");
1765223383edSEnrico Granata           result.SetStatus(eReturnStatusFailed);
1766223383edSEnrico Granata         }
1767223383edSEnrico Granata       }
1768b9c1b51eSKate Stone     } else {
1769b9c1b51eSKate Stone       ScriptInterpreter *interpreter =
1770b9c1b51eSKate Stone           GetCommandInterpreter().GetScriptInterpreter();
1771b9c1b51eSKate Stone       if (!interpreter) {
17729fe00e52SEnrico Granata         result.AppendError("cannot find ScriptInterpreter");
17739fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17749fe00e52SEnrico Granata         return false;
17759fe00e52SEnrico Granata       }
17769fe00e52SEnrico Granata 
1777b9c1b51eSKate Stone       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1778b9c1b51eSKate Stone           m_options.m_class_name.c_str());
1779b9c1b51eSKate Stone       if (!cmd_obj_sp) {
17809fe00e52SEnrico Granata         result.AppendError("cannot create helper object");
17819fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17829fe00e52SEnrico Granata         return false;
17839fe00e52SEnrico Granata       }
17849fe00e52SEnrico Granata 
1785b9c1b51eSKate Stone       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1786b9c1b51eSKate Stone           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1787b9c1b51eSKate Stone       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
17889fe00e52SEnrico Granata         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1789b9c1b51eSKate Stone       } else {
17909fe00e52SEnrico Granata         result.AppendError("cannot add command");
17919fe00e52SEnrico Granata         result.SetStatus(eReturnStatusFailed);
17929fe00e52SEnrico Granata       }
17939fe00e52SEnrico Granata     }
1794223383edSEnrico Granata 
1795223383edSEnrico Granata     return result.Succeeded();
1796223383edSEnrico Granata   }
17975a988416SJim Ingham 
17985a988416SJim Ingham   CommandOptions m_options;
179944d93782SGreg Clayton   std::string m_cmd_name;
1800735152e3SEnrico Granata   std::string m_short_help;
180144d93782SGreg Clayton   ScriptedCommandSynchronicity m_synchronicity;
1802223383edSEnrico Granata };
1803223383edSEnrico Granata 
1804223383edSEnrico Granata //-------------------------------------------------------------------------
1805223383edSEnrico Granata // CommandObjectCommandsScriptList
1806223383edSEnrico Granata //-------------------------------------------------------------------------
1807223383edSEnrico Granata 
1808b9c1b51eSKate Stone class CommandObjectCommandsScriptList : public CommandObjectParsed {
1809223383edSEnrico Granata public:
1810b9c1b51eSKate Stone   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1811b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script list",
1812b9c1b51eSKate Stone                             "List defined scripted commands.", nullptr) {}
1813223383edSEnrico Granata 
18146e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptList() override = default;
1815223383edSEnrico Granata 
1816b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1817b9c1b51eSKate Stone     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1818223383edSEnrico Granata 
1819223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1820223383edSEnrico Granata 
1821223383edSEnrico Granata     return true;
1822223383edSEnrico Granata   }
1823223383edSEnrico Granata };
1824223383edSEnrico Granata 
1825223383edSEnrico Granata //-------------------------------------------------------------------------
1826223383edSEnrico Granata // CommandObjectCommandsScriptClear
1827223383edSEnrico Granata //-------------------------------------------------------------------------
1828223383edSEnrico Granata 
1829b9c1b51eSKate Stone class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1830223383edSEnrico Granata public:
1831b9c1b51eSKate Stone   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1832b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script clear",
1833b9c1b51eSKate Stone                             "Delete all scripted commands.", nullptr) {}
1834223383edSEnrico Granata 
18356e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptClear() override = default;
1836223383edSEnrico Granata 
18375a988416SJim Ingham protected:
1838b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1839223383edSEnrico Granata     m_interpreter.RemoveAllUser();
1840223383edSEnrico Granata 
1841223383edSEnrico Granata     result.SetStatus(eReturnStatusSuccessFinishResult);
1842223383edSEnrico Granata 
1843223383edSEnrico Granata     return true;
1844223383edSEnrico Granata   }
1845223383edSEnrico Granata };
1846223383edSEnrico Granata 
1847223383edSEnrico Granata //-------------------------------------------------------------------------
1848223383edSEnrico Granata // CommandObjectCommandsScriptDelete
1849223383edSEnrico Granata //-------------------------------------------------------------------------
1850223383edSEnrico Granata 
1851b9c1b51eSKate Stone class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1852223383edSEnrico Granata public:
1853b9c1b51eSKate Stone   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1854b9c1b51eSKate Stone       : CommandObjectParsed(interpreter, "command script delete",
1855b9c1b51eSKate Stone                             "Delete a scripted command.", nullptr) {
1856223383edSEnrico Granata     CommandArgumentEntry arg1;
1857223383edSEnrico Granata     CommandArgumentData cmd_arg;
1858223383edSEnrico Granata 
1859223383edSEnrico Granata     // Define the first (and only) variant of this arg.
1860223383edSEnrico Granata     cmd_arg.arg_type = eArgTypeCommandName;
1861223383edSEnrico Granata     cmd_arg.arg_repetition = eArgRepeatPlain;
1862223383edSEnrico Granata 
1863b9c1b51eSKate Stone     // There is only one variant this argument could be; put it into the
1864b9c1b51eSKate Stone     // argument entry.
1865223383edSEnrico Granata     arg1.push_back(cmd_arg);
1866223383edSEnrico Granata 
1867223383edSEnrico Granata     // Push the data for the first argument into the m_arguments vector.
1868223383edSEnrico Granata     m_arguments.push_back(arg1);
1869223383edSEnrico Granata   }
1870223383edSEnrico Granata 
18716e3d8e7fSEugene Zelenko   ~CommandObjectCommandsScriptDelete() override = default;
1872223383edSEnrico Granata 
18735a988416SJim Ingham protected:
1874b9c1b51eSKate Stone   bool DoExecute(Args &command, CommandReturnObject &result) override {
1875223383edSEnrico Granata 
187611eb9c64SZachary Turner     if (command.GetArgumentCount() != 1) {
1877223383edSEnrico Granata       result.AppendError("'command script delete' requires one argument");
1878223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
1879223383edSEnrico Granata       return false;
1880223383edSEnrico Granata     }
1881223383edSEnrico Granata 
18824574a890SZachary Turner     auto cmd_name = command[0].ref;
1883223383edSEnrico Granata 
18844574a890SZachary Turner     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
18854574a890SZachary Turner         !m_interpreter.UserCommandExists(cmd_name)) {
1886*867e7d17SZachary Turner       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1887223383edSEnrico Granata       result.SetStatus(eReturnStatusFailed);
18884574a890SZachary Turner       return false;
1889223383edSEnrico Granata     }
1890223383edSEnrico Granata 
18914574a890SZachary Turner     m_interpreter.RemoveUser(cmd_name);
18924574a890SZachary Turner     result.SetStatus(eReturnStatusSuccessFinishResult);
18934574a890SZachary Turner     return true;
1894223383edSEnrico Granata   }
1895223383edSEnrico Granata };
1896223383edSEnrico Granata 
1897223383edSEnrico Granata #pragma mark CommandObjectMultiwordCommandsScript
1898223383edSEnrico Granata 
1899223383edSEnrico Granata //-------------------------------------------------------------------------
1900223383edSEnrico Granata // CommandObjectMultiwordCommandsScript
1901223383edSEnrico Granata //-------------------------------------------------------------------------
1902223383edSEnrico Granata 
1903b9c1b51eSKate Stone class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1904223383edSEnrico Granata public:
19057428a18cSKate Stone   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1906b9c1b51eSKate Stone       : CommandObjectMultiword(
1907b9c1b51eSKate Stone             interpreter, "command script", "Commands for managing custom "
1908b9c1b51eSKate Stone                                            "commands implemented by "
1909b9c1b51eSKate Stone                                            "interpreter scripts.",
1910b9c1b51eSKate Stone             "command script <subcommand> [<subcommand-options>]") {
1911b9c1b51eSKate Stone     LoadSubCommand("add", CommandObjectSP(
1912b9c1b51eSKate Stone                               new CommandObjectCommandsScriptAdd(interpreter)));
1913b9c1b51eSKate Stone     LoadSubCommand(
1914b9c1b51eSKate Stone         "delete",
1915b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1916b9c1b51eSKate Stone     LoadSubCommand(
1917b9c1b51eSKate Stone         "clear",
1918b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1919b9c1b51eSKate Stone     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1920b9c1b51eSKate Stone                                interpreter)));
1921b9c1b51eSKate Stone     LoadSubCommand(
1922b9c1b51eSKate Stone         "import",
1923b9c1b51eSKate Stone         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1924223383edSEnrico Granata   }
1925223383edSEnrico Granata 
19266e3d8e7fSEugene Zelenko   ~CommandObjectMultiwordCommandsScript() override = default;
1927223383edSEnrico Granata };
1928223383edSEnrico Granata 
1929ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
1930ebc09c36SJim Ingham 
1931ebc09c36SJim Ingham //-------------------------------------------------------------------------
1932ebc09c36SJim Ingham // CommandObjectMultiwordCommands
1933ebc09c36SJim Ingham //-------------------------------------------------------------------------
1934ebc09c36SJim Ingham 
1935b9c1b51eSKate Stone CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1936b9c1b51eSKate Stone     CommandInterpreter &interpreter)
1937b9c1b51eSKate Stone     : CommandObjectMultiword(interpreter, "command",
1938b9c1b51eSKate Stone                              "Commands for managing custom LLDB commands.",
1939b9c1b51eSKate Stone                              "command <subcommand> [<subcommand-options>]") {
1940b9c1b51eSKate Stone   LoadSubCommand("source",
1941b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1942b9c1b51eSKate Stone   LoadSubCommand("alias",
1943b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1944b9c1b51eSKate Stone   LoadSubCommand("unalias", CommandObjectSP(
1945b9c1b51eSKate Stone                                 new CommandObjectCommandsUnalias(interpreter)));
1946b9c1b51eSKate Stone   LoadSubCommand("delete",
1947b9c1b51eSKate Stone                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1948b9c1b51eSKate Stone   LoadSubCommand(
1949b9c1b51eSKate Stone       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1950b9c1b51eSKate Stone   LoadSubCommand("history", CommandObjectSP(
1951b9c1b51eSKate Stone                                 new CommandObjectCommandsHistory(interpreter)));
1952b9c1b51eSKate Stone   LoadSubCommand(
1953b9c1b51eSKate Stone       "script",
1954b9c1b51eSKate Stone       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1955ebc09c36SJim Ingham }
1956ebc09c36SJim Ingham 
19576e3d8e7fSEugene Zelenko CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1958