1435933ddSDimitry Andric //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "llvm/ADT/StringRef.h"
11ac7ddfbfSEd Maste 
124bb0738eSEd Maste #include "CommandObjectCommands.h"
134bb0738eSEd Maste #include "CommandObjectHelp.h"
14ac7ddfbfSEd Maste #include "lldb/Core/Debugger.h"
1512b93ac6SEd Maste #include "lldb/Core/IOHandler.h"
16f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
17ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandHistory.h"
18ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
19ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandObjectRegexCommand.h"
20ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
214ba319b5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
22ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionValueBoolean.h"
234bb0738eSEd Maste #include "lldb/Interpreter/OptionValueString.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/OptionValueUInt64.h"
25ac7ddfbfSEd Maste #include "lldb/Interpreter/Options.h"
26ac7ddfbfSEd Maste #include "lldb/Interpreter/ScriptInterpreter.h"
274ba319b5SDimitry Andric #include "lldb/Utility/Args.h"
28f678e45dSDimitry Andric #include "lldb/Utility/StringList.h"
29ac7ddfbfSEd Maste 
30ac7ddfbfSEd Maste using namespace lldb;
31ac7ddfbfSEd Maste using namespace lldb_private;
32ac7ddfbfSEd Maste 
33ac7ddfbfSEd Maste //-------------------------------------------------------------------------
34ac7ddfbfSEd Maste // CommandObjectCommandsSource
35ac7ddfbfSEd Maste //-------------------------------------------------------------------------
36ac7ddfbfSEd Maste 
37*b5893f02SDimitry Andric static constexpr OptionDefinition g_history_options[] = {
38435933ddSDimitry Andric     // clang-format off
39*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "count",       'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
40*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." },
41*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "end-index",   'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
42*b5893f02SDimitry Andric   { LLDB_OPT_SET_2, false, "clear",       'C', OptionParser::eNoArgument,       nullptr, {}, 0, eArgTypeBoolean,         "Clears the current command history." },
43435933ddSDimitry Andric     // clang-format on
44435933ddSDimitry Andric };
45435933ddSDimitry Andric 
46435933ddSDimitry Andric class CommandObjectCommandsHistory : public CommandObjectParsed {
47ac7ddfbfSEd Maste public:
CommandObjectCommandsHistory(CommandInterpreter & interpreter)48435933ddSDimitry Andric   CommandObjectCommandsHistory(CommandInterpreter &interpreter)
49435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "command history",
506bc11b14SDimitry Andric                             "Dump the history of commands in this session.\n"
516bc11b14SDimitry Andric                             "Commands in the history list can be run again "
526bc11b14SDimitry Andric                             "using \"!<INDEX>\".   \"!-<OFFSET>\" will re-run "
536bc11b14SDimitry Andric                             "the command that is <OFFSET> commands from the end"
546bc11b14SDimitry Andric                             " of the list (counting the current command).",
554bb0738eSEd Maste                             nullptr),
56435933ddSDimitry Andric         m_options() {}
57ac7ddfbfSEd Maste 
584bb0738eSEd Maste   ~CommandObjectCommandsHistory() override = default;
59ac7ddfbfSEd Maste 
GetOptions()60435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
61ac7ddfbfSEd Maste 
62ac7ddfbfSEd Maste protected:
63435933ddSDimitry Andric   class CommandOptions : public Options {
64ac7ddfbfSEd Maste   public:
CommandOptions()65435933ddSDimitry Andric     CommandOptions()
66435933ddSDimitry Andric         : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
67ac7ddfbfSEd Maste     }
68ac7ddfbfSEd Maste 
694bb0738eSEd Maste     ~CommandOptions() override = default;
70ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)715517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
72435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
735517e702SDimitry Andric       Status error;
74ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
75ac7ddfbfSEd Maste 
76435933ddSDimitry Andric       switch (short_option) {
77ac7ddfbfSEd Maste       case 'c':
781c3bbb01SEd Maste         error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
79ac7ddfbfSEd Maste         break;
80ac7ddfbfSEd Maste       case 's':
81435933ddSDimitry Andric         if (option_arg == "end") {
82ac7ddfbfSEd Maste           m_start_idx.SetCurrentValue(UINT64_MAX);
83ac7ddfbfSEd Maste           m_start_idx.SetOptionWasSet();
84435933ddSDimitry Andric         } else
85435933ddSDimitry Andric           error = m_start_idx.SetValueFromString(option_arg,
86435933ddSDimitry Andric                                                  eVarSetOperationAssign);
87ac7ddfbfSEd Maste         break;
88ac7ddfbfSEd Maste       case 'e':
89435933ddSDimitry Andric         error =
90435933ddSDimitry Andric             m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
91ac7ddfbfSEd Maste         break;
92ac7ddfbfSEd Maste       case 'C':
93ac7ddfbfSEd Maste         m_clear.SetCurrentValue(true);
94ac7ddfbfSEd Maste         m_clear.SetOptionWasSet();
95ac7ddfbfSEd Maste         break;
96ac7ddfbfSEd Maste       default:
97435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
98435933ddSDimitry Andric                                        short_option);
99ac7ddfbfSEd Maste         break;
100ac7ddfbfSEd Maste       }
101ac7ddfbfSEd Maste 
102ac7ddfbfSEd Maste       return error;
103ac7ddfbfSEd Maste     }
104ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)105435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
106ac7ddfbfSEd Maste       m_start_idx.Clear();
107ac7ddfbfSEd Maste       m_stop_idx.Clear();
108ac7ddfbfSEd Maste       m_count.Clear();
109ac7ddfbfSEd Maste       m_clear.Clear();
110ac7ddfbfSEd Maste     }
111ac7ddfbfSEd Maste 
GetDefinitions()112435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
113435933ddSDimitry Andric       return llvm::makeArrayRef(g_history_options);
114ac7ddfbfSEd Maste     }
115ac7ddfbfSEd Maste 
116ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
117ac7ddfbfSEd Maste 
118ac7ddfbfSEd Maste     OptionValueUInt64 m_start_idx;
119ac7ddfbfSEd Maste     OptionValueUInt64 m_stop_idx;
120ac7ddfbfSEd Maste     OptionValueUInt64 m_count;
121ac7ddfbfSEd Maste     OptionValueBoolean m_clear;
122ac7ddfbfSEd Maste   };
123ac7ddfbfSEd Maste 
DoExecute(Args & command,CommandReturnObject & result)124435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
125435933ddSDimitry Andric     if (m_options.m_clear.GetCurrentValue() &&
126435933ddSDimitry Andric         m_options.m_clear.OptionWasSet()) {
127ac7ddfbfSEd Maste       m_interpreter.GetCommandHistory().Clear();
128ac7ddfbfSEd Maste       result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
129435933ddSDimitry Andric     } else {
130435933ddSDimitry Andric       if (m_options.m_start_idx.OptionWasSet() &&
131435933ddSDimitry Andric           m_options.m_stop_idx.OptionWasSet() &&
132435933ddSDimitry Andric           m_options.m_count.OptionWasSet()) {
133435933ddSDimitry Andric         result.AppendError("--count, --start-index and --end-index cannot be "
134435933ddSDimitry Andric                            "all specified in the same invocation");
135ac7ddfbfSEd Maste         result.SetStatus(lldb::eReturnStatusFailed);
136435933ddSDimitry Andric       } else {
137435933ddSDimitry Andric         std::pair<bool, uint64_t> start_idx(
138435933ddSDimitry Andric             m_options.m_start_idx.OptionWasSet(),
139435933ddSDimitry Andric             m_options.m_start_idx.GetCurrentValue());
140435933ddSDimitry Andric         std::pair<bool, uint64_t> stop_idx(
141435933ddSDimitry Andric             m_options.m_stop_idx.OptionWasSet(),
142435933ddSDimitry Andric             m_options.m_stop_idx.GetCurrentValue());
143435933ddSDimitry Andric         std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
144435933ddSDimitry Andric                                         m_options.m_count.GetCurrentValue());
145ac7ddfbfSEd Maste 
146ac7ddfbfSEd Maste         const CommandHistory &history(m_interpreter.GetCommandHistory());
147ac7ddfbfSEd Maste 
148435933ddSDimitry Andric         if (start_idx.first && start_idx.second == UINT64_MAX) {
149435933ddSDimitry Andric           if (count.first) {
150ac7ddfbfSEd Maste             start_idx.second = history.GetSize() - count.second;
151ac7ddfbfSEd Maste             stop_idx.second = history.GetSize() - 1;
152435933ddSDimitry Andric           } else if (stop_idx.first) {
153ac7ddfbfSEd Maste             start_idx.second = stop_idx.second;
154ac7ddfbfSEd Maste             stop_idx.second = history.GetSize() - 1;
155435933ddSDimitry Andric           } else {
156ac7ddfbfSEd Maste             start_idx.second = 0;
157ac7ddfbfSEd Maste             stop_idx.second = history.GetSize() - 1;
158ac7ddfbfSEd Maste           }
159435933ddSDimitry Andric         } else {
160435933ddSDimitry Andric           if (!start_idx.first && !stop_idx.first && !count.first) {
161ac7ddfbfSEd Maste             start_idx.second = 0;
162ac7ddfbfSEd Maste             stop_idx.second = history.GetSize() - 1;
163435933ddSDimitry Andric           } else if (start_idx.first) {
164435933ddSDimitry Andric             if (count.first) {
165ac7ddfbfSEd Maste               stop_idx.second = start_idx.second + count.second - 1;
166435933ddSDimitry Andric             } else if (!stop_idx.first) {
167ac7ddfbfSEd Maste               stop_idx.second = history.GetSize() - 1;
168ac7ddfbfSEd Maste             }
169435933ddSDimitry Andric           } else if (stop_idx.first) {
170435933ddSDimitry Andric             if (count.first) {
171ac7ddfbfSEd Maste               if (stop_idx.second >= count.second)
172ac7ddfbfSEd Maste                 start_idx.second = stop_idx.second - count.second + 1;
173ac7ddfbfSEd Maste               else
174ac7ddfbfSEd Maste                 start_idx.second = 0;
175ac7ddfbfSEd Maste             }
176435933ddSDimitry Andric           } else /* if (count.first) */
177ac7ddfbfSEd Maste           {
178ac7ddfbfSEd Maste             start_idx.second = 0;
179ac7ddfbfSEd Maste             stop_idx.second = count.second - 1;
180ac7ddfbfSEd Maste           }
181ac7ddfbfSEd Maste         }
182435933ddSDimitry Andric         history.Dump(result.GetOutputStream(), start_idx.second,
183435933ddSDimitry Andric                      stop_idx.second);
184ac7ddfbfSEd Maste       }
185ac7ddfbfSEd Maste     }
186ac7ddfbfSEd Maste     return result.Succeeded();
187ac7ddfbfSEd Maste   }
188ac7ddfbfSEd Maste 
189ac7ddfbfSEd Maste   CommandOptions m_options;
190ac7ddfbfSEd Maste };
191ac7ddfbfSEd Maste 
192ac7ddfbfSEd Maste //-------------------------------------------------------------------------
193ac7ddfbfSEd Maste // CommandObjectCommandsSource
194ac7ddfbfSEd Maste //-------------------------------------------------------------------------
195ac7ddfbfSEd Maste 
196*b5893f02SDimitry Andric static constexpr OptionDefinition g_source_options[] = {
197435933ddSDimitry Andric     // clang-format off
198*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "stop-on-error",    'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
199*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
200*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "silent-run",       's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
201435933ddSDimitry Andric     // clang-format on
202435933ddSDimitry Andric };
203435933ddSDimitry Andric 
204435933ddSDimitry Andric class CommandObjectCommandsSource : public CommandObjectParsed {
205ac7ddfbfSEd Maste public:
CommandObjectCommandsSource(CommandInterpreter & interpreter)2064bb0738eSEd Maste   CommandObjectCommandsSource(CommandInterpreter &interpreter)
207435933ddSDimitry Andric       : CommandObjectParsed(
208435933ddSDimitry Andric             interpreter, "command source",
209435933ddSDimitry Andric             "Read and execute LLDB commands from the file <filename>.",
2104bb0738eSEd Maste             nullptr),
211435933ddSDimitry Andric         m_options() {
212ac7ddfbfSEd Maste     CommandArgumentEntry arg;
213ac7ddfbfSEd Maste     CommandArgumentData file_arg;
214ac7ddfbfSEd Maste 
215ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
216ac7ddfbfSEd Maste     file_arg.arg_type = eArgTypeFilename;
217ac7ddfbfSEd Maste     file_arg.arg_repetition = eArgRepeatPlain;
218ac7ddfbfSEd Maste 
219435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
220435933ddSDimitry Andric     // argument entry.
221ac7ddfbfSEd Maste     arg.push_back(file_arg);
222ac7ddfbfSEd Maste 
223ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
224ac7ddfbfSEd Maste     m_arguments.push_back(arg);
225ac7ddfbfSEd Maste   }
226ac7ddfbfSEd Maste 
2274bb0738eSEd Maste   ~CommandObjectCommandsSource() override = default;
228ac7ddfbfSEd Maste 
GetRepeatCommand(Args & current_command_args,uint32_t index)229435933ddSDimitry Andric   const char *GetRepeatCommand(Args &current_command_args,
230435933ddSDimitry Andric                                uint32_t index) override {
231ac7ddfbfSEd Maste     return "";
232ac7ddfbfSEd Maste   }
233ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)2344ba319b5SDimitry Andric   int HandleArgumentCompletion(
2354ba319b5SDimitry Andric       CompletionRequest &request,
2364ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
237435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
238435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
2394ba319b5SDimitry Andric         request, nullptr);
2404ba319b5SDimitry Andric     return request.GetNumberOfMatches();
241ac7ddfbfSEd Maste   }
242ac7ddfbfSEd Maste 
GetOptions()243435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
244ac7ddfbfSEd Maste 
245ac7ddfbfSEd Maste protected:
246435933ddSDimitry Andric   class CommandOptions : public Options {
247ac7ddfbfSEd Maste   public:
CommandOptions()248435933ddSDimitry Andric     CommandOptions()
249435933ddSDimitry Andric         : Options(), m_stop_on_error(true), m_silent_run(false),
250435933ddSDimitry Andric           m_stop_on_continue(true) {}
251ac7ddfbfSEd Maste 
2524bb0738eSEd Maste     ~CommandOptions() override = default;
253ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2545517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
255435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
2565517e702SDimitry Andric       Status error;
257ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
258ac7ddfbfSEd Maste 
259435933ddSDimitry Andric       switch (short_option) {
260ac7ddfbfSEd Maste       case 'e':
2611c3bbb01SEd Maste         error = m_stop_on_error.SetValueFromString(option_arg);
262ac7ddfbfSEd Maste         break;
26312b93ac6SEd Maste 
264ac7ddfbfSEd Maste       case 'c':
2651c3bbb01SEd Maste         error = m_stop_on_continue.SetValueFromString(option_arg);
266ac7ddfbfSEd Maste         break;
26712b93ac6SEd Maste 
268ac7ddfbfSEd Maste       case 's':
2691c3bbb01SEd Maste         error = m_silent_run.SetValueFromString(option_arg);
270ac7ddfbfSEd Maste         break;
27112b93ac6SEd Maste 
272ac7ddfbfSEd Maste       default:
273435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
274435933ddSDimitry Andric                                        short_option);
275ac7ddfbfSEd Maste         break;
276ac7ddfbfSEd Maste       }
277ac7ddfbfSEd Maste 
278ac7ddfbfSEd Maste       return error;
279ac7ddfbfSEd Maste     }
280ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)281435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
282ac7ddfbfSEd Maste       m_stop_on_error.Clear();
28312b93ac6SEd Maste       m_silent_run.Clear();
28412b93ac6SEd Maste       m_stop_on_continue.Clear();
285ac7ddfbfSEd Maste     }
286ac7ddfbfSEd Maste 
GetDefinitions()287435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
288435933ddSDimitry Andric       return llvm::makeArrayRef(g_source_options);
289ac7ddfbfSEd Maste     }
290ac7ddfbfSEd Maste 
291ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
292ac7ddfbfSEd Maste 
293ac7ddfbfSEd Maste     OptionValueBoolean m_stop_on_error;
29412b93ac6SEd Maste     OptionValueBoolean m_silent_run;
29512b93ac6SEd Maste     OptionValueBoolean m_stop_on_continue;
296ac7ddfbfSEd Maste   };
297ac7ddfbfSEd Maste 
DoExecute(Args & command,CommandReturnObject & result)298435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
299435933ddSDimitry Andric     if (command.GetArgumentCount() != 1) {
300435933ddSDimitry Andric       result.AppendErrorWithFormat(
301435933ddSDimitry Andric           "'%s' takes exactly one executable filename argument.\n",
302435933ddSDimitry Andric           GetCommandName().str().c_str());
303435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
304435933ddSDimitry Andric       return false;
305435933ddSDimitry Andric     }
306ac7ddfbfSEd Maste 
307*b5893f02SDimitry Andric     FileSpec cmd_file(command[0].ref);
308*b5893f02SDimitry Andric     FileSystem::Instance().Resolve(cmd_file);
3094bb0738eSEd Maste     ExecutionContext *exe_ctx = nullptr; // Just use the default context.
310ac7ddfbfSEd Maste 
31112b93ac6SEd Maste     // If any options were set, then use them
31212b93ac6SEd Maste     if (m_options.m_stop_on_error.OptionWasSet() ||
31312b93ac6SEd Maste         m_options.m_silent_run.OptionWasSet() ||
314435933ddSDimitry Andric         m_options.m_stop_on_continue.OptionWasSet()) {
31512b93ac6SEd Maste       // Use user set settings
3167aa51b79SEd Maste       CommandInterpreterRunOptions options;
3177aa51b79SEd Maste       options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
3187aa51b79SEd Maste       options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
319*b5893f02SDimitry Andric 
320*b5893f02SDimitry Andric       // Individual silent setting is override for global command echo settings.
321*b5893f02SDimitry Andric       if (m_options.m_silent_run.GetCurrentValue()) {
322*b5893f02SDimitry Andric         options.SetSilent(true);
323*b5893f02SDimitry Andric       } else {
324*b5893f02SDimitry Andric         options.SetPrintResults(true);
325*b5893f02SDimitry Andric         options.SetEchoCommands(m_interpreter.GetEchoCommands());
326*b5893f02SDimitry Andric         options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
327*b5893f02SDimitry Andric       }
3287aa51b79SEd Maste 
329435933ddSDimitry Andric       m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
330435933ddSDimitry Andric     } else {
3314ba319b5SDimitry Andric       // No options were set, inherit any settings from nested "command source"
3324ba319b5SDimitry Andric       // commands, or set to sane default settings...
3337aa51b79SEd Maste       CommandInterpreterRunOptions options;
334435933ddSDimitry Andric       m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
335ac7ddfbfSEd Maste     }
336ac7ddfbfSEd Maste     return result.Succeeded();
337ac7ddfbfSEd Maste   }
3384bb0738eSEd Maste 
339ac7ddfbfSEd Maste   CommandOptions m_options;
340ac7ddfbfSEd Maste };
341ac7ddfbfSEd Maste 
342ac7ddfbfSEd Maste #pragma mark CommandObjectCommandsAlias
343ac7ddfbfSEd Maste //-------------------------------------------------------------------------
344ac7ddfbfSEd Maste // CommandObjectCommandsAlias
345ac7ddfbfSEd Maste //-------------------------------------------------------------------------
346ac7ddfbfSEd Maste 
347*b5893f02SDimitry Andric static constexpr OptionDefinition g_alias_options[] = {
348435933ddSDimitry Andric     // clang-format off
349*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "help",      'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" },
350*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" },
351435933ddSDimitry Andric     // clang-format on
352435933ddSDimitry Andric };
353435933ddSDimitry Andric 
354435933ddSDimitry Andric static const char *g_python_command_instructions =
355435933ddSDimitry Andric     "Enter your Python command(s). Type 'DONE' to end.\n"
356ac7ddfbfSEd Maste     "You must define a Python function with this signature:\n"
35712b93ac6SEd Maste     "def my_command_impl(debugger, args, result, internal_dict):\n";
358ac7ddfbfSEd Maste 
359435933ddSDimitry Andric class CommandObjectCommandsAlias : public CommandObjectRaw {
3604bb0738eSEd Maste protected:
361435933ddSDimitry Andric   class CommandOptions : public OptionGroup {
3624bb0738eSEd Maste   public:
CommandOptions()363435933ddSDimitry Andric     CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
364ac7ddfbfSEd Maste 
3654bb0738eSEd Maste     ~CommandOptions() override = default;
3664bb0738eSEd Maste 
GetDefinitions()367435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
368435933ddSDimitry Andric       return llvm::makeArrayRef(g_alias_options);
3694bb0738eSEd Maste     }
3704bb0738eSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_value,ExecutionContext * execution_context)3715517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
372435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
3735517e702SDimitry Andric       Status error;
3744bb0738eSEd Maste 
375435933ddSDimitry Andric       const int short_option = GetDefinitions()[option_idx].short_option;
376435933ddSDimitry Andric       std::string option_str(option_value);
3774bb0738eSEd Maste 
378435933ddSDimitry Andric       switch (short_option) {
3794bb0738eSEd Maste       case 'h':
380435933ddSDimitry Andric         m_help.SetCurrentValue(option_str);
3814bb0738eSEd Maste         m_help.SetOptionWasSet();
3824bb0738eSEd Maste         break;
3834bb0738eSEd Maste 
3844bb0738eSEd Maste       case 'H':
385435933ddSDimitry Andric         m_long_help.SetCurrentValue(option_str);
3864bb0738eSEd Maste         m_long_help.SetOptionWasSet();
3874bb0738eSEd Maste         break;
3884bb0738eSEd Maste 
3894bb0738eSEd Maste       default:
390435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
391435933ddSDimitry Andric                                        short_option);
3924bb0738eSEd Maste         break;
3934bb0738eSEd Maste       }
3944bb0738eSEd Maste 
3954bb0738eSEd Maste       return error;
3964bb0738eSEd Maste     }
3974bb0738eSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)398435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
3994bb0738eSEd Maste       m_help.Clear();
4004bb0738eSEd Maste       m_long_help.Clear();
4014bb0738eSEd Maste     }
4024bb0738eSEd Maste 
4034bb0738eSEd Maste     OptionValueString m_help;
4044bb0738eSEd Maste     OptionValueString m_long_help;
4054bb0738eSEd Maste   };
4064bb0738eSEd Maste 
4074bb0738eSEd Maste   OptionGroupOptions m_option_group;
4084bb0738eSEd Maste   CommandOptions m_command_options;
409ac7ddfbfSEd Maste 
410ac7ddfbfSEd Maste public:
GetOptions()411435933ddSDimitry Andric   Options *GetOptions() override { return &m_option_group; }
4124bb0738eSEd Maste 
CommandObjectCommandsAlias(CommandInterpreter & interpreter)4134bb0738eSEd Maste   CommandObjectCommandsAlias(CommandInterpreter &interpreter)
414435933ddSDimitry Andric       : CommandObjectRaw(
415435933ddSDimitry Andric             interpreter, "command alias",
416435933ddSDimitry Andric             "Define a custom command in terms of an existing command."),
417435933ddSDimitry Andric         m_option_group(), m_command_options() {
4184bb0738eSEd Maste     m_option_group.Append(&m_command_options);
4194bb0738eSEd Maste     m_option_group.Finalize();
4204bb0738eSEd Maste 
421ac7ddfbfSEd Maste     SetHelpLong(
422b91a7dfcSDimitry Andric         "'alias' allows the user to create a short-cut or abbreviation for long \
423b91a7dfcSDimitry Andric commands, multi-word commands, and commands that take particular options.  \
424435933ddSDimitry Andric Below are some simple examples of how one might use the 'alias' command:"
425435933ddSDimitry Andric         R"(
426b91a7dfcSDimitry Andric 
427b91a7dfcSDimitry Andric (lldb) command alias sc script
428b91a7dfcSDimitry Andric 
429b91a7dfcSDimitry Andric     Creates the abbreviation 'sc' for the 'script' command.
430b91a7dfcSDimitry Andric 
431b91a7dfcSDimitry Andric (lldb) command alias bp breakpoint
432b91a7dfcSDimitry Andric 
433435933ddSDimitry Andric )"
434435933ddSDimitry Andric         "    Creates the abbreviation 'bp' for the 'breakpoint' command.  Since \
435b91a7dfcSDimitry Andric breakpoint commands are two-word commands, the user would still need to \
436435933ddSDimitry Andric enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
437435933ddSDimitry Andric         R"(
438b91a7dfcSDimitry Andric 
439b91a7dfcSDimitry Andric (lldb) command alias bpl breakpoint list
440b91a7dfcSDimitry Andric 
441b91a7dfcSDimitry Andric     Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
442b91a7dfcSDimitry Andric 
443435933ddSDimitry Andric )"
444435933ddSDimitry Andric         "An alias can include some options for the command, with the values either \
445b91a7dfcSDimitry Andric filled in at the time the alias is created, or specified as positional \
446b91a7dfcSDimitry Andric arguments, to be filled in when the alias is invoked.  The following example \
447435933ddSDimitry Andric shows how to create aliases with options:"
448435933ddSDimitry Andric         R"(
449b91a7dfcSDimitry Andric 
450b91a7dfcSDimitry Andric (lldb) command alias bfl breakpoint set -f %1 -l %2
451b91a7dfcSDimitry Andric 
452435933ddSDimitry Andric )"
453435933ddSDimitry Andric         "    Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
454b91a7dfcSDimitry Andric options already part of the alias.  So if the user wants to set a breakpoint \
455b91a7dfcSDimitry Andric by file and line without explicitly having to use the -f and -l options, the \
456b91a7dfcSDimitry Andric user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \
457b91a7dfcSDimitry Andric for the actual arguments that will be passed when the alias command is used.  \
458b91a7dfcSDimitry Andric The number in the placeholder refers to the position/order the actual value \
459b91a7dfcSDimitry Andric occupies when the alias is used.  All the occurrences of '%1' in the alias \
460b91a7dfcSDimitry Andric will be replaced with the first argument, all the occurrences of '%2' in the \
461b91a7dfcSDimitry Andric alias will be replaced with the second argument, and so on.  This also allows \
462b91a7dfcSDimitry Andric actual arguments to be used multiple times within an alias (see 'process \
463435933ddSDimitry Andric launch' example below)."
464435933ddSDimitry Andric         R"(
465b91a7dfcSDimitry Andric 
466435933ddSDimitry Andric )"
467435933ddSDimitry Andric         "Note: the positional arguments must substitute as whole words in the resultant \
468b91a7dfcSDimitry Andric command, so you can't at present do something like this to append the file extension \
469435933ddSDimitry Andric \".cpp\":"
470435933ddSDimitry Andric         R"(
471b91a7dfcSDimitry Andric 
472b91a7dfcSDimitry Andric (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
473b91a7dfcSDimitry Andric 
474435933ddSDimitry Andric )"
475435933ddSDimitry Andric         "For more complex aliasing, use the \"command regex\" command instead.  In the \
476b91a7dfcSDimitry Andric 'bfl' case above, the actual file value will be filled in with the first argument \
477b91a7dfcSDimitry Andric following 'bfl' and the actual line number value will be filled in with the second \
478435933ddSDimitry Andric argument.  The user would use this alias as follows:"
479435933ddSDimitry Andric         R"(
480b91a7dfcSDimitry Andric 
481b91a7dfcSDimitry Andric (lldb) command alias bfl breakpoint set -f %1 -l %2
482b91a7dfcSDimitry Andric (lldb) bfl my-file.c 137
483b91a7dfcSDimitry Andric 
484b91a7dfcSDimitry Andric This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
485b91a7dfcSDimitry Andric 
486b91a7dfcSDimitry Andric Another example:
487b91a7dfcSDimitry Andric 
488b91a7dfcSDimitry Andric (lldb) command alias pltty process launch -s -o %1 -e %1
489b91a7dfcSDimitry Andric (lldb) pltty /dev/tty0
490b91a7dfcSDimitry Andric 
491b91a7dfcSDimitry Andric     Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
492b91a7dfcSDimitry Andric 
493435933ddSDimitry Andric )"
494435933ddSDimitry Andric         "If the user always wanted to pass the same value to a particular option, the \
495b91a7dfcSDimitry Andric alias could be defined with that value directly in the alias as a constant, \
496435933ddSDimitry Andric rather than using a positional placeholder:"
497435933ddSDimitry Andric         R"(
498b91a7dfcSDimitry Andric 
499b91a7dfcSDimitry Andric (lldb) command alias bl3 breakpoint set -f %1 -l 3
500b91a7dfcSDimitry Andric 
501435933ddSDimitry Andric     Always sets a breakpoint on line 3 of whatever file is indicated.)");
502ac7ddfbfSEd Maste 
503ac7ddfbfSEd Maste     CommandArgumentEntry arg1;
504ac7ddfbfSEd Maste     CommandArgumentEntry arg2;
505ac7ddfbfSEd Maste     CommandArgumentEntry arg3;
506ac7ddfbfSEd Maste     CommandArgumentData alias_arg;
507ac7ddfbfSEd Maste     CommandArgumentData cmd_arg;
508ac7ddfbfSEd Maste     CommandArgumentData options_arg;
509ac7ddfbfSEd Maste 
510ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
511ac7ddfbfSEd Maste     alias_arg.arg_type = eArgTypeAliasName;
512ac7ddfbfSEd Maste     alias_arg.arg_repetition = eArgRepeatPlain;
513ac7ddfbfSEd Maste 
514435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
515435933ddSDimitry Andric     // argument entry.
516ac7ddfbfSEd Maste     arg1.push_back(alias_arg);
517ac7ddfbfSEd Maste 
518ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
519ac7ddfbfSEd Maste     cmd_arg.arg_type = eArgTypeCommandName;
520ac7ddfbfSEd Maste     cmd_arg.arg_repetition = eArgRepeatPlain;
521ac7ddfbfSEd Maste 
522435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
523435933ddSDimitry Andric     // argument entry.
524ac7ddfbfSEd Maste     arg2.push_back(cmd_arg);
525ac7ddfbfSEd Maste 
526ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
527ac7ddfbfSEd Maste     options_arg.arg_type = eArgTypeAliasOptions;
528ac7ddfbfSEd Maste     options_arg.arg_repetition = eArgRepeatOptional;
529ac7ddfbfSEd Maste 
530435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
531435933ddSDimitry Andric     // argument entry.
532ac7ddfbfSEd Maste     arg3.push_back(options_arg);
533ac7ddfbfSEd Maste 
534ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
535ac7ddfbfSEd Maste     m_arguments.push_back(arg1);
536ac7ddfbfSEd Maste     m_arguments.push_back(arg2);
537ac7ddfbfSEd Maste     m_arguments.push_back(arg3);
538ac7ddfbfSEd Maste   }
539ac7ddfbfSEd Maste 
5404bb0738eSEd Maste   ~CommandObjectCommandsAlias() override = default;
541ac7ddfbfSEd Maste 
542ac7ddfbfSEd Maste protected:
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)5434ba319b5SDimitry Andric   bool DoExecute(llvm::StringRef raw_command_line,
544435933ddSDimitry Andric                  CommandReturnObject &result) override {
5454ba319b5SDimitry Andric     if (raw_command_line.empty()) {
5464bb0738eSEd Maste       result.AppendError("'command alias' requires at least two arguments");
5474bb0738eSEd Maste       return false;
5484bb0738eSEd Maste     }
5494bb0738eSEd Maste 
550435933ddSDimitry Andric     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
551435933ddSDimitry Andric     m_option_group.NotifyOptionParsingStarting(&exe_ctx);
5524bb0738eSEd Maste 
5534ba319b5SDimitry Andric     OptionsWithRaw args_with_suffix(raw_command_line);
5544ba319b5SDimitry Andric     const char *remainder = args_with_suffix.GetRawPart().c_str();
5554bb0738eSEd Maste 
5564ba319b5SDimitry Andric     if (args_with_suffix.HasArgs())
5574ba319b5SDimitry Andric       if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result,
5584ba319b5SDimitry Andric                                  m_option_group, exe_ctx))
5594bb0738eSEd Maste         return false;
5604bb0738eSEd Maste 
561435933ddSDimitry Andric     llvm::StringRef raw_command_string(remainder);
562435933ddSDimitry Andric     Args args(raw_command_string);
563ac7ddfbfSEd Maste 
564435933ddSDimitry Andric     if (args.GetArgumentCount() < 2) {
5654bb0738eSEd Maste       result.AppendError("'command alias' requires at least two arguments");
566ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
567ac7ddfbfSEd Maste       return false;
568ac7ddfbfSEd Maste     }
569ac7ddfbfSEd Maste 
570ac7ddfbfSEd Maste     // Get the alias command.
571ac7ddfbfSEd Maste 
572435933ddSDimitry Andric     auto alias_command = args[0].ref;
573435933ddSDimitry Andric     if (alias_command.startswith("-")) {
5744bb0738eSEd Maste       result.AppendError("aliases starting with a dash are not supported");
575435933ddSDimitry Andric       if (alias_command == "--help" || alias_command == "--long-help") {
576435933ddSDimitry Andric         result.AppendWarning("if trying to pass options to 'command alias' add "
577435933ddSDimitry Andric                              "a -- at the end of the options");
5784bb0738eSEd Maste       }
5794bb0738eSEd Maste       result.SetStatus(eReturnStatusFailed);
5804bb0738eSEd Maste       return false;
5814bb0738eSEd Maste     }
582ac7ddfbfSEd Maste 
583435933ddSDimitry Andric     // Strip the new alias name off 'raw_command_string'  (leave it on args,
5844ba319b5SDimitry Andric     // which gets passed to 'Execute', which does the stripping itself.
585ac7ddfbfSEd Maste     size_t pos = raw_command_string.find(alias_command);
586435933ddSDimitry Andric     if (pos == 0) {
587ac7ddfbfSEd Maste       raw_command_string = raw_command_string.substr(alias_command.size());
588ac7ddfbfSEd Maste       pos = raw_command_string.find_first_not_of(' ');
589ac7ddfbfSEd Maste       if ((pos != std::string::npos) && (pos > 0))
590ac7ddfbfSEd Maste         raw_command_string = raw_command_string.substr(pos);
591435933ddSDimitry Andric     } else {
592ac7ddfbfSEd Maste       result.AppendError("Error parsing command string.  No alias created.");
593ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
594ac7ddfbfSEd Maste       return false;
595ac7ddfbfSEd Maste     }
596ac7ddfbfSEd Maste 
597ac7ddfbfSEd Maste     // Verify that the command is alias-able.
598435933ddSDimitry Andric     if (m_interpreter.CommandExists(alias_command)) {
599435933ddSDimitry Andric       result.AppendErrorWithFormat(
600435933ddSDimitry Andric           "'%s' is a permanent debugger command and cannot be redefined.\n",
601435933ddSDimitry Andric           args[0].c_str());
602ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
603ac7ddfbfSEd Maste       return false;
604ac7ddfbfSEd Maste     }
605ac7ddfbfSEd Maste 
606435933ddSDimitry Andric     // Get CommandObject that is being aliased. The command name is read from
607435933ddSDimitry Andric     // the front of raw_command_string. raw_command_string is returned with the
608435933ddSDimitry Andric     // name of the command object stripped off the front.
609435933ddSDimitry Andric     llvm::StringRef original_raw_command_string = raw_command_string;
610435933ddSDimitry Andric     CommandObject *cmd_obj =
611435933ddSDimitry Andric         m_interpreter.GetCommandObjectForCommand(raw_command_string);
612ac7ddfbfSEd Maste 
613435933ddSDimitry Andric     if (!cmd_obj) {
614435933ddSDimitry Andric       result.AppendErrorWithFormat("invalid command given to 'command alias'. "
615435933ddSDimitry Andric                                    "'%s' does not begin with a valid command."
616435933ddSDimitry Andric                                    "  No alias created.",
617435933ddSDimitry Andric                                    original_raw_command_string.str().c_str());
618ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
619ac7ddfbfSEd Maste       return false;
620435933ddSDimitry Andric     } else if (!cmd_obj->WantsRawCommandString()) {
621435933ddSDimitry Andric       // Note that args was initialized with the original command, and has not
6224ba319b5SDimitry Andric       // been updated to this point. Therefore can we pass it to the version of
6234ba319b5SDimitry Andric       // Execute that does not need/expect raw input in the alias.
624ac7ddfbfSEd Maste       return HandleAliasingNormalCommand(args, result);
625435933ddSDimitry Andric     } else {
626435933ddSDimitry Andric       return HandleAliasingRawCommand(alias_command, raw_command_string,
627435933ddSDimitry Andric                                       *cmd_obj, result);
628ac7ddfbfSEd Maste     }
629ac7ddfbfSEd Maste     return result.Succeeded();
630ac7ddfbfSEd Maste   }
631ac7ddfbfSEd Maste 
HandleAliasingRawCommand(llvm::StringRef alias_command,llvm::StringRef raw_command_string,CommandObject & cmd_obj,CommandReturnObject & result)632435933ddSDimitry Andric   bool HandleAliasingRawCommand(llvm::StringRef alias_command,
633435933ddSDimitry Andric                                 llvm::StringRef raw_command_string,
634435933ddSDimitry Andric                                 CommandObject &cmd_obj,
635435933ddSDimitry Andric                                 CommandReturnObject &result) {
636ac7ddfbfSEd Maste     // Verify & handle any options/arguments passed to the alias command
637ac7ddfbfSEd Maste 
638435933ddSDimitry Andric     OptionArgVectorSP option_arg_vector_sp =
639435933ddSDimitry Andric         OptionArgVectorSP(new OptionArgVector);
640ac7ddfbfSEd Maste 
641435933ddSDimitry Andric     if (CommandObjectSP cmd_obj_sp =
642435933ddSDimitry Andric             m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
643435933ddSDimitry Andric       if (m_interpreter.AliasExists(alias_command) ||
644435933ddSDimitry Andric           m_interpreter.UserCommandExists(alias_command)) {
645435933ddSDimitry Andric         result.AppendWarningWithFormat(
646435933ddSDimitry Andric             "Overwriting existing definition for '%s'.\n",
647435933ddSDimitry Andric             alias_command.str().c_str());
648ac7ddfbfSEd Maste       }
649435933ddSDimitry Andric       if (CommandAlias *alias = m_interpreter.AddAlias(
650435933ddSDimitry Andric               alias_command, cmd_obj_sp, raw_command_string)) {
6514bb0738eSEd Maste         if (m_command_options.m_help.OptionWasSet())
6524bb0738eSEd Maste           alias->SetHelp(m_command_options.m_help.GetCurrentValue());
6534bb0738eSEd Maste         if (m_command_options.m_long_help.OptionWasSet())
6544bb0738eSEd Maste           alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
655ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
656435933ddSDimitry Andric       } else {
657ac7ddfbfSEd Maste         result.AppendError("Unable to create requested alias.\n");
658ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
659ac7ddfbfSEd Maste       }
6604bb0738eSEd Maste 
661435933ddSDimitry Andric     } else {
6624bb0738eSEd Maste       result.AppendError("Unable to create requested alias.\n");
6634bb0738eSEd Maste       result.SetStatus(eReturnStatusFailed);
6644bb0738eSEd Maste     }
6654bb0738eSEd Maste 
666ac7ddfbfSEd Maste     return result.Succeeded();
667ac7ddfbfSEd Maste   }
668ac7ddfbfSEd Maste 
HandleAliasingNormalCommand(Args & args,CommandReturnObject & result)669435933ddSDimitry Andric   bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
670ac7ddfbfSEd Maste     size_t argc = args.GetArgumentCount();
671ac7ddfbfSEd Maste 
672435933ddSDimitry Andric     if (argc < 2) {
6734bb0738eSEd Maste       result.AppendError("'command alias' requires at least two arguments");
674ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
675ac7ddfbfSEd Maste       return false;
676ac7ddfbfSEd Maste     }
677ac7ddfbfSEd Maste 
678435933ddSDimitry Andric     // Save these in std::strings since we're going to shift them off.
679435933ddSDimitry Andric     const std::string alias_command(args[0].ref);
680435933ddSDimitry Andric     const std::string actual_command(args[1].ref);
681ac7ddfbfSEd Maste 
682ac7ddfbfSEd Maste     args.Shift(); // Shift the alias command word off the argument vector.
683ac7ddfbfSEd Maste     args.Shift(); // Shift the old command word off the argument vector.
684ac7ddfbfSEd Maste 
685435933ddSDimitry Andric     // Verify that the command is alias'able, and get the appropriate command
686435933ddSDimitry Andric     // object.
687ac7ddfbfSEd Maste 
688435933ddSDimitry Andric     if (m_interpreter.CommandExists(alias_command)) {
689435933ddSDimitry Andric       result.AppendErrorWithFormat(
690435933ddSDimitry Andric           "'%s' is a permanent debugger command and cannot be redefined.\n",
691ac7ddfbfSEd Maste           alias_command.c_str());
692ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
693435933ddSDimitry Andric       return false;
694ac7ddfbfSEd Maste     }
695435933ddSDimitry Andric 
696435933ddSDimitry Andric     CommandObjectSP command_obj_sp(
697435933ddSDimitry Andric         m_interpreter.GetCommandSPExact(actual_command, true));
698ac7ddfbfSEd Maste     CommandObjectSP subcommand_obj_sp;
699ac7ddfbfSEd Maste     bool use_subcommand = false;
700435933ddSDimitry Andric     if (!command_obj_sp) {
701435933ddSDimitry Andric       result.AppendErrorWithFormat("'%s' is not an existing command.\n",
702435933ddSDimitry Andric                                    actual_command.c_str());
703435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
704435933ddSDimitry Andric       return false;
705435933ddSDimitry Andric     }
706ac7ddfbfSEd Maste     CommandObject *cmd_obj = command_obj_sp.get();
7074bb0738eSEd Maste     CommandObject *sub_cmd_obj = nullptr;
708435933ddSDimitry Andric     OptionArgVectorSP option_arg_vector_sp =
709435933ddSDimitry Andric         OptionArgVectorSP(new OptionArgVector);
710ac7ddfbfSEd Maste 
711435933ddSDimitry Andric     while (cmd_obj->IsMultiwordObject() && !args.empty()) {
712435933ddSDimitry Andric       auto sub_command = args[0].ref;
713435933ddSDimitry Andric       assert(!sub_command.empty());
714435933ddSDimitry Andric       subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
715435933ddSDimitry Andric       if (!subcommand_obj_sp) {
716435933ddSDimitry Andric         result.AppendErrorWithFormat(
717435933ddSDimitry Andric             "'%s' is not a valid sub-command of '%s'.  "
718435933ddSDimitry Andric             "Unable to create alias.\n",
719435933ddSDimitry Andric             args[0].c_str(), actual_command.c_str());
720435933ddSDimitry Andric         result.SetStatus(eReturnStatusFailed);
721435933ddSDimitry Andric         return false;
722435933ddSDimitry Andric       }
723435933ddSDimitry Andric 
724ac7ddfbfSEd Maste       sub_cmd_obj = subcommand_obj_sp.get();
725ac7ddfbfSEd Maste       use_subcommand = true;
726ac7ddfbfSEd Maste       args.Shift(); // Shift the sub_command word off the argument vector.
727ac7ddfbfSEd Maste       cmd_obj = sub_cmd_obj;
728ac7ddfbfSEd Maste     }
729ac7ddfbfSEd Maste 
730ac7ddfbfSEd Maste     // Verify & handle any options/arguments passed to the alias command
731ac7ddfbfSEd Maste 
7324bb0738eSEd Maste     std::string args_string;
7334bb0738eSEd Maste 
734435933ddSDimitry Andric     if (!args.empty()) {
735435933ddSDimitry Andric       CommandObjectSP tmp_sp =
736435933ddSDimitry Andric           m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
737ac7ddfbfSEd Maste       if (use_subcommand)
738435933ddSDimitry Andric         tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
739435933ddSDimitry Andric                                                  false);
740ac7ddfbfSEd Maste 
741ac7ddfbfSEd Maste       args.GetCommandString(args_string);
7424bb0738eSEd Maste     }
743ac7ddfbfSEd Maste 
744435933ddSDimitry Andric     if (m_interpreter.AliasExists(alias_command) ||
745435933ddSDimitry Andric         m_interpreter.UserCommandExists(alias_command)) {
746435933ddSDimitry Andric       result.AppendWarningWithFormat(
747435933ddSDimitry Andric           "Overwriting existing definition for '%s'.\n", alias_command.c_str());
7484bb0738eSEd Maste     }
7494bb0738eSEd Maste 
750435933ddSDimitry Andric     if (CommandAlias *alias = m_interpreter.AddAlias(
751435933ddSDimitry Andric             alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
752435933ddSDimitry Andric             args_string)) {
7534bb0738eSEd Maste       if (m_command_options.m_help.OptionWasSet())
7544bb0738eSEd Maste         alias->SetHelp(m_command_options.m_help.GetCurrentValue());
7554bb0738eSEd Maste       if (m_command_options.m_long_help.OptionWasSet())
7564bb0738eSEd Maste         alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
7574bb0738eSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
758435933ddSDimitry Andric     } else {
759ac7ddfbfSEd Maste       result.AppendError("Unable to create requested alias.\n");
760ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
761ac7ddfbfSEd Maste       return false;
762ac7ddfbfSEd Maste     }
763ac7ddfbfSEd Maste 
764ac7ddfbfSEd Maste     return result.Succeeded();
765ac7ddfbfSEd Maste   }
7664bb0738eSEd Maste };
767ac7ddfbfSEd Maste 
768ac7ddfbfSEd Maste #pragma mark CommandObjectCommandsUnalias
769ac7ddfbfSEd Maste //-------------------------------------------------------------------------
770ac7ddfbfSEd Maste // CommandObjectCommandsUnalias
771ac7ddfbfSEd Maste //-------------------------------------------------------------------------
772ac7ddfbfSEd Maste 
773435933ddSDimitry Andric class CommandObjectCommandsUnalias : public CommandObjectParsed {
774ac7ddfbfSEd Maste public:
CommandObjectCommandsUnalias(CommandInterpreter & interpreter)7754bb0738eSEd Maste   CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
776435933ddSDimitry Andric       : CommandObjectParsed(
777435933ddSDimitry Andric             interpreter, "command unalias",
778435933ddSDimitry Andric             "Delete one or more custom commands defined by 'command alias'.",
779435933ddSDimitry Andric             nullptr) {
780ac7ddfbfSEd Maste     CommandArgumentEntry arg;
781ac7ddfbfSEd Maste     CommandArgumentData alias_arg;
782ac7ddfbfSEd Maste 
783ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
784ac7ddfbfSEd Maste     alias_arg.arg_type = eArgTypeAliasName;
785ac7ddfbfSEd Maste     alias_arg.arg_repetition = eArgRepeatPlain;
786ac7ddfbfSEd Maste 
787435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
788435933ddSDimitry Andric     // argument entry.
789ac7ddfbfSEd Maste     arg.push_back(alias_arg);
790ac7ddfbfSEd Maste 
791ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
792ac7ddfbfSEd Maste     m_arguments.push_back(arg);
793ac7ddfbfSEd Maste   }
794ac7ddfbfSEd Maste 
7954bb0738eSEd Maste   ~CommandObjectCommandsUnalias() override = default;
796ac7ddfbfSEd Maste 
797ac7ddfbfSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)798435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
799ac7ddfbfSEd Maste     CommandObject::CommandMap::iterator pos;
800ac7ddfbfSEd Maste     CommandObject *cmd_obj;
801ac7ddfbfSEd Maste 
802435933ddSDimitry Andric     if (args.empty()) {
803ac7ddfbfSEd Maste       result.AppendError("must call 'unalias' with a valid alias");
804ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
805435933ddSDimitry Andric       return false;
806ac7ddfbfSEd Maste     }
807ac7ddfbfSEd Maste 
808435933ddSDimitry Andric     auto command_name = args[0].ref;
809435933ddSDimitry Andric     cmd_obj = m_interpreter.GetCommandObject(command_name);
810435933ddSDimitry Andric     if (!cmd_obj) {
811435933ddSDimitry Andric       result.AppendErrorWithFormat(
812435933ddSDimitry Andric           "'%s' is not a known command.\nTry 'help' to see a "
813435933ddSDimitry Andric           "current list of commands.\n",
814435933ddSDimitry Andric           args[0].c_str());
815435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
816435933ddSDimitry Andric       return false;
817435933ddSDimitry Andric     }
818435933ddSDimitry Andric 
819435933ddSDimitry Andric     if (m_interpreter.CommandExists(command_name)) {
820435933ddSDimitry Andric       if (cmd_obj->IsRemovable()) {
821435933ddSDimitry Andric         result.AppendErrorWithFormat(
822435933ddSDimitry Andric             "'%s' is not an alias, it is a debugger command which can be "
823435933ddSDimitry Andric             "removed using the 'command delete' command.\n",
824435933ddSDimitry Andric             args[0].c_str());
825435933ddSDimitry Andric       } else {
826435933ddSDimitry Andric         result.AppendErrorWithFormat(
827435933ddSDimitry Andric             "'%s' is a permanent debugger command and cannot be removed.\n",
828435933ddSDimitry Andric             args[0].c_str());
829435933ddSDimitry Andric       }
830435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
831435933ddSDimitry Andric       return false;
832435933ddSDimitry Andric     }
833435933ddSDimitry Andric 
834435933ddSDimitry Andric     if (!m_interpreter.RemoveAlias(command_name)) {
835435933ddSDimitry Andric       if (m_interpreter.AliasExists(command_name))
836435933ddSDimitry Andric         result.AppendErrorWithFormat(
837435933ddSDimitry Andric             "Error occurred while attempting to unalias '%s'.\n",
838435933ddSDimitry Andric             args[0].c_str());
839435933ddSDimitry Andric       else
840435933ddSDimitry Andric         result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
841435933ddSDimitry Andric                                      args[0].c_str());
842435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
843435933ddSDimitry Andric       return false;
844435933ddSDimitry Andric     }
845435933ddSDimitry Andric 
846435933ddSDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishNoResult);
847ac7ddfbfSEd Maste     return result.Succeeded();
848ac7ddfbfSEd Maste   }
849ac7ddfbfSEd Maste };
850ac7ddfbfSEd Maste 
8517aa51b79SEd Maste #pragma mark CommandObjectCommandsDelete
8527aa51b79SEd Maste //-------------------------------------------------------------------------
8537aa51b79SEd Maste // CommandObjectCommandsDelete
8547aa51b79SEd Maste //-------------------------------------------------------------------------
8557aa51b79SEd Maste 
856435933ddSDimitry Andric class CommandObjectCommandsDelete : public CommandObjectParsed {
8577aa51b79SEd Maste public:
CommandObjectCommandsDelete(CommandInterpreter & interpreter)8584bb0738eSEd Maste   CommandObjectCommandsDelete(CommandInterpreter &interpreter)
859435933ddSDimitry Andric       : CommandObjectParsed(
860435933ddSDimitry Andric             interpreter, "command delete",
861435933ddSDimitry Andric             "Delete one or more custom commands defined by 'command regex'.",
862435933ddSDimitry Andric             nullptr) {
8637aa51b79SEd Maste     CommandArgumentEntry arg;
8647aa51b79SEd Maste     CommandArgumentData alias_arg;
8657aa51b79SEd Maste 
8667aa51b79SEd Maste     // Define the first (and only) variant of this arg.
8677aa51b79SEd Maste     alias_arg.arg_type = eArgTypeCommandName;
8687aa51b79SEd Maste     alias_arg.arg_repetition = eArgRepeatPlain;
8697aa51b79SEd Maste 
870435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
871435933ddSDimitry Andric     // argument entry.
8727aa51b79SEd Maste     arg.push_back(alias_arg);
8737aa51b79SEd Maste 
8747aa51b79SEd Maste     // Push the data for the first argument into the m_arguments vector.
8757aa51b79SEd Maste     m_arguments.push_back(arg);
8767aa51b79SEd Maste   }
8777aa51b79SEd Maste 
8784bb0738eSEd Maste   ~CommandObjectCommandsDelete() override = default;
8797aa51b79SEd Maste 
8807aa51b79SEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)881435933ddSDimitry Andric   bool DoExecute(Args &args, CommandReturnObject &result) override {
8827aa51b79SEd Maste     CommandObject::CommandMap::iterator pos;
8837aa51b79SEd Maste 
884435933ddSDimitry Andric     if (args.empty()) {
885435933ddSDimitry Andric       result.AppendErrorWithFormat("must call '%s' with one or more valid user "
886435933ddSDimitry Andric                                    "defined regular expression command names",
887435933ddSDimitry Andric                                    GetCommandName().str().c_str());
8887aa51b79SEd Maste       result.SetStatus(eReturnStatusFailed);
8897aa51b79SEd Maste     }
890435933ddSDimitry Andric 
891435933ddSDimitry Andric     auto command_name = args[0].ref;
892435933ddSDimitry Andric     if (!m_interpreter.CommandExists(command_name)) {
8934bb0738eSEd Maste       StreamString error_msg_stream;
8944bb0738eSEd Maste       const bool generate_apropos = true;
8954bb0738eSEd Maste       const bool generate_type_lookup = false;
896435933ddSDimitry Andric       CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
897435933ddSDimitry Andric           &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
898435933ddSDimitry Andric           generate_apropos, generate_type_lookup);
899435933ddSDimitry Andric       result.AppendError(error_msg_stream.GetString());
9007aa51b79SEd Maste       result.SetStatus(eReturnStatusFailed);
901435933ddSDimitry Andric       return false;
9027aa51b79SEd Maste     }
9037aa51b79SEd Maste 
904435933ddSDimitry Andric     if (!m_interpreter.RemoveCommand(command_name)) {
905435933ddSDimitry Andric       result.AppendErrorWithFormat(
906435933ddSDimitry Andric           "'%s' is a permanent debugger command and cannot be removed.\n",
907435933ddSDimitry Andric           args[0].c_str());
908435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
909435933ddSDimitry Andric       return false;
910435933ddSDimitry Andric     }
911435933ddSDimitry Andric 
912435933ddSDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishNoResult);
913435933ddSDimitry Andric     return true;
9147aa51b79SEd Maste   }
9157aa51b79SEd Maste };
9167aa51b79SEd Maste 
917ac7ddfbfSEd Maste //-------------------------------------------------------------------------
918ac7ddfbfSEd Maste // CommandObjectCommandsAddRegex
919ac7ddfbfSEd Maste //-------------------------------------------------------------------------
920435933ddSDimitry Andric 
921*b5893f02SDimitry Andric static constexpr OptionDefinition g_regex_options[] = {
922435933ddSDimitry Andric     // clang-format off
923*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." },
924*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
925435933ddSDimitry Andric     // clang-format on
926435933ddSDimitry Andric };
927435933ddSDimitry Andric 
928ac7ddfbfSEd Maste #pragma mark CommandObjectCommandsAddRegex
929ac7ddfbfSEd Maste 
930435933ddSDimitry Andric class CommandObjectCommandsAddRegex : public CommandObjectParsed,
931435933ddSDimitry Andric                                       public IOHandlerDelegateMultiline {
932ac7ddfbfSEd Maste public:
CommandObjectCommandsAddRegex(CommandInterpreter & interpreter)9334bb0738eSEd Maste   CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
934435933ddSDimitry Andric       : CommandObjectParsed(
935435933ddSDimitry Andric             interpreter, "command regex", "Define a custom command in terms of "
936435933ddSDimitry Andric                                           "existing commands by matching "
937435933ddSDimitry Andric                                           "regular expressions.",
938ac7ddfbfSEd Maste             "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
939435933ddSDimitry Andric         IOHandlerDelegateMultiline("",
940435933ddSDimitry Andric                                    IOHandlerDelegate::Completion::LLDBCommand),
941435933ddSDimitry Andric         m_options() {
942435933ddSDimitry Andric     SetHelpLong(
943435933ddSDimitry Andric         R"(
944435933ddSDimitry Andric )"
945435933ddSDimitry Andric         "This command allows the user to create powerful regular expression commands \
946b91a7dfcSDimitry Andric with substitutions. The regular expressions and substitutions are specified \
947435933ddSDimitry Andric using the regular expression substitution format of:"
948435933ddSDimitry Andric         R"(
949b91a7dfcSDimitry Andric 
950b91a7dfcSDimitry Andric     s/<regex>/<subst>/
951b91a7dfcSDimitry Andric 
952435933ddSDimitry Andric )"
953435933ddSDimitry Andric         "<regex> is a regular expression that can use parenthesis to capture regular \
954b91a7dfcSDimitry Andric expression input and substitute the captured matches in the output using %1 \
955435933ddSDimitry Andric for the first match, %2 for the second, and so on."
956435933ddSDimitry Andric         R"(
957b91a7dfcSDimitry Andric 
958435933ddSDimitry Andric )"
959435933ddSDimitry Andric         "The regular expressions can all be specified on the command line if more than \
960b91a7dfcSDimitry Andric one argument is provided. If just the command name is provided on the command \
961b91a7dfcSDimitry Andric line, then the regular expressions and substitutions can be entered on separate \
962435933ddSDimitry Andric lines, followed by an empty line to terminate the command definition."
963435933ddSDimitry Andric         R"(
964b91a7dfcSDimitry Andric 
965b91a7dfcSDimitry Andric EXAMPLES
966b91a7dfcSDimitry Andric 
967435933ddSDimitry Andric )"
968435933ddSDimitry Andric         "The following example will define a regular expression command named 'f' that \
969b91a7dfcSDimitry Andric will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
970435933ddSDimitry Andric a number follows 'f':"
971435933ddSDimitry Andric         R"(
972b91a7dfcSDimitry Andric 
973435933ddSDimitry Andric     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
974ac7ddfbfSEd Maste   }
975ac7ddfbfSEd Maste 
9764bb0738eSEd Maste   ~CommandObjectCommandsAddRegex() override = default;
977ac7ddfbfSEd Maste 
978ac7ddfbfSEd Maste protected:
IOHandlerActivated(IOHandler & io_handler)979435933ddSDimitry Andric   void IOHandlerActivated(IOHandler &io_handler) override {
98012b93ac6SEd Maste     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
981435933ddSDimitry Andric     if (output_sp) {
982435933ddSDimitry Andric       output_sp->PutCString("Enter one of more sed substitution commands in "
983435933ddSDimitry Andric                             "the form: 's/<regex>/<subst>/'.\nTerminate the "
984435933ddSDimitry Andric                             "substitution list with an empty line.\n");
98512b93ac6SEd Maste       output_sp->Flush();
98612b93ac6SEd Maste     }
98712b93ac6SEd Maste   }
98812b93ac6SEd Maste 
IOHandlerInputComplete(IOHandler & io_handler,std::string & data)989435933ddSDimitry Andric   void IOHandlerInputComplete(IOHandler &io_handler,
990435933ddSDimitry Andric                               std::string &data) override {
99112b93ac6SEd Maste     io_handler.SetIsDone(true);
992435933ddSDimitry Andric     if (m_regex_cmd_ap) {
99312b93ac6SEd Maste       StringList lines;
994435933ddSDimitry Andric       if (lines.SplitIntoLines(data)) {
99512b93ac6SEd Maste         const size_t num_lines = lines.GetSize();
99612b93ac6SEd Maste         bool check_only = false;
997435933ddSDimitry Andric         for (size_t i = 0; i < num_lines; ++i) {
99812b93ac6SEd Maste           llvm::StringRef bytes_strref(lines[i]);
9995517e702SDimitry Andric           Status error = AppendRegexSubstitution(bytes_strref, check_only);
1000435933ddSDimitry Andric           if (error.Fail()) {
1001435933ddSDimitry Andric             if (!m_interpreter.GetDebugger()
1002435933ddSDimitry Andric                      .GetCommandInterpreter()
1003435933ddSDimitry Andric                      .GetBatchCommandMode()) {
1004435933ddSDimitry Andric               StreamSP out_stream =
1005435933ddSDimitry Andric                   m_interpreter.GetDebugger().GetAsyncOutputStream();
100612b93ac6SEd Maste               out_stream->Printf("error: %s\n", error.AsCString());
100712b93ac6SEd Maste             }
100812b93ac6SEd Maste           }
100912b93ac6SEd Maste         }
101012b93ac6SEd Maste       }
1011435933ddSDimitry Andric       if (m_regex_cmd_ap->HasRegexEntries()) {
101212b93ac6SEd Maste         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
101312b93ac6SEd Maste         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
101412b93ac6SEd Maste       }
101512b93ac6SEd Maste     }
101612b93ac6SEd Maste   }
101712b93ac6SEd Maste 
DoExecute(Args & command,CommandReturnObject & result)1018435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1019ac7ddfbfSEd Maste     const size_t argc = command.GetArgumentCount();
1020435933ddSDimitry Andric     if (argc == 0) {
1021435933ddSDimitry Andric       result.AppendError("usage: 'command regex <command-name> "
1022435933ddSDimitry Andric                          "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1023ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1024435933ddSDimitry Andric       return false;
1025ac7ddfbfSEd Maste     }
1026ac7ddfbfSEd Maste 
10275517e702SDimitry Andric     Status error;
1028435933ddSDimitry Andric     auto name = command[0].ref;
1029435933ddSDimitry Andric     m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>(
1030435933ddSDimitry Andric         m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
1031435933ddSDimitry Andric         true);
1032435933ddSDimitry Andric 
1033435933ddSDimitry Andric     if (argc == 1) {
103412b93ac6SEd Maste       Debugger &debugger = m_interpreter.GetDebugger();
10357aa51b79SEd Maste       bool color_prompt = debugger.GetUseColor();
103612b93ac6SEd Maste       const bool multiple_lines = true; // Get multiple lines
1037435933ddSDimitry Andric       IOHandlerSP io_handler_sp(new IOHandlerEditline(
1038435933ddSDimitry Andric           debugger, IOHandler::Type::Other,
10390127ef0fSEd Maste           "lldb-regex",          // Name of input reader for history
1040435933ddSDimitry Andric           llvm::StringRef("> "), // Prompt
1041435933ddSDimitry Andric           llvm::StringRef(),     // Continuation prompt
1042435933ddSDimitry Andric           multiple_lines, color_prompt,
10430127ef0fSEd Maste           0, // Don't show line numbers
104412b93ac6SEd Maste           *this));
104512b93ac6SEd Maste 
1046435933ddSDimitry Andric       if (io_handler_sp) {
104712b93ac6SEd Maste         debugger.PushIOHandler(io_handler_sp);
1048ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1049ac7ddfbfSEd Maste       }
1050435933ddSDimitry Andric     } else {
1051435933ddSDimitry Andric       for (auto &entry : command.entries().drop_front()) {
105212b93ac6SEd Maste         bool check_only = false;
1053435933ddSDimitry Andric         error = AppendRegexSubstitution(entry.ref, check_only);
1054ac7ddfbfSEd Maste         if (error.Fail())
1055ac7ddfbfSEd Maste           break;
1056ac7ddfbfSEd Maste       }
1057ac7ddfbfSEd Maste 
1058435933ddSDimitry Andric       if (error.Success()) {
1059ac7ddfbfSEd Maste         AddRegexCommandToInterpreter();
1060ac7ddfbfSEd Maste       }
1061ac7ddfbfSEd Maste     }
1062435933ddSDimitry Andric     if (error.Fail()) {
1063ac7ddfbfSEd Maste       result.AppendError(error.AsCString());
1064ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1065ac7ddfbfSEd Maste     }
1066ac7ddfbfSEd Maste 
1067ac7ddfbfSEd Maste     return result.Succeeded();
1068ac7ddfbfSEd Maste   }
1069ac7ddfbfSEd Maste 
AppendRegexSubstitution(const llvm::StringRef & regex_sed,bool check_only)10705517e702SDimitry Andric   Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1071435933ddSDimitry Andric                                  bool check_only) {
10725517e702SDimitry Andric     Status error;
1073ac7ddfbfSEd Maste 
1074435933ddSDimitry Andric     if (!m_regex_cmd_ap) {
1075435933ddSDimitry Andric       error.SetErrorStringWithFormat(
1076435933ddSDimitry Andric           "invalid regular expression command object for: '%.*s'",
1077435933ddSDimitry Andric           (int)regex_sed.size(), regex_sed.data());
1078ac7ddfbfSEd Maste       return error;
1079ac7ddfbfSEd Maste     }
1080ac7ddfbfSEd Maste 
1081ac7ddfbfSEd Maste     size_t regex_sed_size = regex_sed.size();
1082ac7ddfbfSEd Maste 
1083435933ddSDimitry Andric     if (regex_sed_size <= 1) {
1084435933ddSDimitry Andric       error.SetErrorStringWithFormat(
1085435933ddSDimitry Andric           "regular expression substitution string is too short: '%.*s'",
1086435933ddSDimitry Andric           (int)regex_sed.size(), regex_sed.data());
1087ac7ddfbfSEd Maste       return error;
1088ac7ddfbfSEd Maste     }
1089ac7ddfbfSEd Maste 
1090435933ddSDimitry Andric     if (regex_sed[0] != 's') {
1091435933ddSDimitry Andric       error.SetErrorStringWithFormat("regular expression substitution string "
1092435933ddSDimitry Andric                                      "doesn't start with 's': '%.*s'",
1093435933ddSDimitry Andric                                      (int)regex_sed.size(), regex_sed.data());
1094ac7ddfbfSEd Maste       return error;
1095ac7ddfbfSEd Maste     }
1096ac7ddfbfSEd Maste     const size_t first_separator_char_pos = 1;
10974ba319b5SDimitry Andric     // use the char that follows 's' as the regex separator character so we can
10984ba319b5SDimitry Andric     // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1099ac7ddfbfSEd Maste     const char separator_char = regex_sed[first_separator_char_pos];
1100435933ddSDimitry Andric     const size_t second_separator_char_pos =
1101435933ddSDimitry Andric         regex_sed.find(separator_char, first_separator_char_pos + 1);
1102ac7ddfbfSEd Maste 
1103435933ddSDimitry Andric     if (second_separator_char_pos == std::string::npos) {
1104435933ddSDimitry Andric       error.SetErrorStringWithFormat(
1105435933ddSDimitry Andric           "missing second '%c' separator char after '%.*s' in '%.*s'",
1106ac7ddfbfSEd Maste           separator_char,
1107ac7ddfbfSEd Maste           (int)(regex_sed.size() - first_separator_char_pos - 1),
11087aa51b79SEd Maste           regex_sed.data() + (first_separator_char_pos + 1),
1109435933ddSDimitry Andric           (int)regex_sed.size(), regex_sed.data());
1110ac7ddfbfSEd Maste       return error;
1111ac7ddfbfSEd Maste     }
1112ac7ddfbfSEd Maste 
1113435933ddSDimitry Andric     const size_t third_separator_char_pos =
1114435933ddSDimitry Andric         regex_sed.find(separator_char, second_separator_char_pos + 1);
1115ac7ddfbfSEd Maste 
1116435933ddSDimitry Andric     if (third_separator_char_pos == std::string::npos) {
1117435933ddSDimitry Andric       error.SetErrorStringWithFormat(
1118435933ddSDimitry Andric           "missing third '%c' separator char after '%.*s' in '%.*s'",
1119ac7ddfbfSEd Maste           separator_char,
1120ac7ddfbfSEd Maste           (int)(regex_sed.size() - second_separator_char_pos - 1),
11217aa51b79SEd Maste           regex_sed.data() + (second_separator_char_pos + 1),
1122435933ddSDimitry Andric           (int)regex_sed.size(), regex_sed.data());
1123ac7ddfbfSEd Maste       return error;
1124ac7ddfbfSEd Maste     }
1125ac7ddfbfSEd Maste 
1126435933ddSDimitry Andric     if (third_separator_char_pos != regex_sed_size - 1) {
11274ba319b5SDimitry Andric       // Make sure that everything that follows the last regex separator char
1128435933ddSDimitry Andric       if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1129435933ddSDimitry Andric                                       third_separator_char_pos + 1) !=
1130435933ddSDimitry Andric           std::string::npos) {
1131435933ddSDimitry Andric         error.SetErrorStringWithFormat(
1132435933ddSDimitry Andric             "extra data found after the '%.*s' regular expression substitution "
1133435933ddSDimitry Andric             "string: '%.*s'",
1134435933ddSDimitry Andric             (int)third_separator_char_pos + 1, regex_sed.data(),
1135ac7ddfbfSEd Maste             (int)(regex_sed.size() - third_separator_char_pos - 1),
1136ac7ddfbfSEd Maste             regex_sed.data() + (third_separator_char_pos + 1));
1137ac7ddfbfSEd Maste         return error;
1138ac7ddfbfSEd Maste       }
1139435933ddSDimitry Andric     } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1140435933ddSDimitry Andric       error.SetErrorStringWithFormat(
1141435933ddSDimitry Andric           "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1142435933ddSDimitry Andric           separator_char, separator_char, separator_char, (int)regex_sed.size(),
1143ac7ddfbfSEd Maste           regex_sed.data());
1144ac7ddfbfSEd Maste       return error;
1145435933ddSDimitry Andric     } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1146435933ddSDimitry Andric       error.SetErrorStringWithFormat(
1147435933ddSDimitry Andric           "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1148435933ddSDimitry Andric           separator_char, separator_char, separator_char, (int)regex_sed.size(),
1149ac7ddfbfSEd Maste           regex_sed.data());
1150ac7ddfbfSEd Maste       return error;
1151ac7ddfbfSEd Maste     }
115212b93ac6SEd Maste 
1153435933ddSDimitry Andric     if (!check_only) {
1154435933ddSDimitry Andric       std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1155435933ddSDimitry Andric                                          second_separator_char_pos -
1156435933ddSDimitry Andric                                              first_separator_char_pos - 1));
1157435933ddSDimitry Andric       std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1158435933ddSDimitry Andric                                          third_separator_char_pos -
1159435933ddSDimitry Andric                                              second_separator_char_pos - 1));
1160435933ddSDimitry Andric       m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
116112b93ac6SEd Maste     }
1162ac7ddfbfSEd Maste     return error;
1163ac7ddfbfSEd Maste   }
1164ac7ddfbfSEd Maste 
AddRegexCommandToInterpreter()1165435933ddSDimitry Andric   void AddRegexCommandToInterpreter() {
1166435933ddSDimitry Andric     if (m_regex_cmd_ap) {
1167435933ddSDimitry Andric       if (m_regex_cmd_ap->HasRegexEntries()) {
1168ac7ddfbfSEd Maste         CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1169ac7ddfbfSEd Maste         m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1170ac7ddfbfSEd Maste       }
1171ac7ddfbfSEd Maste     }
1172ac7ddfbfSEd Maste   }
1173ac7ddfbfSEd Maste 
1174ac7ddfbfSEd Maste private:
1175ac7ddfbfSEd Maste   std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1176ac7ddfbfSEd Maste 
1177435933ddSDimitry Andric   class CommandOptions : public Options {
1178ac7ddfbfSEd Maste   public:
CommandOptions()1179435933ddSDimitry Andric     CommandOptions() : Options() {}
1180ac7ddfbfSEd Maste 
11814bb0738eSEd Maste     ~CommandOptions() override = default;
1182ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)11835517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1184435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
11855517e702SDimitry Andric       Status error;
1186ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1187ac7ddfbfSEd Maste 
1188435933ddSDimitry Andric       switch (short_option) {
1189ac7ddfbfSEd Maste       case 'h':
1190ac7ddfbfSEd Maste         m_help.assign(option_arg);
1191ac7ddfbfSEd Maste         break;
1192ac7ddfbfSEd Maste       case 's':
1193ac7ddfbfSEd Maste         m_syntax.assign(option_arg);
1194ac7ddfbfSEd Maste         break;
1195ac7ddfbfSEd Maste       default:
1196435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
1197435933ddSDimitry Andric                                        short_option);
1198ac7ddfbfSEd Maste         break;
1199ac7ddfbfSEd Maste       }
1200ac7ddfbfSEd Maste 
1201ac7ddfbfSEd Maste       return error;
1202ac7ddfbfSEd Maste     }
1203ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)1204435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1205ac7ddfbfSEd Maste       m_help.clear();
1206ac7ddfbfSEd Maste       m_syntax.clear();
1207ac7ddfbfSEd Maste     }
1208ac7ddfbfSEd Maste 
GetDefinitions()1209435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1210435933ddSDimitry Andric       return llvm::makeArrayRef(g_regex_options);
1211ac7ddfbfSEd Maste     }
1212ac7ddfbfSEd Maste 
1213435933ddSDimitry Andric     // TODO: Convert these functions to return StringRefs.
GetHelp()1214435933ddSDimitry Andric     const char *GetHelp() {
12154bb0738eSEd Maste       return (m_help.empty() ? nullptr : m_help.c_str());
1216ac7ddfbfSEd Maste     }
12174bb0738eSEd Maste 
GetSyntax()1218435933ddSDimitry Andric     const char *GetSyntax() {
12194bb0738eSEd Maste       return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1220ac7ddfbfSEd Maste     }
12214bb0738eSEd Maste 
1222ac7ddfbfSEd Maste   protected:
12234bb0738eSEd Maste     // Instance variables to hold the values for command options.
12244bb0738eSEd Maste 
1225ac7ddfbfSEd Maste     std::string m_help;
1226ac7ddfbfSEd Maste     std::string m_syntax;
1227ac7ddfbfSEd Maste   };
1228ac7ddfbfSEd Maste 
GetOptions()1229435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1230ac7ddfbfSEd Maste 
1231ac7ddfbfSEd Maste   CommandOptions m_options;
1232ac7ddfbfSEd Maste };
1233ac7ddfbfSEd Maste 
1234435933ddSDimitry Andric class CommandObjectPythonFunction : public CommandObjectRaw {
1235ac7ddfbfSEd Maste public:
CommandObjectPythonFunction(CommandInterpreter & interpreter,std::string name,std::string funct,std::string help,ScriptedCommandSynchronicity synch)1236435933ddSDimitry Andric   CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1237435933ddSDimitry Andric                               std::string funct, std::string help,
1238435933ddSDimitry Andric                               ScriptedCommandSynchronicity synch)
1239435933ddSDimitry Andric       : CommandObjectRaw(interpreter, name),
1240435933ddSDimitry Andric         m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
12417aa51b79SEd Maste     if (!help.empty())
1242435933ddSDimitry Andric       SetHelp(help);
1243435933ddSDimitry Andric     else {
12447aa51b79SEd Maste       StreamString stream;
12457aa51b79SEd Maste       stream.Printf("For more information run 'help %s'", name.c_str());
1246435933ddSDimitry Andric       SetHelp(stream.GetString());
12477aa51b79SEd Maste     }
1248ac7ddfbfSEd Maste   }
1249ac7ddfbfSEd Maste 
12504bb0738eSEd Maste   ~CommandObjectPythonFunction() override = default;
1251ac7ddfbfSEd Maste 
IsRemovable() const1252435933ddSDimitry Andric   bool IsRemovable() const override { return true; }
1253ac7ddfbfSEd Maste 
GetFunctionName()1254435933ddSDimitry Andric   const std::string &GetFunctionName() { return m_function_name; }
1255ac7ddfbfSEd Maste 
GetSynchronicity()1256435933ddSDimitry Andric   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1257ac7ddfbfSEd Maste 
GetHelpLong()1258435933ddSDimitry Andric   llvm::StringRef GetHelpLong() override {
1259435933ddSDimitry Andric     if (m_fetched_help_long)
1260435933ddSDimitry Andric       return CommandObjectRaw::GetHelpLong();
1261435933ddSDimitry Andric 
1262ac7ddfbfSEd Maste     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1263435933ddSDimitry Andric     if (!scripter)
1264435933ddSDimitry Andric       return CommandObjectRaw::GetHelpLong();
1265435933ddSDimitry Andric 
1266ac7ddfbfSEd Maste     std::string docstring;
1267435933ddSDimitry Andric     m_fetched_help_long =
1268435933ddSDimitry Andric         scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1269ac7ddfbfSEd Maste     if (!docstring.empty())
1270435933ddSDimitry Andric       SetHelpLong(docstring);
1271ac7ddfbfSEd Maste     return CommandObjectRaw::GetHelpLong();
1272ac7ddfbfSEd Maste   }
1273ac7ddfbfSEd Maste 
1274ac7ddfbfSEd Maste protected:
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)12754ba319b5SDimitry Andric   bool DoExecute(llvm::StringRef raw_command_line,
1276435933ddSDimitry Andric                  CommandReturnObject &result) override {
1277ac7ddfbfSEd Maste     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1278ac7ddfbfSEd Maste 
12795517e702SDimitry Andric     Status error;
1280ac7ddfbfSEd Maste 
1281ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusInvalid);
1282ac7ddfbfSEd Maste 
1283435933ddSDimitry Andric     if (!scripter ||
1284435933ddSDimitry Andric         !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1285435933ddSDimitry Andric                                          raw_command_line, m_synchro, result,
1286435933ddSDimitry Andric                                          error, m_exe_ctx)) {
1287ac7ddfbfSEd Maste       result.AppendError(error.AsCString());
1288ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1289435933ddSDimitry Andric     } else {
1290ac7ddfbfSEd Maste       // Don't change the status if the command already set it...
1291435933ddSDimitry Andric       if (result.GetStatus() == eReturnStatusInvalid) {
1292435933ddSDimitry Andric         if (result.GetOutputData().empty())
1293ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1294ac7ddfbfSEd Maste         else
1295ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1296ac7ddfbfSEd Maste       }
1297ac7ddfbfSEd Maste     }
1298ac7ddfbfSEd Maste 
1299ac7ddfbfSEd Maste     return result.Succeeded();
1300ac7ddfbfSEd Maste   }
1301ac7ddfbfSEd Maste 
13024bb0738eSEd Maste private:
13034bb0738eSEd Maste   std::string m_function_name;
13044bb0738eSEd Maste   ScriptedCommandSynchronicity m_synchro;
13054bb0738eSEd Maste   bool m_fetched_help_long;
1306ac7ddfbfSEd Maste };
1307ac7ddfbfSEd Maste 
1308435933ddSDimitry Andric class CommandObjectScriptingObject : public CommandObjectRaw {
13091c3bbb01SEd Maste public:
CommandObjectScriptingObject(CommandInterpreter & interpreter,std::string name,StructuredData::GenericSP cmd_obj_sp,ScriptedCommandSynchronicity synch)13101c3bbb01SEd Maste   CommandObjectScriptingObject(CommandInterpreter &interpreter,
13111c3bbb01SEd Maste                                std::string name,
13121c3bbb01SEd Maste                                StructuredData::GenericSP cmd_obj_sp,
1313435933ddSDimitry Andric                                ScriptedCommandSynchronicity synch)
1314435933ddSDimitry Andric       : CommandObjectRaw(interpreter, name),
1315435933ddSDimitry Andric         m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1316435933ddSDimitry Andric         m_fetched_help_long(false) {
13171c3bbb01SEd Maste     StreamString stream;
13181c3bbb01SEd Maste     stream.Printf("For more information run 'help %s'", name.c_str());
1319435933ddSDimitry Andric     SetHelp(stream.GetString());
13201c3bbb01SEd Maste     if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
13211c3bbb01SEd Maste       GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
13221c3bbb01SEd Maste   }
13231c3bbb01SEd Maste 
13244bb0738eSEd Maste   ~CommandObjectScriptingObject() override = default;
13251c3bbb01SEd Maste 
IsRemovable() const1326435933ddSDimitry Andric   bool IsRemovable() const override { return true; }
13271c3bbb01SEd Maste 
GetImplementingObject()1328435933ddSDimitry Andric   StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
13291c3bbb01SEd Maste 
GetSynchronicity()1330435933ddSDimitry Andric   ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
13311c3bbb01SEd Maste 
GetHelp()1332435933ddSDimitry Andric   llvm::StringRef GetHelp() override {
1333435933ddSDimitry Andric     if (m_fetched_help_short)
1334435933ddSDimitry Andric       return CommandObjectRaw::GetHelp();
13351c3bbb01SEd Maste     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1336435933ddSDimitry Andric     if (!scripter)
1337435933ddSDimitry Andric       return CommandObjectRaw::GetHelp();
13381c3bbb01SEd Maste     std::string docstring;
1339435933ddSDimitry Andric     m_fetched_help_short =
1340435933ddSDimitry Andric         scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
13411c3bbb01SEd Maste     if (!docstring.empty())
1342435933ddSDimitry Andric       SetHelp(docstring);
1343435933ddSDimitry Andric 
13441c3bbb01SEd Maste     return CommandObjectRaw::GetHelp();
13451c3bbb01SEd Maste   }
13461c3bbb01SEd Maste 
GetHelpLong()1347435933ddSDimitry Andric   llvm::StringRef GetHelpLong() override {
1348435933ddSDimitry Andric     if (m_fetched_help_long)
1349435933ddSDimitry Andric       return CommandObjectRaw::GetHelpLong();
1350435933ddSDimitry Andric 
13511c3bbb01SEd Maste     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1352435933ddSDimitry Andric     if (!scripter)
1353435933ddSDimitry Andric       return CommandObjectRaw::GetHelpLong();
1354435933ddSDimitry Andric 
13551c3bbb01SEd Maste     std::string docstring;
1356435933ddSDimitry Andric     m_fetched_help_long =
1357435933ddSDimitry Andric         scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
13581c3bbb01SEd Maste     if (!docstring.empty())
1359435933ddSDimitry Andric       SetHelpLong(docstring);
13601c3bbb01SEd Maste     return CommandObjectRaw::GetHelpLong();
13611c3bbb01SEd Maste   }
13621c3bbb01SEd Maste 
13631c3bbb01SEd Maste protected:
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)13644ba319b5SDimitry Andric   bool DoExecute(llvm::StringRef raw_command_line,
1365435933ddSDimitry Andric                  CommandReturnObject &result) override {
13661c3bbb01SEd Maste     ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
13671c3bbb01SEd Maste 
13685517e702SDimitry Andric     Status error;
13691c3bbb01SEd Maste 
13701c3bbb01SEd Maste     result.SetStatus(eReturnStatusInvalid);
13711c3bbb01SEd Maste 
1372435933ddSDimitry Andric     if (!scripter ||
1373435933ddSDimitry Andric         !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1374435933ddSDimitry Andric                                          m_synchro, result, error, m_exe_ctx)) {
13751c3bbb01SEd Maste       result.AppendError(error.AsCString());
13761c3bbb01SEd Maste       result.SetStatus(eReturnStatusFailed);
1377435933ddSDimitry Andric     } else {
13781c3bbb01SEd Maste       // Don't change the status if the command already set it...
1379435933ddSDimitry Andric       if (result.GetStatus() == eReturnStatusInvalid) {
1380435933ddSDimitry Andric         if (result.GetOutputData().empty())
13811c3bbb01SEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
13821c3bbb01SEd Maste         else
13831c3bbb01SEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
13841c3bbb01SEd Maste       }
13851c3bbb01SEd Maste     }
13861c3bbb01SEd Maste 
13871c3bbb01SEd Maste     return result.Succeeded();
13881c3bbb01SEd Maste   }
13891c3bbb01SEd Maste 
13904bb0738eSEd Maste private:
13914bb0738eSEd Maste   StructuredData::GenericSP m_cmd_obj_sp;
13924bb0738eSEd Maste   ScriptedCommandSynchronicity m_synchro;
13934bb0738eSEd Maste   bool m_fetched_help_short : 1;
13944bb0738eSEd Maste   bool m_fetched_help_long : 1;
13951c3bbb01SEd Maste };
13961c3bbb01SEd Maste 
1397ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1398ac7ddfbfSEd Maste // CommandObjectCommandsScriptImport
1399ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1400ac7ddfbfSEd Maste 
1401*b5893f02SDimitry Andric static constexpr OptionDefinition g_script_import_options[] = {
1402435933ddSDimitry Andric     // clang-format off
1403*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, 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." },
1404435933ddSDimitry Andric     // clang-format on
1405435933ddSDimitry Andric };
1406435933ddSDimitry Andric 
1407435933ddSDimitry Andric class CommandObjectCommandsScriptImport : public CommandObjectParsed {
1408ac7ddfbfSEd Maste public:
CommandObjectCommandsScriptImport(CommandInterpreter & interpreter)1409435933ddSDimitry Andric   CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1410435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "command script import",
1411435933ddSDimitry Andric                             "Import a scripting module in LLDB.", nullptr),
1412435933ddSDimitry Andric         m_options() {
1413ac7ddfbfSEd Maste     CommandArgumentEntry arg1;
1414ac7ddfbfSEd Maste     CommandArgumentData cmd_arg;
1415ac7ddfbfSEd Maste 
1416ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1417ac7ddfbfSEd Maste     cmd_arg.arg_type = eArgTypeFilename;
14181c3bbb01SEd Maste     cmd_arg.arg_repetition = eArgRepeatPlus;
1419ac7ddfbfSEd Maste 
1420435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1421435933ddSDimitry Andric     // argument entry.
1422ac7ddfbfSEd Maste     arg1.push_back(cmd_arg);
1423ac7ddfbfSEd Maste 
1424ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1425ac7ddfbfSEd Maste     m_arguments.push_back(arg1);
1426ac7ddfbfSEd Maste   }
1427ac7ddfbfSEd Maste 
14284bb0738eSEd Maste   ~CommandObjectCommandsScriptImport() override = default;
1429ac7ddfbfSEd Maste 
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)14304ba319b5SDimitry Andric   int HandleArgumentCompletion(
14314ba319b5SDimitry Andric       CompletionRequest &request,
14324ba319b5SDimitry Andric       OptionElementVector &opt_element_vector) override {
1433435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
1434435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
14354ba319b5SDimitry Andric         request, nullptr);
14364ba319b5SDimitry Andric     return request.GetNumberOfMatches();
1437ac7ddfbfSEd Maste   }
1438ac7ddfbfSEd Maste 
GetOptions()1439435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1440ac7ddfbfSEd Maste 
1441ac7ddfbfSEd Maste protected:
1442435933ddSDimitry Andric   class CommandOptions : public Options {
1443ac7ddfbfSEd Maste   public:
CommandOptions()1444435933ddSDimitry Andric     CommandOptions() : Options() {}
1445ac7ddfbfSEd Maste 
14464bb0738eSEd Maste     ~CommandOptions() override = default;
1447ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)14485517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1449435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
14505517e702SDimitry Andric       Status error;
1451ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1452ac7ddfbfSEd Maste 
1453435933ddSDimitry Andric       switch (short_option) {
1454ac7ddfbfSEd Maste       case 'r':
1455ac7ddfbfSEd Maste         m_allow_reload = true;
1456ac7ddfbfSEd Maste         break;
1457ac7ddfbfSEd Maste       default:
1458435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
1459435933ddSDimitry Andric                                        short_option);
1460ac7ddfbfSEd Maste         break;
1461ac7ddfbfSEd Maste       }
1462ac7ddfbfSEd Maste 
1463ac7ddfbfSEd Maste       return error;
1464ac7ddfbfSEd Maste     }
1465ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)1466435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1467ac7ddfbfSEd Maste       m_allow_reload = true;
1468ac7ddfbfSEd Maste     }
1469ac7ddfbfSEd Maste 
GetDefinitions()1470435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1471435933ddSDimitry Andric       return llvm::makeArrayRef(g_script_import_options);
1472ac7ddfbfSEd Maste     }
1473ac7ddfbfSEd Maste 
1474ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
1475ac7ddfbfSEd Maste 
1476ac7ddfbfSEd Maste     bool m_allow_reload;
1477ac7ddfbfSEd Maste   };
1478ac7ddfbfSEd Maste 
DoExecute(Args & command,CommandReturnObject & result)1479435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1480435933ddSDimitry Andric     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1481435933ddSDimitry Andric         lldb::eScriptLanguagePython) {
1482435933ddSDimitry Andric       result.AppendError("only scripting language supported for module "
1483435933ddSDimitry Andric                          "importing is currently Python");
1484ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1485ac7ddfbfSEd Maste       return false;
1486ac7ddfbfSEd Maste     }
1487ac7ddfbfSEd Maste 
1488435933ddSDimitry Andric     if (command.empty()) {
14891c3bbb01SEd Maste       result.AppendError("command script import needs one or more arguments");
1490ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1491ac7ddfbfSEd Maste       return false;
1492ac7ddfbfSEd Maste     }
1493ac7ddfbfSEd Maste 
1494435933ddSDimitry Andric     for (auto &entry : command.entries()) {
14955517e702SDimitry Andric       Status error;
1496ac7ddfbfSEd Maste 
1497ac7ddfbfSEd Maste       const bool init_session = true;
1498435933ddSDimitry Andric       // FIXME: this is necessary because CommandObject::CheckRequirements()
1499435933ddSDimitry Andric       // assumes that commands won't ever be recursively invoked, but it's
1500435933ddSDimitry Andric       // actually possible to craft a Python script that does other "command
15014ba319b5SDimitry Andric       // script imports" in __lldb_init_module the real fix is to have
15024ba319b5SDimitry Andric       // recursive commands possible with a CommandInvocation object separate
15034ba319b5SDimitry Andric       // from the CommandObject itself, so that recursive command invocations
15044ba319b5SDimitry Andric       // won't stomp on each other (wrt to execution contents, options, and
15054ba319b5SDimitry Andric       // more)
1506ac7ddfbfSEd Maste       m_exe_ctx.Clear();
1507435933ddSDimitry Andric       if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1508435933ddSDimitry Andric               entry.c_str(), m_options.m_allow_reload, init_session, error)) {
1509ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1510435933ddSDimitry Andric       } else {
1511435933ddSDimitry Andric         result.AppendErrorWithFormat("module importing failed: %s",
1512435933ddSDimitry Andric                                      error.AsCString());
1513ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1514ac7ddfbfSEd Maste       }
15151c3bbb01SEd Maste     }
1516ac7ddfbfSEd Maste 
1517ac7ddfbfSEd Maste     return result.Succeeded();
1518ac7ddfbfSEd Maste   }
1519ac7ddfbfSEd Maste 
1520ac7ddfbfSEd Maste   CommandOptions m_options;
1521ac7ddfbfSEd Maste };
1522ac7ddfbfSEd Maste 
1523ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1524ac7ddfbfSEd Maste // CommandObjectCommandsScriptAdd
1525ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1526*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_script_synchro_type[] = {
1527435933ddSDimitry Andric   {eScriptedCommandSynchronicitySynchronous, "synchronous",
1528435933ddSDimitry Andric    "Run synchronous"},
1529435933ddSDimitry Andric   {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1530435933ddSDimitry Andric    "Run asynchronous"},
1531435933ddSDimitry Andric   {eScriptedCommandSynchronicityCurrentValue, "current",
1532*b5893f02SDimitry Andric    "Do not alter current setting"} };
1533435933ddSDimitry Andric 
ScriptSynchroType()1534*b5893f02SDimitry Andric static constexpr OptionEnumValues ScriptSynchroType() {
1535*b5893f02SDimitry Andric   return OptionEnumValues(g_script_synchro_type);
1536*b5893f02SDimitry Andric }
1537*b5893f02SDimitry Andric 
1538*b5893f02SDimitry Andric static constexpr OptionDefinition g_script_add_options[] = {
1539435933ddSDimitry Andric     // clang-format off
1540*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,   false, "function",      'f', OptionParser::eRequiredArgument, nullptr, {},                  0, eArgTypePythonFunction,               "Name of the Python function to bind to this command name." },
1541*b5893f02SDimitry Andric   { LLDB_OPT_SET_2,   false, "class",         'c', OptionParser::eRequiredArgument, nullptr, {},                  0, eArgTypePythonClass,                  "Name of the Python class to bind to this command name." },
1542*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,   false, "help"  ,        'h', OptionParser::eRequiredArgument, nullptr, {},                  0, eArgTypeHelpText,                     "The help text to display for this command." },
1543*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, ScriptSynchroType(), 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." },
1544435933ddSDimitry Andric     // clang-format on
1545435933ddSDimitry Andric };
1546435933ddSDimitry Andric 
1547435933ddSDimitry Andric class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1548435933ddSDimitry Andric                                        public IOHandlerDelegateMultiline {
1549ac7ddfbfSEd Maste public:
CommandObjectCommandsScriptAdd(CommandInterpreter & interpreter)1550435933ddSDimitry Andric   CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1551435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "command script add",
1552ac7ddfbfSEd Maste                             "Add a scripted function as an LLDB command.",
15534bb0738eSEd Maste                             nullptr),
1554435933ddSDimitry Andric         IOHandlerDelegateMultiline("DONE"), m_options() {
1555ac7ddfbfSEd Maste     CommandArgumentEntry arg1;
1556ac7ddfbfSEd Maste     CommandArgumentData cmd_arg;
1557ac7ddfbfSEd Maste 
1558ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1559ac7ddfbfSEd Maste     cmd_arg.arg_type = eArgTypeCommandName;
1560ac7ddfbfSEd Maste     cmd_arg.arg_repetition = eArgRepeatPlain;
1561ac7ddfbfSEd Maste 
1562435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1563435933ddSDimitry Andric     // argument entry.
1564ac7ddfbfSEd Maste     arg1.push_back(cmd_arg);
1565ac7ddfbfSEd Maste 
1566ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1567ac7ddfbfSEd Maste     m_arguments.push_back(arg1);
1568ac7ddfbfSEd Maste   }
1569ac7ddfbfSEd Maste 
15704bb0738eSEd Maste   ~CommandObjectCommandsScriptAdd() override = default;
1571ac7ddfbfSEd Maste 
GetOptions()1572435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1573ac7ddfbfSEd Maste 
1574ac7ddfbfSEd Maste protected:
1575435933ddSDimitry Andric   class CommandOptions : public Options {
1576ac7ddfbfSEd Maste   public:
CommandOptions()1577435933ddSDimitry Andric     CommandOptions()
1578435933ddSDimitry Andric         : Options(), m_class_name(), m_funct_name(), m_short_help(),
1579435933ddSDimitry Andric           m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
1580ac7ddfbfSEd Maste 
15814bb0738eSEd Maste     ~CommandOptions() override = default;
1582ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)15835517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1584435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
15855517e702SDimitry Andric       Status error;
1586ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1587ac7ddfbfSEd Maste 
1588435933ddSDimitry Andric       switch (short_option) {
1589ac7ddfbfSEd Maste       case 'f':
1590435933ddSDimitry Andric         if (!option_arg.empty())
1591435933ddSDimitry Andric           m_funct_name = option_arg;
15927aa51b79SEd Maste         break;
15931c3bbb01SEd Maste       case 'c':
1594435933ddSDimitry Andric         if (!option_arg.empty())
1595435933ddSDimitry Andric           m_class_name = option_arg;
15961c3bbb01SEd Maste         break;
15977aa51b79SEd Maste       case 'h':
1598435933ddSDimitry Andric         if (!option_arg.empty())
1599435933ddSDimitry Andric           m_short_help = option_arg;
1600ac7ddfbfSEd Maste         break;
1601ac7ddfbfSEd Maste       case 's':
1602435933ddSDimitry Andric         m_synchronicity =
16034ba319b5SDimitry Andric             (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
1604435933ddSDimitry Andric                 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
1605ac7ddfbfSEd Maste         if (!error.Success())
1606435933ddSDimitry Andric           error.SetErrorStringWithFormat(
1607435933ddSDimitry Andric               "unrecognized value for synchronicity '%s'",
1608435933ddSDimitry Andric               option_arg.str().c_str());
1609ac7ddfbfSEd Maste         break;
1610ac7ddfbfSEd Maste       default:
1611435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
1612435933ddSDimitry Andric                                        short_option);
1613ac7ddfbfSEd Maste         break;
1614ac7ddfbfSEd Maste       }
1615ac7ddfbfSEd Maste 
1616ac7ddfbfSEd Maste       return error;
1617ac7ddfbfSEd Maste     }
1618ac7ddfbfSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)1619435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
16201c3bbb01SEd Maste       m_class_name.clear();
16217aa51b79SEd Maste       m_funct_name.clear();
16227aa51b79SEd Maste       m_short_help.clear();
162312b93ac6SEd Maste       m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1624ac7ddfbfSEd Maste     }
1625ac7ddfbfSEd Maste 
GetDefinitions()1626435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1627435933ddSDimitry Andric       return llvm::makeArrayRef(g_script_add_options);
1628ac7ddfbfSEd Maste     }
1629ac7ddfbfSEd Maste 
1630ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
1631ac7ddfbfSEd Maste 
16321c3bbb01SEd Maste     std::string m_class_name;
1633ac7ddfbfSEd Maste     std::string m_funct_name;
16347aa51b79SEd Maste     std::string m_short_help;
163512b93ac6SEd Maste     ScriptedCommandSynchronicity m_synchronicity;
1636ac7ddfbfSEd Maste   };
1637ac7ddfbfSEd Maste 
IOHandlerActivated(IOHandler & io_handler)1638435933ddSDimitry Andric   void IOHandlerActivated(IOHandler &io_handler) override {
163912b93ac6SEd Maste     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1640435933ddSDimitry Andric     if (output_sp) {
164112b93ac6SEd Maste       output_sp->PutCString(g_python_command_instructions);
164212b93ac6SEd Maste       output_sp->Flush();
1643ac7ddfbfSEd Maste     }
1644ac7ddfbfSEd Maste   }
1645ac7ddfbfSEd Maste 
IOHandlerInputComplete(IOHandler & io_handler,std::string & data)1646435933ddSDimitry Andric   void IOHandlerInputComplete(IOHandler &io_handler,
1647435933ddSDimitry Andric                               std::string &data) override {
164812b93ac6SEd Maste     StreamFileSP error_sp = io_handler.GetErrorStreamFile();
164912b93ac6SEd Maste 
165012b93ac6SEd Maste     ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1651435933ddSDimitry Andric     if (interpreter) {
165212b93ac6SEd Maste 
165312b93ac6SEd Maste       StringList lines;
165412b93ac6SEd Maste       lines.SplitIntoLines(data);
1655435933ddSDimitry Andric       if (lines.GetSize() > 0) {
1656ac7ddfbfSEd Maste         std::string funct_name_str;
1657435933ddSDimitry Andric         if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1658435933ddSDimitry Andric           if (funct_name_str.empty()) {
1659435933ddSDimitry Andric             error_sp->Printf("error: unable to obtain a function name, didn't "
1660435933ddSDimitry Andric                              "add python command.\n");
166112b93ac6SEd Maste             error_sp->Flush();
1662435933ddSDimitry Andric           } else {
1663ac7ddfbfSEd Maste             // everything should be fine now, let's add this alias
1664ac7ddfbfSEd Maste 
1665435933ddSDimitry Andric             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1666435933ddSDimitry Andric                 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
166712b93ac6SEd Maste                 m_synchronicity));
1668ac7ddfbfSEd Maste 
1669435933ddSDimitry Andric             if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1670435933ddSDimitry Andric                                               true)) {
1671435933ddSDimitry Andric               error_sp->Printf("error: unable to add selected command, didn't "
1672435933ddSDimitry Andric                                "add python command.\n");
167312b93ac6SEd Maste               error_sp->Flush();
1674ac7ddfbfSEd Maste             }
1675ac7ddfbfSEd Maste           }
1676435933ddSDimitry Andric         } else {
1677435933ddSDimitry Andric           error_sp->Printf(
1678435933ddSDimitry Andric               "error: unable to create function, didn't add python command.\n");
167912b93ac6SEd Maste           error_sp->Flush();
168012b93ac6SEd Maste         }
1681435933ddSDimitry Andric       } else {
168212b93ac6SEd Maste         error_sp->Printf("error: empty function, didn't add python command.\n");
168312b93ac6SEd Maste         error_sp->Flush();
168412b93ac6SEd Maste       }
1685435933ddSDimitry Andric     } else {
1686435933ddSDimitry Andric       error_sp->Printf(
1687435933ddSDimitry Andric           "error: script interpreter missing, didn't add python command.\n");
168812b93ac6SEd Maste       error_sp->Flush();
168912b93ac6SEd Maste     }
169012b93ac6SEd Maste 
169112b93ac6SEd Maste     io_handler.SetIsDone(true);
169212b93ac6SEd Maste   }
1693ac7ddfbfSEd Maste 
1694ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1695435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1696435933ddSDimitry Andric     if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1697435933ddSDimitry Andric         lldb::eScriptLanguagePython) {
1698435933ddSDimitry Andric       result.AppendError("only scripting language supported for scripted "
1699435933ddSDimitry Andric                          "commands is currently Python");
1700ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1701ac7ddfbfSEd Maste       return false;
1702ac7ddfbfSEd Maste     }
1703ac7ddfbfSEd Maste 
1704435933ddSDimitry Andric     if (command.GetArgumentCount() != 1) {
1705ac7ddfbfSEd Maste       result.AppendError("'command script add' requires one argument");
1706ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1707ac7ddfbfSEd Maste       return false;
1708ac7ddfbfSEd Maste     }
1709ac7ddfbfSEd Maste 
17107aa51b79SEd Maste     // Store the options in case we get multi-line input
1711435933ddSDimitry Andric     m_cmd_name = command[0].ref;
17127aa51b79SEd Maste     m_short_help.assign(m_options.m_short_help);
171312b93ac6SEd Maste     m_synchronicity = m_options.m_synchronicity;
1714ac7ddfbfSEd Maste 
1715435933ddSDimitry Andric     if (m_options.m_class_name.empty()) {
1716435933ddSDimitry Andric       if (m_options.m_funct_name.empty()) {
1717435933ddSDimitry Andric         m_interpreter.GetPythonCommandsFromIOHandler(
1718435933ddSDimitry Andric             "     ",  // Prompt
171912b93ac6SEd Maste             *this,    // IOHandlerDelegate
172012b93ac6SEd Maste             true,     // Run IOHandler in async mode
1721435933ddSDimitry Andric             nullptr); // Baton for the "io_handler" that will be passed back
1722435933ddSDimitry Andric                       // into our IOHandlerDelegate functions
1723435933ddSDimitry Andric       } else {
1724435933ddSDimitry Andric         CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1725435933ddSDimitry Andric             m_interpreter, m_cmd_name, m_options.m_funct_name,
1726435933ddSDimitry Andric             m_options.m_short_help, m_synchronicity));
1727435933ddSDimitry Andric         if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1728ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1729435933ddSDimitry Andric         } else {
1730ac7ddfbfSEd Maste           result.AppendError("cannot add command");
1731ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
1732ac7ddfbfSEd Maste         }
1733ac7ddfbfSEd Maste       }
1734435933ddSDimitry Andric     } else {
1735435933ddSDimitry Andric       ScriptInterpreter *interpreter =
1736435933ddSDimitry Andric           GetCommandInterpreter().GetScriptInterpreter();
1737435933ddSDimitry Andric       if (!interpreter) {
17381c3bbb01SEd Maste         result.AppendError("cannot find ScriptInterpreter");
17391c3bbb01SEd Maste         result.SetStatus(eReturnStatusFailed);
17401c3bbb01SEd Maste         return false;
17411c3bbb01SEd Maste       }
17421c3bbb01SEd Maste 
1743435933ddSDimitry Andric       auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1744435933ddSDimitry Andric           m_options.m_class_name.c_str());
1745435933ddSDimitry Andric       if (!cmd_obj_sp) {
17461c3bbb01SEd Maste         result.AppendError("cannot create helper object");
17471c3bbb01SEd Maste         result.SetStatus(eReturnStatusFailed);
17481c3bbb01SEd Maste         return false;
17491c3bbb01SEd Maste       }
17501c3bbb01SEd Maste 
1751435933ddSDimitry Andric       CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1752435933ddSDimitry Andric           m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1753435933ddSDimitry Andric       if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
17541c3bbb01SEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
1755435933ddSDimitry Andric       } else {
17561c3bbb01SEd Maste         result.AppendError("cannot add command");
17571c3bbb01SEd Maste         result.SetStatus(eReturnStatusFailed);
17581c3bbb01SEd Maste       }
17591c3bbb01SEd Maste     }
1760ac7ddfbfSEd Maste 
1761ac7ddfbfSEd Maste     return result.Succeeded();
1762ac7ddfbfSEd Maste   }
1763ac7ddfbfSEd Maste 
1764ac7ddfbfSEd Maste   CommandOptions m_options;
176512b93ac6SEd Maste   std::string m_cmd_name;
17667aa51b79SEd Maste   std::string m_short_help;
176712b93ac6SEd Maste   ScriptedCommandSynchronicity m_synchronicity;
1768ac7ddfbfSEd Maste };
1769ac7ddfbfSEd Maste 
1770ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1771ac7ddfbfSEd Maste // CommandObjectCommandsScriptList
1772ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1773ac7ddfbfSEd Maste 
1774435933ddSDimitry Andric class CommandObjectCommandsScriptList : public CommandObjectParsed {
1775ac7ddfbfSEd Maste public:
CommandObjectCommandsScriptList(CommandInterpreter & interpreter)1776435933ddSDimitry Andric   CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1777435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "command script list",
1778435933ddSDimitry Andric                             "List defined scripted commands.", nullptr) {}
1779ac7ddfbfSEd Maste 
17804bb0738eSEd Maste   ~CommandObjectCommandsScriptList() override = default;
1781ac7ddfbfSEd Maste 
DoExecute(Args & command,CommandReturnObject & result)1782435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1783435933ddSDimitry Andric     m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1784ac7ddfbfSEd Maste 
1785ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
1786ac7ddfbfSEd Maste 
1787ac7ddfbfSEd Maste     return true;
1788ac7ddfbfSEd Maste   }
1789ac7ddfbfSEd Maste };
1790ac7ddfbfSEd Maste 
1791ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1792ac7ddfbfSEd Maste // CommandObjectCommandsScriptClear
1793ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1794ac7ddfbfSEd Maste 
1795435933ddSDimitry Andric class CommandObjectCommandsScriptClear : public CommandObjectParsed {
1796ac7ddfbfSEd Maste public:
CommandObjectCommandsScriptClear(CommandInterpreter & interpreter)1797435933ddSDimitry Andric   CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1798435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "command script clear",
1799435933ddSDimitry Andric                             "Delete all scripted commands.", nullptr) {}
1800ac7ddfbfSEd Maste 
18014bb0738eSEd Maste   ~CommandObjectCommandsScriptClear() override = default;
1802ac7ddfbfSEd Maste 
1803ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1804435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1805ac7ddfbfSEd Maste     m_interpreter.RemoveAllUser();
1806ac7ddfbfSEd Maste 
1807ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
1808ac7ddfbfSEd Maste 
1809ac7ddfbfSEd Maste     return true;
1810ac7ddfbfSEd Maste   }
1811ac7ddfbfSEd Maste };
1812ac7ddfbfSEd Maste 
1813ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1814ac7ddfbfSEd Maste // CommandObjectCommandsScriptDelete
1815ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1816ac7ddfbfSEd Maste 
1817435933ddSDimitry Andric class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
1818ac7ddfbfSEd Maste public:
CommandObjectCommandsScriptDelete(CommandInterpreter & interpreter)1819435933ddSDimitry Andric   CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1820435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "command script delete",
1821435933ddSDimitry Andric                             "Delete a scripted command.", nullptr) {
1822ac7ddfbfSEd Maste     CommandArgumentEntry arg1;
1823ac7ddfbfSEd Maste     CommandArgumentData cmd_arg;
1824ac7ddfbfSEd Maste 
1825ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1826ac7ddfbfSEd Maste     cmd_arg.arg_type = eArgTypeCommandName;
1827ac7ddfbfSEd Maste     cmd_arg.arg_repetition = eArgRepeatPlain;
1828ac7ddfbfSEd Maste 
1829435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1830435933ddSDimitry Andric     // argument entry.
1831ac7ddfbfSEd Maste     arg1.push_back(cmd_arg);
1832ac7ddfbfSEd Maste 
1833ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1834ac7ddfbfSEd Maste     m_arguments.push_back(arg1);
1835ac7ddfbfSEd Maste   }
1836ac7ddfbfSEd Maste 
18374bb0738eSEd Maste   ~CommandObjectCommandsScriptDelete() override = default;
1838ac7ddfbfSEd Maste 
1839ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1840435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1841ac7ddfbfSEd Maste 
1842435933ddSDimitry Andric     if (command.GetArgumentCount() != 1) {
1843ac7ddfbfSEd Maste       result.AppendError("'command script delete' requires one argument");
1844ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1845ac7ddfbfSEd Maste       return false;
1846ac7ddfbfSEd Maste     }
1847ac7ddfbfSEd Maste 
1848435933ddSDimitry Andric     auto cmd_name = command[0].ref;
1849ac7ddfbfSEd Maste 
1850435933ddSDimitry Andric     if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1851435933ddSDimitry Andric         !m_interpreter.UserCommandExists(cmd_name)) {
1852435933ddSDimitry Andric       result.AppendErrorWithFormat("command %s not found", command[0].c_str());
1853435933ddSDimitry Andric       result.SetStatus(eReturnStatusFailed);
1854435933ddSDimitry Andric       return false;
1855435933ddSDimitry Andric     }
1856435933ddSDimitry Andric 
1857ac7ddfbfSEd Maste     m_interpreter.RemoveUser(cmd_name);
1858ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishResult);
1859435933ddSDimitry Andric     return true;
1860ac7ddfbfSEd Maste   }
1861ac7ddfbfSEd Maste };
1862ac7ddfbfSEd Maste 
1863ac7ddfbfSEd Maste #pragma mark CommandObjectMultiwordCommandsScript
1864ac7ddfbfSEd Maste 
1865ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1866ac7ddfbfSEd Maste // CommandObjectMultiwordCommandsScript
1867ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1868ac7ddfbfSEd Maste 
1869435933ddSDimitry Andric class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
1870ac7ddfbfSEd Maste public:
CommandObjectMultiwordCommandsScript(CommandInterpreter & interpreter)18714bb0738eSEd Maste   CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1872435933ddSDimitry Andric       : CommandObjectMultiword(
1873435933ddSDimitry Andric             interpreter, "command script", "Commands for managing custom "
1874435933ddSDimitry Andric                                            "commands implemented by "
1875435933ddSDimitry Andric                                            "interpreter scripts.",
1876435933ddSDimitry Andric             "command script <subcommand> [<subcommand-options>]") {
1877435933ddSDimitry Andric     LoadSubCommand("add", CommandObjectSP(
1878435933ddSDimitry Andric                               new CommandObjectCommandsScriptAdd(interpreter)));
1879435933ddSDimitry Andric     LoadSubCommand(
1880435933ddSDimitry Andric         "delete",
1881435933ddSDimitry Andric         CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1882435933ddSDimitry Andric     LoadSubCommand(
1883435933ddSDimitry Andric         "clear",
1884435933ddSDimitry Andric         CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1885435933ddSDimitry Andric     LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1886435933ddSDimitry Andric                                interpreter)));
1887435933ddSDimitry Andric     LoadSubCommand(
1888435933ddSDimitry Andric         "import",
1889435933ddSDimitry Andric         CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1890ac7ddfbfSEd Maste   }
1891ac7ddfbfSEd Maste 
18924bb0738eSEd Maste   ~CommandObjectMultiwordCommandsScript() override = default;
1893ac7ddfbfSEd Maste };
1894ac7ddfbfSEd Maste 
1895ac7ddfbfSEd Maste #pragma mark CommandObjectMultiwordCommands
1896ac7ddfbfSEd Maste 
1897ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1898ac7ddfbfSEd Maste // CommandObjectMultiwordCommands
1899ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1900ac7ddfbfSEd Maste 
CommandObjectMultiwordCommands(CommandInterpreter & interpreter)1901435933ddSDimitry Andric CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1902435933ddSDimitry Andric     CommandInterpreter &interpreter)
1903435933ddSDimitry Andric     : CommandObjectMultiword(interpreter, "command",
1904435933ddSDimitry Andric                              "Commands for managing custom LLDB commands.",
1905435933ddSDimitry Andric                              "command <subcommand> [<subcommand-options>]") {
1906435933ddSDimitry Andric   LoadSubCommand("source",
1907435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1908435933ddSDimitry Andric   LoadSubCommand("alias",
1909435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1910435933ddSDimitry Andric   LoadSubCommand("unalias", CommandObjectSP(
1911435933ddSDimitry Andric                                 new CommandObjectCommandsUnalias(interpreter)));
1912435933ddSDimitry Andric   LoadSubCommand("delete",
1913435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1914435933ddSDimitry Andric   LoadSubCommand(
1915435933ddSDimitry Andric       "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1916435933ddSDimitry Andric   LoadSubCommand("history", CommandObjectSP(
1917435933ddSDimitry Andric                                 new CommandObjectCommandsHistory(interpreter)));
1918435933ddSDimitry Andric   LoadSubCommand(
1919435933ddSDimitry Andric       "script",
1920435933ddSDimitry Andric       CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
1921ac7ddfbfSEd Maste }
1922ac7ddfbfSEd Maste 
19234bb0738eSEd Maste CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
1924