blob: 584e081c6e87ad02b3aea09c4558bb7a3a3d1e0e [file] [log] [blame]
Alexander Shaposhnikov696bd632016-11-26 05:23:44 +00001//===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===//
Jim Inghamebc09c32010-07-07 03:36:20 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Jim Inghamebc09c32010-07-07 03:36:20 +000010// C Includes
11// C++ Includes
12// Other libraries and framework includes
Greg Clayton0e5e5a72011-04-20 22:55:21 +000013#include "llvm/ADT/StringRef.h"
14
Jim Inghamebc09c32010-07-07 03:36:20 +000015// Project includes
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000016#include "CommandObjectCommands.h"
Enrico Granata46d4aa22016-02-29 23:22:53 +000017#include "CommandObjectHelp.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000018#include "lldb/Core/Debugger.h"
Greg Clayton44d93782014-01-27 23:43:24 +000019#include "lldb/Core/IOHandler.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000020#include "lldb/Host/OptionParser.h"
Enrico Granata7594f142013-06-17 22:51:50 +000021#include "lldb/Interpreter/CommandHistory.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000022#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytonde164aa2011-04-20 16:37:46 +000023#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000024#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000025#include "lldb/Interpreter/OptionArgParser.h"
Enrico Granata012d4fc2013-06-11 01:26:35 +000026#include "lldb/Interpreter/OptionValueBoolean.h"
Enrico Granata45d0e232016-03-31 01:10:54 +000027#include "lldb/Interpreter/OptionValueString.h"
Enrico Granata7594f142013-06-17 22:51:50 +000028#include "lldb/Interpreter/OptionValueUInt64.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000029#include "lldb/Interpreter/Options.h"
Enrico Granata99f0b8f2011-08-17 01:30:04 +000030#include "lldb/Interpreter/ScriptInterpreter.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000031#include "lldb/Utility/Args.h"
Zachary Turner573ab902017-03-21 18:25:04 +000032#include "lldb/Utility/StringList.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Jim Inghamebc09c32010-07-07 03:36:20 +000037//-------------------------------------------------------------------------
38// CommandObjectCommandsSource
39//-------------------------------------------------------------------------
40
Zachary Turner1f0f5b52016-09-22 20:22:55 +000041static OptionDefinition g_history_options[] = {
42 // clang-format off
43 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
44 { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." },
45 { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
46 { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." },
47 // clang-format on
48};
49
Kate Stoneb9c1b512016-09-06 20:57:50 +000050class CommandObjectCommandsHistory : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +000051public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 CommandObjectCommandsHistory(CommandInterpreter &interpreter)
53 : CommandObjectParsed(interpreter, "command history",
Jim Inghamaab5be02017-04-19 23:21:04 +000054 "Dump the history of commands in this session.\n"
55 "Commands in the history list can be run again "
56 "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run "
57 "the command that is <OFFSET> commands from the end"
58 " of the list (counting the current command).",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000059 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 m_options() {}
Jim Ingham5a988412012-06-08 21:56:10 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 ~CommandObjectCommandsHistory() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +000063
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +000065
66protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 class CommandOptions : public Options {
68 public:
69 CommandOptions()
70 : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
Jim Inghama5a97eb2011-07-12 03:12:18 +000071 }
Jim Ingham5a988412012-06-08 21:56:10 +000072
Kate Stoneb9c1b512016-09-06 20:57:50 +000073 ~CommandOptions() override = default;
74
Zachary Turner97206d52017-05-12 04:51:55 +000075 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
76 ExecutionContext *execution_context) override {
77 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 const int short_option = m_getopt_table[option_idx].val;
79
80 switch (short_option) {
81 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +000082 error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 break;
84 case 's':
Zachary Turnerfe114832016-11-12 16:56:47 +000085 if (option_arg == "end") {
Kate Stoneb9c1b512016-09-06 20:57:50 +000086 m_start_idx.SetCurrentValue(UINT64_MAX);
87 m_start_idx.SetOptionWasSet();
88 } else
Zachary Turnerfe114832016-11-12 16:56:47 +000089 error = m_start_idx.SetValueFromString(option_arg,
Kate Stoneb9c1b512016-09-06 20:57:50 +000090 eVarSetOperationAssign);
91 break;
92 case 'e':
Zachary Turnerfe114832016-11-12 16:56:47 +000093 error =
94 m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 break;
96 case 'C':
97 m_clear.SetCurrentValue(true);
98 m_clear.SetOptionWasSet();
99 break;
100 default:
101 error.SetErrorStringWithFormat("unrecognized option '%c'",
102 short_option);
103 break;
104 }
105
106 return error;
107 }
108
109 void OptionParsingStarting(ExecutionContext *execution_context) override {
110 m_start_idx.Clear();
111 m_stop_idx.Clear();
112 m_count.Clear();
113 m_clear.Clear();
114 }
115
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000116 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000117 return llvm::makeArrayRef(g_history_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000118 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119
120 // Instance variables to hold the values for command options.
121
122 OptionValueUInt64 m_start_idx;
123 OptionValueUInt64 m_stop_idx;
124 OptionValueUInt64 m_count;
125 OptionValueBoolean m_clear;
126 };
127
128 bool DoExecute(Args &command, CommandReturnObject &result) override {
129 if (m_options.m_clear.GetCurrentValue() &&
130 m_options.m_clear.OptionWasSet()) {
131 m_interpreter.GetCommandHistory().Clear();
132 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
133 } else {
134 if (m_options.m_start_idx.OptionWasSet() &&
135 m_options.m_stop_idx.OptionWasSet() &&
136 m_options.m_count.OptionWasSet()) {
137 result.AppendError("--count, --start-index and --end-index cannot be "
138 "all specified in the same invocation");
139 result.SetStatus(lldb::eReturnStatusFailed);
140 } else {
141 std::pair<bool, uint64_t> start_idx(
142 m_options.m_start_idx.OptionWasSet(),
143 m_options.m_start_idx.GetCurrentValue());
144 std::pair<bool, uint64_t> stop_idx(
145 m_options.m_stop_idx.OptionWasSet(),
146 m_options.m_stop_idx.GetCurrentValue());
147 std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
148 m_options.m_count.GetCurrentValue());
149
150 const CommandHistory &history(m_interpreter.GetCommandHistory());
151
152 if (start_idx.first && start_idx.second == UINT64_MAX) {
153 if (count.first) {
154 start_idx.second = history.GetSize() - count.second;
155 stop_idx.second = history.GetSize() - 1;
156 } else if (stop_idx.first) {
157 start_idx.second = stop_idx.second;
158 stop_idx.second = history.GetSize() - 1;
159 } else {
160 start_idx.second = 0;
161 stop_idx.second = history.GetSize() - 1;
162 }
163 } else {
164 if (!start_idx.first && !stop_idx.first && !count.first) {
165 start_idx.second = 0;
166 stop_idx.second = history.GetSize() - 1;
167 } else if (start_idx.first) {
168 if (count.first) {
169 stop_idx.second = start_idx.second + count.second - 1;
170 } else if (!stop_idx.first) {
171 stop_idx.second = history.GetSize() - 1;
172 }
173 } else if (stop_idx.first) {
174 if (count.first) {
175 if (stop_idx.second >= count.second)
176 start_idx.second = stop_idx.second - count.second + 1;
177 else
178 start_idx.second = 0;
179 }
180 } else /* if (count.first) */
181 {
182 start_idx.second = 0;
183 stop_idx.second = count.second - 1;
184 }
185 }
186 history.Dump(result.GetOutputStream(), start_idx.second,
187 stop_idx.second);
188 }
189 }
190 return result.Succeeded();
191 }
192
193 CommandOptions m_options;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000194};
195
Jim Inghama5a97eb2011-07-12 03:12:18 +0000196//-------------------------------------------------------------------------
197// CommandObjectCommandsSource
198//-------------------------------------------------------------------------
199
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000200static OptionDefinition g_source_options[] = {
201 // clang-format off
202 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
203 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
204 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
205 // clang-format on
206};
207
Kate Stoneb9c1b512016-09-06 20:57:50 +0000208class CommandObjectCommandsSource : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000209public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210 CommandObjectCommandsSource(CommandInterpreter &interpreter)
211 : CommandObjectParsed(
212 interpreter, "command source",
213 "Read and execute LLDB commands from the file <filename>.",
214 nullptr),
215 m_options() {
216 CommandArgumentEntry arg;
217 CommandArgumentData file_arg;
Jim Ingham5a988412012-06-08 21:56:10 +0000218
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 // Define the first (and only) variant of this arg.
220 file_arg.arg_type = eArgTypeFilename;
221 file_arg.arg_repetition = eArgRepeatPlain;
Jim Ingham5a988412012-06-08 21:56:10 +0000222
Kate Stoneb9c1b512016-09-06 20:57:50 +0000223 // There is only one variant this argument could be; put it into the
224 // argument entry.
225 arg.push_back(file_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +0000226
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227 // Push the data for the first argument into the m_arguments vector.
228 m_arguments.push_back(arg);
229 }
Jim Ingham5a988412012-06-08 21:56:10 +0000230
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 ~CommandObjectCommandsSource() override = default;
232
233 const char *GetRepeatCommand(Args &current_command_args,
234 uint32_t index) override {
235 return "";
236 }
237
Raphael Isemann2443bbd2018-07-02 21:29:56 +0000238 int HandleArgumentCompletion(
239 CompletionRequest &request,
240 OptionElementVector &opt_element_vector) override {
241 auto completion_str = request.GetParsedLine()[request.GetCursorIndex()].ref;
242 completion_str = completion_str.take_front(request.GetCursorCharPosition());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000243
Raphael Isemann2443bbd2018-07-02 21:29:56 +0000244 bool word_complete = request.GetWordComplete();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000245 CommandCompletions::InvokeCommonCompletionCallbacks(
246 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
Raphael Isemann2443bbd2018-07-02 21:29:56 +0000247 completion_str, request.GetMatchStartPoint(),
248 request.GetMaxReturnElements(), nullptr, word_complete,
249 request.GetMatches());
250 request.SetWordComplete(word_complete);
251 return request.GetMatches().GetSize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 }
253
254 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +0000255
256protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257 class CommandOptions : public Options {
258 public:
259 CommandOptions()
260 : Options(), m_stop_on_error(true), m_silent_run(false),
261 m_stop_on_continue(true) {}
Jim Inghame16c50a2011-02-18 00:54:25 +0000262
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263 ~CommandOptions() override = default;
Jim Inghame16c50a2011-02-18 00:54:25 +0000264
Zachary Turner97206d52017-05-12 04:51:55 +0000265 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
266 ExecutionContext *execution_context) override {
267 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268 const int short_option = m_getopt_table[option_idx].val;
Greg Clayton340b0302014-02-05 17:57:57 +0000269
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 switch (short_option) {
271 case 'e':
Zachary Turnerfe114832016-11-12 16:56:47 +0000272 error = m_stop_on_error.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000274
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +0000276 error = m_stop_on_continue.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000277 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 case 's':
Zachary Turnerfe114832016-11-12 16:56:47 +0000280 error = m_silent_run.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000281 break;
Jim Inghame16c50a2011-02-18 00:54:25 +0000282
Kate Stoneb9c1b512016-09-06 20:57:50 +0000283 default:
284 error.SetErrorStringWithFormat("unrecognized option '%c'",
285 short_option);
286 break;
287 }
Jim Inghame16c50a2011-02-18 00:54:25 +0000288
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 return error;
Jim Inghamebc09c32010-07-07 03:36:20 +0000290 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000291
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 void OptionParsingStarting(ExecutionContext *execution_context) override {
293 m_stop_on_error.Clear();
294 m_silent_run.Clear();
295 m_stop_on_continue.Clear();
296 }
297
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000298 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000299 return llvm::makeArrayRef(g_source_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000300 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301
302 // Instance variables to hold the values for command options.
303
304 OptionValueBoolean m_stop_on_error;
305 OptionValueBoolean m_silent_run;
306 OptionValueBoolean m_stop_on_continue;
307 };
308
309 bool DoExecute(Args &command, CommandReturnObject &result) override {
Zachary Turner4574a892016-12-08 01:31:04 +0000310 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311 result.AppendErrorWithFormat(
312 "'%s' takes exactly one executable filename argument.\n",
Zachary Turnera4496982016-10-05 21:14:38 +0000313 GetCommandName().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000315 return false;
316 }
317
318 FileSpec cmd_file(command[0].ref, true);
319 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
320
321 // If any options were set, then use them
322 if (m_options.m_stop_on_error.OptionWasSet() ||
323 m_options.m_silent_run.OptionWasSet() ||
324 m_options.m_stop_on_continue.OptionWasSet()) {
325 // Use user set settings
326 CommandInterpreterRunOptions options;
327 options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
328 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
329 options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
330 options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
331
332 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
333 } else {
Adrian Prantl05097242018-04-30 16:49:04 +0000334 // No options were set, inherit any settings from nested "command source"
335 // commands, or set to sane default settings...
Zachary Turner4574a892016-12-08 01:31:04 +0000336 CommandInterpreterRunOptions options;
337 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000338 }
339 return result.Succeeded();
340 }
341
342 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000343};
344
345#pragma mark CommandObjectCommandsAlias
346//-------------------------------------------------------------------------
347// CommandObjectCommandsAlias
348//-------------------------------------------------------------------------
349
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000350static OptionDefinition g_alias_options[] = {
351 // clang-format off
352 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
353 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
354 // clang-format on
355};
356
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357static const char *g_python_command_instructions =
358 "Enter your Python command(s). Type 'DONE' to end.\n"
359 "You must define a Python function with this signature:\n"
360 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000361
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362class CommandObjectCommandsAlias : public CommandObjectRaw {
Enrico Granata45d0e232016-03-31 01:10:54 +0000363protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 class CommandOptions : public OptionGroup {
365 public:
366 CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
Enrico Granata45d0e232016-03-31 01:10:54 +0000367
Kate Stoneb9c1b512016-09-06 20:57:50 +0000368 ~CommandOptions() override = default;
369
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000370 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000371 return llvm::makeArrayRef(g_alias_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000372 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373
Zachary Turner97206d52017-05-12 04:51:55 +0000374 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
375 ExecutionContext *execution_context) override {
376 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000378 const int short_option = GetDefinitions()[option_idx].short_option;
Zachary Turner8cef4b02016-09-23 17:48:13 +0000379 std::string option_str(option_value);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380
381 switch (short_option) {
382 case 'h':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000383 m_help.SetCurrentValue(option_str);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 m_help.SetOptionWasSet();
385 break;
386
387 case 'H':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000388 m_long_help.SetCurrentValue(option_str);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000389 m_long_help.SetOptionWasSet();
390 break;
391
392 default:
393 error.SetErrorStringWithFormat("invalid short option character '%c'",
394 short_option);
395 break;
396 }
397
398 return error;
Enrico Granata45d0e232016-03-31 01:10:54 +0000399 }
400
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 void OptionParsingStarting(ExecutionContext *execution_context) override {
402 m_help.Clear();
403 m_long_help.Clear();
404 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000405
Kate Stoneb9c1b512016-09-06 20:57:50 +0000406 OptionValueString m_help;
407 OptionValueString m_long_help;
408 };
409
410 OptionGroupOptions m_option_group;
411 CommandOptions m_command_options;
412
413public:
414 Options *GetOptions() override { return &m_option_group; }
415
416 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
417 : CommandObjectRaw(
418 interpreter, "command alias",
Zachary Turnera4496982016-10-05 21:14:38 +0000419 "Define a custom command in terms of an existing command."),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000420 m_option_group(), m_command_options() {
421 m_option_group.Append(&m_command_options);
422 m_option_group.Finalize();
423
424 SetHelpLong(
425 "'alias' allows the user to create a short-cut or abbreviation for long \
Kate Stoneea671fb2015-07-14 05:48:36 +0000426commands, multi-word commands, and commands that take particular options. \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427Below are some simple examples of how one might use the 'alias' command:"
428 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000429
430(lldb) command alias sc script
431
432 Creates the abbreviation 'sc' for the 'script' command.
433
434(lldb) command alias bp breakpoint
435
Kate Stoneb9c1b512016-09-06 20:57:50 +0000436)"
437 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
Kate Stoneea671fb2015-07-14 05:48:36 +0000438breakpoint commands are two-word commands, the user would still need to \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
440 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000441
442(lldb) command alias bpl breakpoint list
443
444 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
445
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446)"
447 "An alias can include some options for the command, with the values either \
Kate Stoneea671fb2015-07-14 05:48:36 +0000448filled in at the time the alias is created, or specified as positional \
449arguments, to be filled in when the alias is invoked. The following example \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000450shows how to create aliases with options:"
451 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000452
453(lldb) command alias bfl breakpoint set -f %1 -l %2
454
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455)"
456 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
Kate Stoneea671fb2015-07-14 05:48:36 +0000457options already part of the alias. So if the user wants to set a breakpoint \
458by file and line without explicitly having to use the -f and -l options, the \
459user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
460for the actual arguments that will be passed when the alias command is used. \
461The number in the placeholder refers to the position/order the actual value \
462occupies when the alias is used. All the occurrences of '%1' in the alias \
463will be replaced with the first argument, all the occurrences of '%2' in the \
464alias will be replaced with the second argument, and so on. This also allows \
465actual arguments to be used multiple times within an alias (see 'process \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466launch' example below)."
467 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000468
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469)"
470 "Note: the positional arguments must substitute as whole words in the resultant \
Kate Stoneea671fb2015-07-14 05:48:36 +0000471command, so you can't at present do something like this to append the file extension \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000472\".cpp\":"
473 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000474
475(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
476
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477)"
478 "For more complex aliasing, use the \"command regex\" command instead. In the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000479'bfl' case above, the actual file value will be filled in with the first argument \
480following 'bfl' and the actual line number value will be filled in with the second \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481argument. The user would use this alias as follows:"
482 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000483
484(lldb) command alias bfl breakpoint set -f %1 -l %2
485(lldb) bfl my-file.c 137
486
487This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
488
489Another example:
490
491(lldb) command alias pltty process launch -s -o %1 -e %1
492(lldb) pltty /dev/tty0
493
494 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
495
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496)"
497 "If the user always wanted to pass the same value to a particular option, the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000498alias could be defined with that value directly in the alias as a constant, \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499rather than using a positional placeholder:"
500 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000501
502(lldb) command alias bl3 breakpoint set -f %1 -l 3
503
Kate Stoneb9c1b512016-09-06 20:57:50 +0000504 Always sets a breakpoint on line 3 of whatever file is indicated.)");
Jim Inghamebc09c32010-07-07 03:36:20 +0000505
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506 CommandArgumentEntry arg1;
507 CommandArgumentEntry arg2;
508 CommandArgumentEntry arg3;
509 CommandArgumentData alias_arg;
510 CommandArgumentData cmd_arg;
511 CommandArgumentData options_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000512
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513 // Define the first (and only) variant of this arg.
514 alias_arg.arg_type = eArgTypeAliasName;
515 alias_arg.arg_repetition = eArgRepeatPlain;
516
517 // There is only one variant this argument could be; put it into the
518 // argument entry.
519 arg1.push_back(alias_arg);
520
521 // Define the first (and only) variant of this arg.
522 cmd_arg.arg_type = eArgTypeCommandName;
523 cmd_arg.arg_repetition = eArgRepeatPlain;
524
525 // There is only one variant this argument could be; put it into the
526 // argument entry.
527 arg2.push_back(cmd_arg);
528
529 // Define the first (and only) variant of this arg.
530 options_arg.arg_type = eArgTypeAliasOptions;
531 options_arg.arg_repetition = eArgRepeatOptional;
532
533 // There is only one variant this argument could be; put it into the
534 // argument entry.
535 arg3.push_back(options_arg);
536
537 // Push the data for the first argument into the m_arguments vector.
538 m_arguments.push_back(arg1);
539 m_arguments.push_back(arg2);
540 m_arguments.push_back(arg3);
541 }
542
543 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000544
Jim Ingham5a988412012-06-08 21:56:10 +0000545protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546 bool DoExecute(const char *raw_command_line,
547 CommandReturnObject &result) override {
548 if (!raw_command_line || !raw_command_line[0]) {
549 result.AppendError("'command alias' requires at least two arguments");
550 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000551 }
552
Kate Stoneb9c1b512016-09-06 20:57:50 +0000553 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
554 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
Caroline Ticeca90c472011-05-06 21:37:15 +0000555
Kate Stoneb9c1b512016-09-06 20:57:50 +0000556 const char *remainder = nullptr;
Enrico Granata212130a2016-03-08 05:37:15 +0000557
Kate Stoneb9c1b512016-09-06 20:57:50 +0000558 if (raw_command_line[0] == '-') {
559 // We have some options and these options MUST end with --.
560 const char *end_options = nullptr;
561 const char *s = raw_command_line;
562 while (s && s[0]) {
563 end_options = ::strstr(s, "--");
564 if (end_options) {
565 end_options += 2; // Get past the "--"
566 if (::isspace(end_options[0])) {
567 remainder = end_options;
568 while (::isspace(*remainder))
569 ++remainder;
570 break;
571 }
572 }
573 s = end_options;
574 }
575
576 if (end_options) {
577 Args args(
578 llvm::StringRef(raw_command_line, end_options - raw_command_line));
579 if (!ParseOptions(args, result))
580 return false;
581
Zachary Turner97206d52017-05-12 04:51:55 +0000582 Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000583 if (error.Fail()) {
584 result.AppendError(error.AsCString());
585 result.SetStatus(eReturnStatusFailed);
586 return false;
587 }
588 }
Caroline Tice844d2302010-12-09 22:52:49 +0000589 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000590 if (nullptr == remainder)
591 remainder = raw_command_line;
Jim Inghamebc09c32010-07-07 03:36:20 +0000592
Zachary Turnera01bccd2016-10-05 21:14:56 +0000593 llvm::StringRef raw_command_string(remainder);
594 Args args(raw_command_string);
Jim Inghamebc09c32010-07-07 03:36:20 +0000595
Zachary Turner11eb9c62016-10-05 20:03:37 +0000596 if (args.GetArgumentCount() < 2) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000597 result.AppendError("'command alias' requires at least two arguments");
598 result.SetStatus(eReturnStatusFailed);
599 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000600 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000601
602 // Get the alias command.
603
Zachary Turner4574a892016-12-08 01:31:04 +0000604 auto alias_command = args[0].ref;
605 if (alias_command.startswith("-")) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000606 result.AppendError("aliases starting with a dash are not supported");
607 if (alias_command == "--help" || alias_command == "--long-help") {
608 result.AppendWarning("if trying to pass options to 'command alias' add "
609 "a -- at the end of the options");
610 }
611 result.SetStatus(eReturnStatusFailed);
612 return false;
613 }
614
615 // Strip the new alias name off 'raw_command_string' (leave it on args,
Adrian Prantl05097242018-04-30 16:49:04 +0000616 // which gets passed to 'Execute', which does the stripping itself.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000617 size_t pos = raw_command_string.find(alias_command);
618 if (pos == 0) {
619 raw_command_string = raw_command_string.substr(alias_command.size());
620 pos = raw_command_string.find_first_not_of(' ');
621 if ((pos != std::string::npos) && (pos > 0))
622 raw_command_string = raw_command_string.substr(pos);
623 } else {
624 result.AppendError("Error parsing command string. No alias created.");
625 result.SetStatus(eReturnStatusFailed);
626 return false;
627 }
628
629 // Verify that the command is alias-able.
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000630 if (m_interpreter.CommandExists(alias_command)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000631 result.AppendErrorWithFormat(
632 "'%s' is a permanent debugger command and cannot be redefined.\n",
Zachary Turner4574a892016-12-08 01:31:04 +0000633 args[0].c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000634 result.SetStatus(eReturnStatusFailed);
635 return false;
636 }
637
638 // Get CommandObject that is being aliased. The command name is read from
Zachary Turnera01bccd2016-10-05 21:14:56 +0000639 // the front of raw_command_string. raw_command_string is returned with the
640 // name of the command object stripped off the front.
641 llvm::StringRef original_raw_command_string = raw_command_string;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000642 CommandObject *cmd_obj =
643 m_interpreter.GetCommandObjectForCommand(raw_command_string);
644
645 if (!cmd_obj) {
646 result.AppendErrorWithFormat("invalid command given to 'command alias'. "
647 "'%s' does not begin with a valid command."
648 " No alias created.",
Zachary Turnera01bccd2016-10-05 21:14:56 +0000649 original_raw_command_string.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000650 result.SetStatus(eReturnStatusFailed);
651 return false;
652 } else if (!cmd_obj->WantsRawCommandString()) {
653 // Note that args was initialized with the original command, and has not
Adrian Prantl05097242018-04-30 16:49:04 +0000654 // been updated to this point. Therefore can we pass it to the version of
655 // Execute that does not need/expect raw input in the alias.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 return HandleAliasingNormalCommand(args, result);
657 } else {
658 return HandleAliasingRawCommand(alias_command, raw_command_string,
659 *cmd_obj, result);
660 }
661 return result.Succeeded();
662 }
663
Zachary Turnera01bccd2016-10-05 21:14:56 +0000664 bool HandleAliasingRawCommand(llvm::StringRef alias_command,
665 llvm::StringRef raw_command_string,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000666 CommandObject &cmd_obj,
667 CommandReturnObject &result) {
668 // Verify & handle any options/arguments passed to the alias command
669
670 OptionArgVectorSP option_arg_vector_sp =
671 OptionArgVectorSP(new OptionArgVector);
672
673 if (CommandObjectSP cmd_obj_sp =
674 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
Zachary Turnera01bccd2016-10-05 21:14:56 +0000675 if (m_interpreter.AliasExists(alias_command) ||
676 m_interpreter.UserCommandExists(alias_command)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000677 result.AppendWarningWithFormat(
678 "Overwriting existing definition for '%s'.\n",
Zachary Turnera01bccd2016-10-05 21:14:56 +0000679 alias_command.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000680 }
681 if (CommandAlias *alias = m_interpreter.AddAlias(
Zachary Turnera01bccd2016-10-05 21:14:56 +0000682 alias_command, cmd_obj_sp, raw_command_string)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000683 if (m_command_options.m_help.OptionWasSet())
684 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
685 if (m_command_options.m_long_help.OptionWasSet())
686 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
687 result.SetStatus(eReturnStatusSuccessFinishNoResult);
688 } else {
689 result.AppendError("Unable to create requested alias.\n");
690 result.SetStatus(eReturnStatusFailed);
691 }
692
693 } else {
694 result.AppendError("Unable to create requested alias.\n");
695 result.SetStatus(eReturnStatusFailed);
696 }
697
698 return result.Succeeded();
699 }
700
701 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
702 size_t argc = args.GetArgumentCount();
703
704 if (argc < 2) {
705 result.AppendError("'command alias' requires at least two arguments");
706 result.SetStatus(eReturnStatusFailed);
707 return false;
708 }
709
Zachary Turner4574a892016-12-08 01:31:04 +0000710 // Save these in std::strings since we're going to shift them off.
711 const std::string alias_command(args[0].ref);
712 const std::string actual_command(args[1].ref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000713
714 args.Shift(); // Shift the alias command word off the argument vector.
715 args.Shift(); // Shift the old command word off the argument vector.
716
717 // Verify that the command is alias'able, and get the appropriate command
718 // object.
719
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000720 if (m_interpreter.CommandExists(alias_command)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000721 result.AppendErrorWithFormat(
722 "'%s' is a permanent debugger command and cannot be redefined.\n",
723 alias_command.c_str());
724 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000725 return false;
726 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000727
Zachary Turner4574a892016-12-08 01:31:04 +0000728 CommandObjectSP command_obj_sp(
729 m_interpreter.GetCommandSPExact(actual_command, true));
730 CommandObjectSP subcommand_obj_sp;
731 bool use_subcommand = false;
732 if (!command_obj_sp) {
733 result.AppendErrorWithFormat("'%s' is not an existing command.\n",
734 actual_command.c_str());
735 result.SetStatus(eReturnStatusFailed);
736 return false;
737 }
738 CommandObject *cmd_obj = command_obj_sp.get();
739 CommandObject *sub_cmd_obj = nullptr;
740 OptionArgVectorSP option_arg_vector_sp =
741 OptionArgVectorSP(new OptionArgVector);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000742
Zachary Turner4574a892016-12-08 01:31:04 +0000743 while (cmd_obj->IsMultiwordObject() && !args.empty()) {
744 auto sub_command = args[0].ref;
745 assert(!sub_command.empty());
746 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
747 if (!subcommand_obj_sp) {
748 result.AppendErrorWithFormat(
749 "'%s' is not a valid sub-command of '%s'. "
750 "Unable to create alias.\n",
751 args[0].c_str(), actual_command.c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000752 result.SetStatus(eReturnStatusFailed);
753 return false;
754 }
Zachary Turner4574a892016-12-08 01:31:04 +0000755
756 sub_cmd_obj = subcommand_obj_sp.get();
757 use_subcommand = true;
758 args.Shift(); // Shift the sub_command word off the argument vector.
759 cmd_obj = sub_cmd_obj;
760 }
761
762 // Verify & handle any options/arguments passed to the alias command
763
764 std::string args_string;
765
766 if (!args.empty()) {
767 CommandObjectSP tmp_sp =
768 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
769 if (use_subcommand)
770 tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
771 false);
772
773 args.GetCommandString(args_string);
774 }
775
776 if (m_interpreter.AliasExists(alias_command) ||
777 m_interpreter.UserCommandExists(alias_command)) {
778 result.AppendWarningWithFormat(
779 "Overwriting existing definition for '%s'.\n", alias_command.c_str());
780 }
781
782 if (CommandAlias *alias = m_interpreter.AddAlias(
783 alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
784 args_string)) {
785 if (m_command_options.m_help.OptionWasSet())
786 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
787 if (m_command_options.m_long_help.OptionWasSet())
788 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
789 result.SetStatus(eReturnStatusSuccessFinishNoResult);
790 } else {
791 result.AppendError("Unable to create requested alias.\n");
792 result.SetStatus(eReturnStatusFailed);
793 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000794 }
795
796 return result.Succeeded();
797 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000798};
799
800#pragma mark CommandObjectCommandsUnalias
801//-------------------------------------------------------------------------
802// CommandObjectCommandsUnalias
803//-------------------------------------------------------------------------
804
Kate Stoneb9c1b512016-09-06 20:57:50 +0000805class CommandObjectCommandsUnalias : public CommandObjectParsed {
Jim Inghamebc09c32010-07-07 03:36:20 +0000806public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000807 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
808 : CommandObjectParsed(
809 interpreter, "command unalias",
810 "Delete one or more custom commands defined by 'command alias'.",
811 nullptr) {
812 CommandArgumentEntry arg;
813 CommandArgumentData alias_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000814
Kate Stoneb9c1b512016-09-06 20:57:50 +0000815 // Define the first (and only) variant of this arg.
816 alias_arg.arg_type = eArgTypeAliasName;
817 alias_arg.arg_repetition = eArgRepeatPlain;
818
819 // There is only one variant this argument could be; put it into the
820 // argument entry.
821 arg.push_back(alias_arg);
822
823 // Push the data for the first argument into the m_arguments vector.
824 m_arguments.push_back(arg);
825 }
826
827 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000828
Jim Ingham5a988412012-06-08 21:56:10 +0000829protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000830 bool DoExecute(Args &args, CommandReturnObject &result) override {
831 CommandObject::CommandMap::iterator pos;
832 CommandObject *cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000833
Zachary Turner11eb9c62016-10-05 20:03:37 +0000834 if (args.empty()) {
835 result.AppendError("must call 'unalias' with a valid alias");
836 result.SetStatus(eReturnStatusFailed);
837 return false;
838 }
839
Zachary Turner4574a892016-12-08 01:31:04 +0000840 auto command_name = args[0].ref;
Zachary Turner11eb9c62016-10-05 20:03:37 +0000841 cmd_obj = m_interpreter.GetCommandObject(command_name);
Zachary Turner4574a892016-12-08 01:31:04 +0000842 if (!cmd_obj) {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000843 result.AppendErrorWithFormat(
844 "'%s' is not a known command.\nTry 'help' to see a "
845 "current list of commands.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000846 args[0].c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000847 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000848 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000849 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000850
Zachary Turner4574a892016-12-08 01:31:04 +0000851 if (m_interpreter.CommandExists(command_name)) {
852 if (cmd_obj->IsRemovable()) {
853 result.AppendErrorWithFormat(
854 "'%s' is not an alias, it is a debugger command which can be "
855 "removed using the 'command delete' command.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000856 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000857 } else {
858 result.AppendErrorWithFormat(
859 "'%s' is a permanent debugger command and cannot be removed.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000860 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000861 }
862 result.SetStatus(eReturnStatusFailed);
863 return false;
864 }
865
866 if (!m_interpreter.RemoveAlias(command_name)) {
867 if (m_interpreter.AliasExists(command_name))
868 result.AppendErrorWithFormat(
Zachary Turner867e7d12016-12-09 01:20:58 +0000869 "Error occurred while attempting to unalias '%s'.\n",
870 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000871 else
872 result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000873 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000874 result.SetStatus(eReturnStatusFailed);
875 return false;
876 }
877
878 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000879 return result.Succeeded();
880 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000881};
882
Greg Claytonb5472782015-01-09 19:08:20 +0000883#pragma mark CommandObjectCommandsDelete
884//-------------------------------------------------------------------------
885// CommandObjectCommandsDelete
886//-------------------------------------------------------------------------
887
Kate Stoneb9c1b512016-09-06 20:57:50 +0000888class CommandObjectCommandsDelete : public CommandObjectParsed {
Greg Claytonb5472782015-01-09 19:08:20 +0000889public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000890 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
891 : CommandObjectParsed(
892 interpreter, "command delete",
893 "Delete one or more custom commands defined by 'command regex'.",
894 nullptr) {
895 CommandArgumentEntry arg;
896 CommandArgumentData alias_arg;
Greg Claytonb5472782015-01-09 19:08:20 +0000897
Kate Stoneb9c1b512016-09-06 20:57:50 +0000898 // Define the first (and only) variant of this arg.
899 alias_arg.arg_type = eArgTypeCommandName;
900 alias_arg.arg_repetition = eArgRepeatPlain;
Greg Claytonb5472782015-01-09 19:08:20 +0000901
Kate Stoneb9c1b512016-09-06 20:57:50 +0000902 // There is only one variant this argument could be; put it into the
903 // argument entry.
904 arg.push_back(alias_arg);
Greg Claytonb5472782015-01-09 19:08:20 +0000905
Kate Stoneb9c1b512016-09-06 20:57:50 +0000906 // Push the data for the first argument into the m_arguments vector.
907 m_arguments.push_back(arg);
908 }
Greg Claytonb5472782015-01-09 19:08:20 +0000909
Kate Stoneb9c1b512016-09-06 20:57:50 +0000910 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +0000911
912protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000913 bool DoExecute(Args &args, CommandReturnObject &result) override {
914 CommandObject::CommandMap::iterator pos;
Greg Claytonb5472782015-01-09 19:08:20 +0000915
Zachary Turner11eb9c62016-10-05 20:03:37 +0000916 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000917 result.AppendErrorWithFormat("must call '%s' with one or more valid user "
918 "defined regular expression command names",
Zachary Turnera4496982016-10-05 21:14:38 +0000919 GetCommandName().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000921 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000922
Zachary Turner4574a892016-12-08 01:31:04 +0000923 auto command_name = args[0].ref;
924 if (!m_interpreter.CommandExists(command_name)) {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000925 StreamString error_msg_stream;
926 const bool generate_apropos = true;
927 const bool generate_type_lookup = false;
928 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
Zachary Turner4574a892016-12-08 01:31:04 +0000929 &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
930 generate_apropos, generate_type_lookup);
Zachary Turnerc1564272016-11-16 21:15:24 +0000931 result.AppendError(error_msg_stream.GetString());
Zachary Turner11eb9c62016-10-05 20:03:37 +0000932 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000933 return false;
Zachary Turner11eb9c62016-10-05 20:03:37 +0000934 }
935
Zachary Turner4574a892016-12-08 01:31:04 +0000936 if (!m_interpreter.RemoveCommand(command_name)) {
937 result.AppendErrorWithFormat(
938 "'%s' is a permanent debugger command and cannot be removed.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000939 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000940 result.SetStatus(eReturnStatusFailed);
941 return false;
942 }
943
944 result.SetStatus(eReturnStatusSuccessFinishNoResult);
945 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000946 }
Greg Claytonb5472782015-01-09 19:08:20 +0000947};
948
Greg Claytonde164aa2011-04-20 16:37:46 +0000949//-------------------------------------------------------------------------
950// CommandObjectCommandsAddRegex
951//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000952
953static OptionDefinition g_regex_options[] = {
954 // clang-format off
955 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
956 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
957 // clang-format on
958};
959
Jim Ingham5a988412012-06-08 21:56:10 +0000960#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +0000961
Kate Stoneb9c1b512016-09-06 20:57:50 +0000962class CommandObjectCommandsAddRegex : public CommandObjectParsed,
963 public IOHandlerDelegateMultiline {
Greg Claytonde164aa2011-04-20 16:37:46 +0000964public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000965 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
966 : CommandObjectParsed(
967 interpreter, "command regex", "Define a custom command in terms of "
968 "existing commands by matching "
969 "regular expressions.",
970 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
971 IOHandlerDelegateMultiline("",
972 IOHandlerDelegate::Completion::LLDBCommand),
973 m_options() {
974 SetHelpLong(
975 R"(
976)"
977 "This command allows the user to create powerful regular expression commands \
Kate Stoneea671fb2015-07-14 05:48:36 +0000978with substitutions. The regular expressions and substitutions are specified \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000979using the regular expression substitution format of:"
980 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000981
982 s/<regex>/<subst>/
983
Kate Stoneb9c1b512016-09-06 20:57:50 +0000984)"
985 "<regex> is a regular expression that can use parenthesis to capture regular \
Kate Stoneea671fb2015-07-14 05:48:36 +0000986expression input and substitute the captured matches in the output using %1 \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000987for the first match, %2 for the second, and so on."
988 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000989
Kate Stoneb9c1b512016-09-06 20:57:50 +0000990)"
991 "The regular expressions can all be specified on the command line if more than \
Kate Stoneea671fb2015-07-14 05:48:36 +0000992one argument is provided. If just the command name is provided on the command \
993line, then the regular expressions and substitutions can be entered on separate \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000994lines, followed by an empty line to terminate the command definition."
995 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000996
997EXAMPLES
998
Kate Stoneb9c1b512016-09-06 20:57:50 +0000999)"
1000 "The following example will define a regular expression command named 'f' that \
Kate Stoneea671fb2015-07-14 05:48:36 +00001001will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001002a number follows 'f':"
1003 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001004
Kate Stoneb9c1b512016-09-06 20:57:50 +00001005 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1006 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001007
Kate Stoneb9c1b512016-09-06 20:57:50 +00001008 ~CommandObjectCommandsAddRegex() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001009
Jim Ingham5a988412012-06-08 21:56:10 +00001010protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011 void IOHandlerActivated(IOHandler &io_handler) override {
1012 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1013 if (output_sp) {
1014 output_sp->PutCString("Enter one of more sed substitution commands in "
1015 "the form: 's/<regex>/<subst>/'.\nTerminate the "
1016 "substitution list with an empty line.\n");
1017 output_sp->Flush();
1018 }
1019 }
1020
1021 void IOHandlerInputComplete(IOHandler &io_handler,
1022 std::string &data) override {
1023 io_handler.SetIsDone(true);
1024 if (m_regex_cmd_ap) {
1025 StringList lines;
1026 if (lines.SplitIntoLines(data)) {
1027 const size_t num_lines = lines.GetSize();
1028 bool check_only = false;
1029 for (size_t i = 0; i < num_lines; ++i) {
1030 llvm::StringRef bytes_strref(lines[i]);
Zachary Turner97206d52017-05-12 04:51:55 +00001031 Status error = AppendRegexSubstitution(bytes_strref, check_only);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001032 if (error.Fail()) {
1033 if (!m_interpreter.GetDebugger()
1034 .GetCommandInterpreter()
1035 .GetBatchCommandMode()) {
1036 StreamSP out_stream =
1037 m_interpreter.GetDebugger().GetAsyncOutputStream();
1038 out_stream->Printf("error: %s\n", error.AsCString());
1039 }
1040 }
Greg Clayton44d93782014-01-27 23:43:24 +00001041 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001042 }
1043 if (m_regex_cmd_ap->HasRegexEntries()) {
1044 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1045 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1046 }
1047 }
1048 }
1049
1050 bool DoExecute(Args &command, CommandReturnObject &result) override {
1051 const size_t argc = command.GetArgumentCount();
1052 if (argc == 0) {
1053 result.AppendError("usage: 'command regex <command-name> "
1054 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1055 result.SetStatus(eReturnStatusFailed);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001056 return false;
1057 }
1058
Zachary Turner97206d52017-05-12 04:51:55 +00001059 Status error;
Zachary Turner4574a892016-12-08 01:31:04 +00001060 auto name = command[0].ref;
1061 m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>(
1062 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
1063 true);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001064
1065 if (argc == 1) {
1066 Debugger &debugger = m_interpreter.GetDebugger();
1067 bool color_prompt = debugger.GetUseColor();
1068 const bool multiple_lines = true; // Get multiple lines
1069 IOHandlerSP io_handler_sp(new IOHandlerEditline(
1070 debugger, IOHandler::Type::Other,
1071 "lldb-regex", // Name of input reader for history
1072 llvm::StringRef("> "), // Prompt
1073 llvm::StringRef(), // Continuation prompt
1074 multiple_lines, color_prompt,
1075 0, // Don't show line numbers
1076 *this));
1077
1078 if (io_handler_sp) {
1079 debugger.PushIOHandler(io_handler_sp);
1080 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1081 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001082 } else {
Zachary Turner97d2c402016-10-05 23:40:23 +00001083 for (auto &entry : command.entries().drop_front()) {
Zachary Turner11eb9c62016-10-05 20:03:37 +00001084 bool check_only = false;
Zachary Turner97d2c402016-10-05 23:40:23 +00001085 error = AppendRegexSubstitution(entry.ref, check_only);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001086 if (error.Fail())
1087 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001088 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001089
1090 if (error.Success()) {
1091 AddRegexCommandToInterpreter();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001092 }
Greg Clayton44d93782014-01-27 23:43:24 +00001093 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001094 if (error.Fail()) {
1095 result.AppendError(error.AsCString());
1096 result.SetStatus(eReturnStatusFailed);
1097 }
Greg Clayton44d93782014-01-27 23:43:24 +00001098
Kate Stoneb9c1b512016-09-06 20:57:50 +00001099 return result.Succeeded();
1100 }
1101
Zachary Turner97206d52017-05-12 04:51:55 +00001102 Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1103 bool check_only) {
1104 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001105
1106 if (!m_regex_cmd_ap) {
1107 error.SetErrorStringWithFormat(
1108 "invalid regular expression command object for: '%.*s'",
1109 (int)regex_sed.size(), regex_sed.data());
1110 return error;
Greg Clayton44d93782014-01-27 23:43:24 +00001111 }
Greg Clayton44d93782014-01-27 23:43:24 +00001112
Kate Stoneb9c1b512016-09-06 20:57:50 +00001113 size_t regex_sed_size = regex_sed.size();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001114
Kate Stoneb9c1b512016-09-06 20:57:50 +00001115 if (regex_sed_size <= 1) {
1116 error.SetErrorStringWithFormat(
1117 "regular expression substitution string is too short: '%.*s'",
1118 (int)regex_sed.size(), regex_sed.data());
1119 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001120 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001121
Kate Stoneb9c1b512016-09-06 20:57:50 +00001122 if (regex_sed[0] != 's') {
1123 error.SetErrorStringWithFormat("regular expression substitution string "
1124 "doesn't start with 's': '%.*s'",
1125 (int)regex_sed.size(), regex_sed.data());
1126 return error;
1127 }
1128 const size_t first_separator_char_pos = 1;
Adrian Prantl05097242018-04-30 16:49:04 +00001129 // use the char that follows 's' as the regex separator character so we can
1130 // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001131 const char separator_char = regex_sed[first_separator_char_pos];
1132 const size_t second_separator_char_pos =
1133 regex_sed.find(separator_char, first_separator_char_pos + 1);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001134
Kate Stoneb9c1b512016-09-06 20:57:50 +00001135 if (second_separator_char_pos == std::string::npos) {
1136 error.SetErrorStringWithFormat(
1137 "missing second '%c' separator char after '%.*s' in '%.*s'",
1138 separator_char,
1139 (int)(regex_sed.size() - first_separator_char_pos - 1),
1140 regex_sed.data() + (first_separator_char_pos + 1),
1141 (int)regex_sed.size(), regex_sed.data());
1142 return error;
1143 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001144
Kate Stoneb9c1b512016-09-06 20:57:50 +00001145 const size_t third_separator_char_pos =
1146 regex_sed.find(separator_char, second_separator_char_pos + 1);
Greg Clayton44d93782014-01-27 23:43:24 +00001147
Kate Stoneb9c1b512016-09-06 20:57:50 +00001148 if (third_separator_char_pos == std::string::npos) {
1149 error.SetErrorStringWithFormat(
1150 "missing third '%c' separator char after '%.*s' in '%.*s'",
1151 separator_char,
1152 (int)(regex_sed.size() - second_separator_char_pos - 1),
1153 regex_sed.data() + (second_separator_char_pos + 1),
1154 (int)regex_sed.size(), regex_sed.data());
1155 return error;
1156 }
1157
1158 if (third_separator_char_pos != regex_sed_size - 1) {
Adrian Prantl05097242018-04-30 16:49:04 +00001159 // Make sure that everything that follows the last regex separator char
Kate Stoneb9c1b512016-09-06 20:57:50 +00001160 if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1161 third_separator_char_pos + 1) !=
1162 std::string::npos) {
1163 error.SetErrorStringWithFormat(
1164 "extra data found after the '%.*s' regular expression substitution "
1165 "string: '%.*s'",
1166 (int)third_separator_char_pos + 1, regex_sed.data(),
1167 (int)(regex_sed.size() - third_separator_char_pos - 1),
1168 regex_sed.data() + (third_separator_char_pos + 1));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001169 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001170 }
1171 } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1172 error.SetErrorStringWithFormat(
1173 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1174 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1175 regex_sed.data());
1176 return error;
1177 } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1178 error.SetErrorStringWithFormat(
1179 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1180 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1181 regex_sed.data());
1182 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001183 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001184
1185 if (!check_only) {
1186 std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1187 second_separator_char_pos -
1188 first_separator_char_pos - 1));
1189 std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1190 third_separator_char_pos -
1191 second_separator_char_pos - 1));
1192 m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001193 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194 return error;
1195 }
1196
1197 void AddRegexCommandToInterpreter() {
1198 if (m_regex_cmd_ap) {
1199 if (m_regex_cmd_ap->HasRegexEntries()) {
1200 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1201 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1202 }
1203 }
1204 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001205
Greg Claytonde164aa2011-04-20 16:37:46 +00001206private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001207 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001208
Kate Stoneb9c1b512016-09-06 20:57:50 +00001209 class CommandOptions : public Options {
1210 public:
1211 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001212
Kate Stoneb9c1b512016-09-06 20:57:50 +00001213 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001214
Zachary Turner97206d52017-05-12 04:51:55 +00001215 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1216 ExecutionContext *execution_context) override {
1217 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001218 const int short_option = m_getopt_table[option_idx].val;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001219
Kate Stoneb9c1b512016-09-06 20:57:50 +00001220 switch (short_option) {
1221 case 'h':
1222 m_help.assign(option_arg);
1223 break;
1224 case 's':
1225 m_syntax.assign(option_arg);
1226 break;
1227 default:
1228 error.SetErrorStringWithFormat("unrecognized option '%c'",
1229 short_option);
1230 break;
1231 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001232
Kate Stoneb9c1b512016-09-06 20:57:50 +00001233 return error;
1234 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001235
Kate Stoneb9c1b512016-09-06 20:57:50 +00001236 void OptionParsingStarting(ExecutionContext *execution_context) override {
1237 m_help.clear();
1238 m_syntax.clear();
1239 }
1240
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001241 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001242 return llvm::makeArrayRef(g_regex_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001243 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001244
Zachary Turner11eb9c62016-10-05 20:03:37 +00001245 // TODO: Convert these functions to return StringRefs.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001246 const char *GetHelp() {
1247 return (m_help.empty() ? nullptr : m_help.c_str());
1248 }
1249
1250 const char *GetSyntax() {
1251 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1252 }
1253
1254 protected:
1255 // Instance variables to hold the values for command options.
1256
1257 std::string m_help;
1258 std::string m_syntax;
1259 };
1260
1261 Options *GetOptions() override { return &m_options; }
1262
1263 CommandOptions m_options;
Greg Claytonde164aa2011-04-20 16:37:46 +00001264};
1265
Kate Stoneb9c1b512016-09-06 20:57:50 +00001266class CommandObjectPythonFunction : public CommandObjectRaw {
Enrico Granata223383e2011-08-16 23:24:13 +00001267public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001268 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1269 std::string funct, std::string help,
1270 ScriptedCommandSynchronicity synch)
Zachary Turnera4496982016-10-05 21:14:38 +00001271 : CommandObjectRaw(interpreter, name),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001272 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1273 if (!help.empty())
Zachary Turner442f6532016-11-12 20:41:02 +00001274 SetHelp(help);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001275 else {
1276 StreamString stream;
1277 stream.Printf("For more information run 'help %s'", name.c_str());
Zachary Turnerc1564272016-11-16 21:15:24 +00001278 SetHelp(stream.GetString());
Enrico Granata223383e2011-08-16 23:24:13 +00001279 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001280 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001281
Kate Stoneb9c1b512016-09-06 20:57:50 +00001282 ~CommandObjectPythonFunction() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001283
Kate Stoneb9c1b512016-09-06 20:57:50 +00001284 bool IsRemovable() const override { return true; }
Jim Ingham5a988412012-06-08 21:56:10 +00001285
Kate Stoneb9c1b512016-09-06 20:57:50 +00001286 const std::string &GetFunctionName() { return m_function_name; }
Jim Ingham5a988412012-06-08 21:56:10 +00001287
Kate Stoneb9c1b512016-09-06 20:57:50 +00001288 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1289
Zachary Turner442f6532016-11-12 20:41:02 +00001290 llvm::StringRef GetHelpLong() override {
1291 if (m_fetched_help_long)
1292 return CommandObjectRaw::GetHelpLong();
1293
1294 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1295 if (!scripter)
1296 return CommandObjectRaw::GetHelpLong();
1297
1298 std::string docstring;
1299 m_fetched_help_long =
1300 scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1301 if (!docstring.empty())
1302 SetHelpLong(docstring);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001303 return CommandObjectRaw::GetHelpLong();
1304 }
1305
Jim Ingham5a988412012-06-08 21:56:10 +00001306protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001307 bool DoExecute(const char *raw_command_line,
1308 CommandReturnObject &result) override {
1309 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1310
Zachary Turner97206d52017-05-12 04:51:55 +00001311 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001312
1313 result.SetStatus(eReturnStatusInvalid);
1314
1315 if (!scripter ||
1316 !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1317 raw_command_line, m_synchro, result,
1318 error, m_exe_ctx)) {
1319 result.AppendError(error.AsCString());
1320 result.SetStatus(eReturnStatusFailed);
1321 } else {
1322 // Don't change the status if the command already set it...
1323 if (result.GetStatus() == eReturnStatusInvalid) {
Zachary Turnerc1564272016-11-16 21:15:24 +00001324 if (result.GetOutputData().empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001325 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata223383e2011-08-16 23:24:13 +00001326 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001327 result.SetStatus(eReturnStatusSuccessFinishResult);
1328 }
Enrico Granata223383e2011-08-16 23:24:13 +00001329 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001330
Kate Stoneb9c1b512016-09-06 20:57:50 +00001331 return result.Succeeded();
1332 }
1333
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001334private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001335 std::string m_function_name;
1336 ScriptedCommandSynchronicity m_synchro;
1337 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001338};
1339
Kate Stoneb9c1b512016-09-06 20:57:50 +00001340class CommandObjectScriptingObject : public CommandObjectRaw {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001341public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001342 CommandObjectScriptingObject(CommandInterpreter &interpreter,
1343 std::string name,
1344 StructuredData::GenericSP cmd_obj_sp,
1345 ScriptedCommandSynchronicity synch)
Zachary Turnera4496982016-10-05 21:14:38 +00001346 : CommandObjectRaw(interpreter, name),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001347 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1348 m_fetched_help_long(false) {
1349 StreamString stream;
1350 stream.Printf("For more information run 'help %s'", name.c_str());
Zachary Turnerc1564272016-11-16 21:15:24 +00001351 SetHelp(stream.GetString());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001352 if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1353 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1354 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001355
Kate Stoneb9c1b512016-09-06 20:57:50 +00001356 ~CommandObjectScriptingObject() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001357
Kate Stoneb9c1b512016-09-06 20:57:50 +00001358 bool IsRemovable() const override { return true; }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001359
Kate Stoneb9c1b512016-09-06 20:57:50 +00001360 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1361
1362 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1363
Zachary Turner442f6532016-11-12 20:41:02 +00001364 llvm::StringRef GetHelp() override {
1365 if (m_fetched_help_short)
1366 return CommandObjectRaw::GetHelp();
1367 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1368 if (!scripter)
1369 return CommandObjectRaw::GetHelp();
1370 std::string docstring;
1371 m_fetched_help_short =
1372 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1373 if (!docstring.empty())
1374 SetHelp(docstring);
1375
Kate Stoneb9c1b512016-09-06 20:57:50 +00001376 return CommandObjectRaw::GetHelp();
1377 }
1378
Zachary Turner442f6532016-11-12 20:41:02 +00001379 llvm::StringRef GetHelpLong() override {
1380 if (m_fetched_help_long)
1381 return CommandObjectRaw::GetHelpLong();
1382
1383 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1384 if (!scripter)
1385 return CommandObjectRaw::GetHelpLong();
1386
1387 std::string docstring;
1388 m_fetched_help_long =
1389 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1390 if (!docstring.empty())
1391 SetHelpLong(docstring);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001392 return CommandObjectRaw::GetHelpLong();
1393 }
1394
Enrico Granata9fe00e52015-03-13 02:20:41 +00001395protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001396 bool DoExecute(const char *raw_command_line,
1397 CommandReturnObject &result) override {
1398 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1399
Zachary Turner97206d52017-05-12 04:51:55 +00001400 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001401
1402 result.SetStatus(eReturnStatusInvalid);
1403
1404 if (!scripter ||
1405 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1406 m_synchro, result, error, m_exe_ctx)) {
1407 result.AppendError(error.AsCString());
1408 result.SetStatus(eReturnStatusFailed);
1409 } else {
1410 // Don't change the status if the command already set it...
1411 if (result.GetStatus() == eReturnStatusInvalid) {
Zachary Turnerc1564272016-11-16 21:15:24 +00001412 if (result.GetOutputData().empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001413 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata9fe00e52015-03-13 02:20:41 +00001414 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001415 result.SetStatus(eReturnStatusSuccessFinishResult);
1416 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001417 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001418
Kate Stoneb9c1b512016-09-06 20:57:50 +00001419 return result.Succeeded();
1420 }
1421
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001422private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001423 StructuredData::GenericSP m_cmd_obj_sp;
1424 ScriptedCommandSynchronicity m_synchro;
1425 bool m_fetched_help_short : 1;
1426 bool m_fetched_help_long : 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001427};
1428
Enrico Granataa9dbf432011-10-17 21:45:27 +00001429//-------------------------------------------------------------------------
1430// CommandObjectCommandsScriptImport
1431//-------------------------------------------------------------------------
1432
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001433OptionDefinition g_script_import_options[] = {
1434 // clang-format off
1435 { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." },
1436 // clang-format on
1437};
1438
Kate Stoneb9c1b512016-09-06 20:57:50 +00001439class CommandObjectCommandsScriptImport : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001440public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001441 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1442 : CommandObjectParsed(interpreter, "command script import",
1443 "Import a scripting module in LLDB.", nullptr),
1444 m_options() {
1445 CommandArgumentEntry arg1;
1446 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001447
Kate Stoneb9c1b512016-09-06 20:57:50 +00001448 // Define the first (and only) variant of this arg.
1449 cmd_arg.arg_type = eArgTypeFilename;
1450 cmd_arg.arg_repetition = eArgRepeatPlus;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001451
Kate Stoneb9c1b512016-09-06 20:57:50 +00001452 // There is only one variant this argument could be; put it into the
1453 // argument entry.
1454 arg1.push_back(cmd_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +00001455
Kate Stoneb9c1b512016-09-06 20:57:50 +00001456 // Push the data for the first argument into the m_arguments vector.
1457 m_arguments.push_back(arg1);
1458 }
1459
1460 ~CommandObjectCommandsScriptImport() override = default;
1461
Raphael Isemann2443bbd2018-07-02 21:29:56 +00001462 int HandleArgumentCompletion(
1463 CompletionRequest &request,
1464 OptionElementVector &opt_element_vector) override {
1465 llvm::StringRef completion_str =
1466 request.GetParsedLine()[request.GetCursorIndex()].ref;
1467 completion_str = completion_str.take_front(request.GetCursorCharPosition());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001468
Raphael Isemann2443bbd2018-07-02 21:29:56 +00001469 bool word_complete = request.GetWordComplete();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001470 CommandCompletions::InvokeCommonCompletionCallbacks(
1471 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
Raphael Isemann2443bbd2018-07-02 21:29:56 +00001472 completion_str, request.GetMatchStartPoint(),
1473 request.GetMaxReturnElements(), nullptr, word_complete,
1474 request.GetMatches());
1475 request.SetWordComplete(word_complete);
1476 return request.GetMatches().GetSize();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001477 }
1478
1479 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +00001480
1481protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001482 class CommandOptions : public Options {
1483 public:
1484 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001485
Kate Stoneb9c1b512016-09-06 20:57:50 +00001486 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001487
Zachary Turner97206d52017-05-12 04:51:55 +00001488 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1489 ExecutionContext *execution_context) override {
1490 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001491 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001492
Kate Stoneb9c1b512016-09-06 20:57:50 +00001493 switch (short_option) {
1494 case 'r':
1495 m_allow_reload = true;
1496 break;
1497 default:
1498 error.SetErrorStringWithFormat("unrecognized option '%c'",
1499 short_option);
1500 break;
1501 }
1502
1503 return error;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001504 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001505
1506 void OptionParsingStarting(ExecutionContext *execution_context) override {
1507 m_allow_reload = true;
1508 }
1509
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001510 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001511 return llvm::makeArrayRef(g_script_import_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001512 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001513
1514 // Instance variables to hold the values for command options.
1515
1516 bool m_allow_reload;
1517 };
1518
1519 bool DoExecute(Args &command, CommandReturnObject &result) override {
1520 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1521 lldb::eScriptLanguagePython) {
1522 result.AppendError("only scripting language supported for module "
1523 "importing is currently Python");
1524 result.SetStatus(eReturnStatusFailed);
1525 return false;
1526 }
1527
Zachary Turner11eb9c62016-10-05 20:03:37 +00001528 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001529 result.AppendError("command script import needs one or more arguments");
1530 result.SetStatus(eReturnStatusFailed);
1531 return false;
1532 }
1533
Zachary Turner11eb9c62016-10-05 20:03:37 +00001534 for (auto &entry : command.entries()) {
Zachary Turner97206d52017-05-12 04:51:55 +00001535 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001536
1537 const bool init_session = true;
1538 // FIXME: this is necessary because CommandObject::CheckRequirements()
Zachary Turner11eb9c62016-10-05 20:03:37 +00001539 // assumes that commands won't ever be recursively invoked, but it's
1540 // actually possible to craft a Python script that does other "command
Adrian Prantl05097242018-04-30 16:49:04 +00001541 // script imports" in __lldb_init_module the real fix is to have
1542 // recursive commands possible with a CommandInvocation object separate
1543 // from the CommandObject itself, so that recursive command invocations
1544 // won't stomp on each other (wrt to execution contents, options, and
1545 // more)
Kate Stoneb9c1b512016-09-06 20:57:50 +00001546 m_exe_ctx.Clear();
1547 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
Zachary Turner11eb9c62016-10-05 20:03:37 +00001548 entry.c_str(), m_options.m_allow_reload, init_session, error)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001549 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1550 } else {
1551 result.AppendErrorWithFormat("module importing failed: %s",
1552 error.AsCString());
1553 result.SetStatus(eReturnStatusFailed);
1554 }
1555 }
1556
1557 return result.Succeeded();
1558 }
1559
1560 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001561};
Enrico Granata223383e2011-08-16 23:24:13 +00001562
1563//-------------------------------------------------------------------------
1564// CommandObjectCommandsScriptAdd
1565//-------------------------------------------------------------------------
1566
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001567static OptionEnumValueElement g_script_synchro_type[] = {
1568 {eScriptedCommandSynchronicitySynchronous, "synchronous",
1569 "Run synchronous"},
1570 {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1571 "Run asynchronous"},
1572 {eScriptedCommandSynchronicityCurrentValue, "current",
1573 "Do not alter current setting"},
1574 {0, nullptr, nullptr}};
1575
1576static OptionDefinition g_script_add_options[] = {
1577 // clang-format off
1578 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
1579 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
1580 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." },
1581 { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." },
1582 // clang-format on
1583};
1584
Kate Stoneb9c1b512016-09-06 20:57:50 +00001585class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1586 public IOHandlerDelegateMultiline {
Jim Ingham5a988412012-06-08 21:56:10 +00001587public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001588 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1589 : CommandObjectParsed(interpreter, "command script add",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001590 "Add a scripted function as an LLDB command.",
1591 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001592 IOHandlerDelegateMultiline("DONE"), m_options() {
1593 CommandArgumentEntry arg1;
1594 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001595
Kate Stoneb9c1b512016-09-06 20:57:50 +00001596 // Define the first (and only) variant of this arg.
1597 cmd_arg.arg_type = eArgTypeCommandName;
1598 cmd_arg.arg_repetition = eArgRepeatPlain;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001599
Kate Stoneb9c1b512016-09-06 20:57:50 +00001600 // There is only one variant this argument could be; put it into the
1601 // argument entry.
1602 arg1.push_back(cmd_arg);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001603
Kate Stoneb9c1b512016-09-06 20:57:50 +00001604 // Push the data for the first argument into the m_arguments vector.
1605 m_arguments.push_back(arg1);
1606 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001607
Kate Stoneb9c1b512016-09-06 20:57:50 +00001608 ~CommandObjectCommandsScriptAdd() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001609
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610 Options *GetOptions() override { return &m_options; }
Greg Clayton44d93782014-01-27 23:43:24 +00001611
Jim Ingham5a988412012-06-08 21:56:10 +00001612protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001613 class CommandOptions : public Options {
1614 public:
1615 CommandOptions()
1616 : Options(), m_class_name(), m_funct_name(), m_short_help(),
1617 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
Enrico Granata223383e2011-08-16 23:24:13 +00001618
Kate Stoneb9c1b512016-09-06 20:57:50 +00001619 ~CommandOptions() override = default;
1620
Zachary Turner97206d52017-05-12 04:51:55 +00001621 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1622 ExecutionContext *execution_context) override {
1623 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001624 const int short_option = m_getopt_table[option_idx].val;
1625
1626 switch (short_option) {
1627 case 'f':
Zachary Turnerfe114832016-11-12 16:56:47 +00001628 if (!option_arg.empty())
1629 m_funct_name = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001630 break;
1631 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +00001632 if (!option_arg.empty())
1633 m_class_name = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001634 break;
1635 case 'h':
Zachary Turnerfe114832016-11-12 16:56:47 +00001636 if (!option_arg.empty())
1637 m_short_help = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001638 break;
1639 case 's':
1640 m_synchronicity =
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001641 (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
Zachary Turnerfe114832016-11-12 16:56:47 +00001642 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001643 if (!error.Success())
1644 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001645 "unrecognized value for synchronicity '%s'",
1646 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001647 break;
1648 default:
1649 error.SetErrorStringWithFormat("unrecognized option '%c'",
1650 short_option);
1651 break;
1652 }
1653
1654 return error;
Enrico Granata223383e2011-08-16 23:24:13 +00001655 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001656
1657 void OptionParsingStarting(ExecutionContext *execution_context) override {
1658 m_class_name.clear();
1659 m_funct_name.clear();
1660 m_short_help.clear();
1661 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1662 }
1663
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001664 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001665 return llvm::makeArrayRef(g_script_add_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001666 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001667
1668 // Instance variables to hold the values for command options.
1669
1670 std::string m_class_name;
1671 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001672 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001673 ScriptedCommandSynchronicity m_synchronicity;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001674 };
1675
1676 void IOHandlerActivated(IOHandler &io_handler) override {
1677 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1678 if (output_sp) {
1679 output_sp->PutCString(g_python_command_instructions);
1680 output_sp->Flush();
1681 }
1682 }
1683
1684 void IOHandlerInputComplete(IOHandler &io_handler,
1685 std::string &data) override {
1686 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1687
1688 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1689 if (interpreter) {
1690
1691 StringList lines;
1692 lines.SplitIntoLines(data);
1693 if (lines.GetSize() > 0) {
1694 std::string funct_name_str;
1695 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1696 if (funct_name_str.empty()) {
1697 error_sp->Printf("error: unable to obtain a function name, didn't "
1698 "add python command.\n");
1699 error_sp->Flush();
1700 } else {
1701 // everything should be fine now, let's add this alias
1702
1703 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00001704 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001705 m_synchronicity));
1706
1707 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1708 true)) {
1709 error_sp->Printf("error: unable to add selected command, didn't "
1710 "add python command.\n");
1711 error_sp->Flush();
1712 }
1713 }
1714 } else {
1715 error_sp->Printf(
1716 "error: unable to create function, didn't add python command.\n");
1717 error_sp->Flush();
1718 }
1719 } else {
1720 error_sp->Printf("error: empty function, didn't add python command.\n");
1721 error_sp->Flush();
1722 }
1723 } else {
1724 error_sp->Printf(
1725 "error: script interpreter missing, didn't add python command.\n");
1726 error_sp->Flush();
1727 }
1728
1729 io_handler.SetIsDone(true);
1730 }
1731
1732protected:
1733 bool DoExecute(Args &command, CommandReturnObject &result) override {
1734 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1735 lldb::eScriptLanguagePython) {
1736 result.AppendError("only scripting language supported for scripted "
1737 "commands is currently Python");
1738 result.SetStatus(eReturnStatusFailed);
1739 return false;
1740 }
1741
Zachary Turner11eb9c62016-10-05 20:03:37 +00001742 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001743 result.AppendError("'command script add' requires one argument");
1744 result.SetStatus(eReturnStatusFailed);
1745 return false;
1746 }
1747
1748 // Store the options in case we get multi-line input
Zachary Turner4574a892016-12-08 01:31:04 +00001749 m_cmd_name = command[0].ref;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001750 m_short_help.assign(m_options.m_short_help);
1751 m_synchronicity = m_options.m_synchronicity;
1752
1753 if (m_options.m_class_name.empty()) {
1754 if (m_options.m_funct_name.empty()) {
1755 m_interpreter.GetPythonCommandsFromIOHandler(
1756 " ", // Prompt
1757 *this, // IOHandlerDelegate
1758 true, // Run IOHandler in async mode
1759 nullptr); // Baton for the "io_handler" that will be passed back
1760 // into our IOHandlerDelegate functions
1761 } else {
1762 CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1763 m_interpreter, m_cmd_name, m_options.m_funct_name,
1764 m_options.m_short_help, m_synchronicity));
1765 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1766 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1767 } else {
1768 result.AppendError("cannot add command");
1769 result.SetStatus(eReturnStatusFailed);
1770 }
1771 }
1772 } else {
1773 ScriptInterpreter *interpreter =
1774 GetCommandInterpreter().GetScriptInterpreter();
1775 if (!interpreter) {
1776 result.AppendError("cannot find ScriptInterpreter");
1777 result.SetStatus(eReturnStatusFailed);
1778 return false;
1779 }
1780
1781 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1782 m_options.m_class_name.c_str());
1783 if (!cmd_obj_sp) {
1784 result.AppendError("cannot create helper object");
1785 result.SetStatus(eReturnStatusFailed);
1786 return false;
1787 }
1788
1789 CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1790 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1791 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1792 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1793 } else {
1794 result.AppendError("cannot add command");
1795 result.SetStatus(eReturnStatusFailed);
1796 }
1797 }
1798
1799 return result.Succeeded();
1800 }
1801
1802 CommandOptions m_options;
1803 std::string m_cmd_name;
1804 std::string m_short_help;
1805 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001806};
1807
Enrico Granata223383e2011-08-16 23:24:13 +00001808//-------------------------------------------------------------------------
1809// CommandObjectCommandsScriptList
1810//-------------------------------------------------------------------------
1811
Kate Stoneb9c1b512016-09-06 20:57:50 +00001812class CommandObjectCommandsScriptList : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001813public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001814 CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1815 : CommandObjectParsed(interpreter, "command script list",
1816 "List defined scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001817
Kate Stoneb9c1b512016-09-06 20:57:50 +00001818 ~CommandObjectCommandsScriptList() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001819
Kate Stoneb9c1b512016-09-06 20:57:50 +00001820 bool DoExecute(Args &command, CommandReturnObject &result) override {
1821 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1822
1823 result.SetStatus(eReturnStatusSuccessFinishResult);
1824
1825 return true;
1826 }
Enrico Granata223383e2011-08-16 23:24:13 +00001827};
1828
1829//-------------------------------------------------------------------------
1830// CommandObjectCommandsScriptClear
1831//-------------------------------------------------------------------------
1832
Kate Stoneb9c1b512016-09-06 20:57:50 +00001833class CommandObjectCommandsScriptClear : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001834public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001835 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1836 : CommandObjectParsed(interpreter, "command script clear",
1837 "Delete all scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001838
Kate Stoneb9c1b512016-09-06 20:57:50 +00001839 ~CommandObjectCommandsScriptClear() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001840
Jim Ingham5a988412012-06-08 21:56:10 +00001841protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001842 bool DoExecute(Args &command, CommandReturnObject &result) override {
1843 m_interpreter.RemoveAllUser();
1844
1845 result.SetStatus(eReturnStatusSuccessFinishResult);
1846
1847 return true;
1848 }
Enrico Granata223383e2011-08-16 23:24:13 +00001849};
1850
1851//-------------------------------------------------------------------------
1852// CommandObjectCommandsScriptDelete
1853//-------------------------------------------------------------------------
1854
Kate Stoneb9c1b512016-09-06 20:57:50 +00001855class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001856public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001857 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1858 : CommandObjectParsed(interpreter, "command script delete",
1859 "Delete a scripted command.", nullptr) {
1860 CommandArgumentEntry arg1;
1861 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001862
Kate Stoneb9c1b512016-09-06 20:57:50 +00001863 // Define the first (and only) variant of this arg.
1864 cmd_arg.arg_type = eArgTypeCommandName;
1865 cmd_arg.arg_repetition = eArgRepeatPlain;
1866
1867 // There is only one variant this argument could be; put it into the
1868 // argument entry.
1869 arg1.push_back(cmd_arg);
1870
1871 // Push the data for the first argument into the m_arguments vector.
1872 m_arguments.push_back(arg1);
1873 }
1874
1875 ~CommandObjectCommandsScriptDelete() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001876
Jim Ingham5a988412012-06-08 21:56:10 +00001877protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001878 bool DoExecute(Args &command, CommandReturnObject &result) override {
1879
Zachary Turner11eb9c62016-10-05 20:03:37 +00001880 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001881 result.AppendError("'command script delete' requires one argument");
1882 result.SetStatus(eReturnStatusFailed);
1883 return false;
Enrico Granata223383e2011-08-16 23:24:13 +00001884 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001885
Zachary Turner4574a892016-12-08 01:31:04 +00001886 auto cmd_name = command[0].ref;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001887
Zachary Turner4574a892016-12-08 01:31:04 +00001888 if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1889 !m_interpreter.UserCommandExists(cmd_name)) {
Zachary Turner867e7d12016-12-09 01:20:58 +00001890 result.AppendErrorWithFormat("command %s not found", command[0].c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001891 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +00001892 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001893 }
1894
Zachary Turner4574a892016-12-08 01:31:04 +00001895 m_interpreter.RemoveUser(cmd_name);
1896 result.SetStatus(eReturnStatusSuccessFinishResult);
1897 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001898 }
Enrico Granata223383e2011-08-16 23:24:13 +00001899};
1900
1901#pragma mark CommandObjectMultiwordCommandsScript
1902
1903//-------------------------------------------------------------------------
1904// CommandObjectMultiwordCommandsScript
1905//-------------------------------------------------------------------------
1906
Kate Stoneb9c1b512016-09-06 20:57:50 +00001907class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
Enrico Granata223383e2011-08-16 23:24:13 +00001908public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001909 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1910 : CommandObjectMultiword(
1911 interpreter, "command script", "Commands for managing custom "
1912 "commands implemented by "
1913 "interpreter scripts.",
1914 "command script <subcommand> [<subcommand-options>]") {
1915 LoadSubCommand("add", CommandObjectSP(
1916 new CommandObjectCommandsScriptAdd(interpreter)));
1917 LoadSubCommand(
1918 "delete",
1919 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1920 LoadSubCommand(
1921 "clear",
1922 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1923 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1924 interpreter)));
1925 LoadSubCommand(
1926 "import",
1927 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1928 }
Enrico Granata223383e2011-08-16 23:24:13 +00001929
Kate Stoneb9c1b512016-09-06 20:57:50 +00001930 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00001931};
1932
Jim Inghamebc09c32010-07-07 03:36:20 +00001933#pragma mark CommandObjectMultiwordCommands
1934
1935//-------------------------------------------------------------------------
1936// CommandObjectMultiwordCommands
1937//-------------------------------------------------------------------------
1938
Kate Stoneb9c1b512016-09-06 20:57:50 +00001939CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1940 CommandInterpreter &interpreter)
1941 : CommandObjectMultiword(interpreter, "command",
1942 "Commands for managing custom LLDB commands.",
1943 "command <subcommand> [<subcommand-options>]") {
1944 LoadSubCommand("source",
1945 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1946 LoadSubCommand("alias",
1947 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1948 LoadSubCommand("unalias", CommandObjectSP(
1949 new CommandObjectCommandsUnalias(interpreter)));
1950 LoadSubCommand("delete",
1951 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1952 LoadSubCommand(
1953 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1954 LoadSubCommand("history", CommandObjectSP(
1955 new CommandObjectCommandsHistory(interpreter)));
1956 LoadSubCommand(
1957 "script",
1958 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00001959}
1960
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001961CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;