blob: 8aff1b6d2a6349ce76504139978bb1ba522f7899 [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"
Greg Claytonde164aa2011-04-20 16:37:46 +000021#include "lldb/Interpreter/Args.h"
Enrico Granata7594f142013-06-17 22:51:50 +000022#include "lldb/Interpreter/CommandHistory.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000023#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytonde164aa2011-04-20 16:37:46 +000024#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000025#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000026#include "lldb/Interpreter/OptionArgParser.h"
Enrico Granata012d4fc2013-06-11 01:26:35 +000027#include "lldb/Interpreter/OptionValueBoolean.h"
Enrico Granata45d0e232016-03-31 01:10:54 +000028#include "lldb/Interpreter/OptionValueString.h"
Enrico Granata7594f142013-06-17 22:51:50 +000029#include "lldb/Interpreter/OptionValueUInt64.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000030#include "lldb/Interpreter/Options.h"
Enrico Granata99f0b8f2011-08-17 01:30:04 +000031#include "lldb/Interpreter/ScriptInterpreter.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
238 int HandleArgumentCompletion(Args &input, int &cursor_index,
239 int &cursor_char_position,
240 OptionElementVector &opt_element_vector,
241 int match_start_point, int max_return_elements,
242 bool &word_complete,
243 StringList &matches) override {
Zachary Turner4574a892016-12-08 01:31:04 +0000244 auto completion_str = input[cursor_index].ref;
245 completion_str = completion_str.take_front(cursor_char_position);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000246
247 CommandCompletions::InvokeCommonCompletionCallbacks(
248 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
Zachary Turner4574a892016-12-08 01:31:04 +0000249 completion_str, match_start_point, max_return_elements, nullptr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000250 word_complete, matches);
251 return matches.GetSize();
252 }
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 {
334 // No options were set, inherit any settings from nested "command
335 // source" commands,
336 // or set to sane default settings...
337 CommandInterpreterRunOptions options;
338 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000339 }
340 return result.Succeeded();
341 }
342
343 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000344};
345
346#pragma mark CommandObjectCommandsAlias
347//-------------------------------------------------------------------------
348// CommandObjectCommandsAlias
349//-------------------------------------------------------------------------
350
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000351static OptionDefinition g_alias_options[] = {
352 // clang-format off
353 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
354 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
355 // clang-format on
356};
357
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358static const char *g_python_command_instructions =
359 "Enter your Python command(s). Type 'DONE' to end.\n"
360 "You must define a Python function with this signature:\n"
361 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000362
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363class CommandObjectCommandsAlias : public CommandObjectRaw {
Enrico Granata45d0e232016-03-31 01:10:54 +0000364protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 class CommandOptions : public OptionGroup {
366 public:
367 CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
Enrico Granata45d0e232016-03-31 01:10:54 +0000368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 ~CommandOptions() override = default;
370
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000371 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000372 return llvm::makeArrayRef(g_alias_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000373 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000374
Zachary Turner97206d52017-05-12 04:51:55 +0000375 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
376 ExecutionContext *execution_context) override {
377 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000378
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000379 const int short_option = GetDefinitions()[option_idx].short_option;
Zachary Turner8cef4b02016-09-23 17:48:13 +0000380 std::string option_str(option_value);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000381
382 switch (short_option) {
383 case 'h':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000384 m_help.SetCurrentValue(option_str);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000385 m_help.SetOptionWasSet();
386 break;
387
388 case 'H':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000389 m_long_help.SetCurrentValue(option_str);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390 m_long_help.SetOptionWasSet();
391 break;
392
393 default:
394 error.SetErrorStringWithFormat("invalid short option character '%c'",
395 short_option);
396 break;
397 }
398
399 return error;
Enrico Granata45d0e232016-03-31 01:10:54 +0000400 }
401
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402 void OptionParsingStarting(ExecutionContext *execution_context) override {
403 m_help.Clear();
404 m_long_help.Clear();
405 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000406
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407 OptionValueString m_help;
408 OptionValueString m_long_help;
409 };
410
411 OptionGroupOptions m_option_group;
412 CommandOptions m_command_options;
413
414public:
415 Options *GetOptions() override { return &m_option_group; }
416
417 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
418 : CommandObjectRaw(
419 interpreter, "command alias",
Zachary Turnera4496982016-10-05 21:14:38 +0000420 "Define a custom command in terms of an existing command."),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000421 m_option_group(), m_command_options() {
422 m_option_group.Append(&m_command_options);
423 m_option_group.Finalize();
424
425 SetHelpLong(
426 "'alias' allows the user to create a short-cut or abbreviation for long \
Kate Stoneea671fb2015-07-14 05:48:36 +0000427commands, multi-word commands, and commands that take particular options. \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428Below are some simple examples of how one might use the 'alias' command:"
429 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000430
431(lldb) command alias sc script
432
433 Creates the abbreviation 'sc' for the 'script' command.
434
435(lldb) command alias bp breakpoint
436
Kate Stoneb9c1b512016-09-06 20:57:50 +0000437)"
438 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
Kate Stoneea671fb2015-07-14 05:48:36 +0000439breakpoint commands are two-word commands, the user would still need to \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000440enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
441 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000442
443(lldb) command alias bpl breakpoint list
444
445 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
446
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447)"
448 "An alias can include some options for the command, with the values either \
Kate Stoneea671fb2015-07-14 05:48:36 +0000449filled in at the time the alias is created, or specified as positional \
450arguments, to be filled in when the alias is invoked. The following example \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451shows how to create aliases with options:"
452 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000453
454(lldb) command alias bfl breakpoint set -f %1 -l %2
455
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456)"
457 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
Kate Stoneea671fb2015-07-14 05:48:36 +0000458options already part of the alias. So if the user wants to set a breakpoint \
459by file and line without explicitly having to use the -f and -l options, the \
460user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
461for the actual arguments that will be passed when the alias command is used. \
462The number in the placeholder refers to the position/order the actual value \
463occupies when the alias is used. All the occurrences of '%1' in the alias \
464will be replaced with the first argument, all the occurrences of '%2' in the \
465alias will be replaced with the second argument, and so on. This also allows \
466actual arguments to be used multiple times within an alias (see 'process \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000467launch' example below)."
468 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000469
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470)"
471 "Note: the positional arguments must substitute as whole words in the resultant \
Kate Stoneea671fb2015-07-14 05:48:36 +0000472command, so you can't at present do something like this to append the file extension \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473\".cpp\":"
474 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000475
476(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
477
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478)"
479 "For more complex aliasing, use the \"command regex\" command instead. In the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000480'bfl' case above, the actual file value will be filled in with the first argument \
481following 'bfl' and the actual line number value will be filled in with the second \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482argument. The user would use this alias as follows:"
483 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000484
485(lldb) command alias bfl breakpoint set -f %1 -l %2
486(lldb) bfl my-file.c 137
487
488This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
489
490Another example:
491
492(lldb) command alias pltty process launch -s -o %1 -e %1
493(lldb) pltty /dev/tty0
494
495 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
496
Kate Stoneb9c1b512016-09-06 20:57:50 +0000497)"
498 "If the user always wanted to pass the same value to a particular option, the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000499alias could be defined with that value directly in the alias as a constant, \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000500rather than using a positional placeholder:"
501 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000502
503(lldb) command alias bl3 breakpoint set -f %1 -l 3
504
Kate Stoneb9c1b512016-09-06 20:57:50 +0000505 Always sets a breakpoint on line 3 of whatever file is indicated.)");
Jim Inghamebc09c32010-07-07 03:36:20 +0000506
Kate Stoneb9c1b512016-09-06 20:57:50 +0000507 CommandArgumentEntry arg1;
508 CommandArgumentEntry arg2;
509 CommandArgumentEntry arg3;
510 CommandArgumentData alias_arg;
511 CommandArgumentData cmd_arg;
512 CommandArgumentData options_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000513
Kate Stoneb9c1b512016-09-06 20:57:50 +0000514 // Define the first (and only) variant of this arg.
515 alias_arg.arg_type = eArgTypeAliasName;
516 alias_arg.arg_repetition = eArgRepeatPlain;
517
518 // There is only one variant this argument could be; put it into the
519 // argument entry.
520 arg1.push_back(alias_arg);
521
522 // Define the first (and only) variant of this arg.
523 cmd_arg.arg_type = eArgTypeCommandName;
524 cmd_arg.arg_repetition = eArgRepeatPlain;
525
526 // There is only one variant this argument could be; put it into the
527 // argument entry.
528 arg2.push_back(cmd_arg);
529
530 // Define the first (and only) variant of this arg.
531 options_arg.arg_type = eArgTypeAliasOptions;
532 options_arg.arg_repetition = eArgRepeatOptional;
533
534 // There is only one variant this argument could be; put it into the
535 // argument entry.
536 arg3.push_back(options_arg);
537
538 // Push the data for the first argument into the m_arguments vector.
539 m_arguments.push_back(arg1);
540 m_arguments.push_back(arg2);
541 m_arguments.push_back(arg3);
542 }
543
544 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000545
Jim Ingham5a988412012-06-08 21:56:10 +0000546protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000547 bool DoExecute(const char *raw_command_line,
548 CommandReturnObject &result) override {
549 if (!raw_command_line || !raw_command_line[0]) {
550 result.AppendError("'command alias' requires at least two arguments");
551 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000552 }
553
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
555 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
Caroline Ticeca90c472011-05-06 21:37:15 +0000556
Kate Stoneb9c1b512016-09-06 20:57:50 +0000557 const char *remainder = nullptr;
Enrico Granata212130a2016-03-08 05:37:15 +0000558
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559 if (raw_command_line[0] == '-') {
560 // We have some options and these options MUST end with --.
561 const char *end_options = nullptr;
562 const char *s = raw_command_line;
563 while (s && s[0]) {
564 end_options = ::strstr(s, "--");
565 if (end_options) {
566 end_options += 2; // Get past the "--"
567 if (::isspace(end_options[0])) {
568 remainder = end_options;
569 while (::isspace(*remainder))
570 ++remainder;
571 break;
572 }
573 }
574 s = end_options;
575 }
576
577 if (end_options) {
578 Args args(
579 llvm::StringRef(raw_command_line, end_options - raw_command_line));
580 if (!ParseOptions(args, result))
581 return false;
582
Zachary Turner97206d52017-05-12 04:51:55 +0000583 Status error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000584 if (error.Fail()) {
585 result.AppendError(error.AsCString());
586 result.SetStatus(eReturnStatusFailed);
587 return false;
588 }
589 }
Caroline Tice844d2302010-12-09 22:52:49 +0000590 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591 if (nullptr == remainder)
592 remainder = raw_command_line;
Jim Inghamebc09c32010-07-07 03:36:20 +0000593
Zachary Turnera01bccd2016-10-05 21:14:56 +0000594 llvm::StringRef raw_command_string(remainder);
595 Args args(raw_command_string);
Jim Inghamebc09c32010-07-07 03:36:20 +0000596
Zachary Turner11eb9c62016-10-05 20:03:37 +0000597 if (args.GetArgumentCount() < 2) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000598 result.AppendError("'command alias' requires at least two arguments");
599 result.SetStatus(eReturnStatusFailed);
600 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000601 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000602
603 // Get the alias command.
604
Zachary Turner4574a892016-12-08 01:31:04 +0000605 auto alias_command = args[0].ref;
606 if (alias_command.startswith("-")) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000607 result.AppendError("aliases starting with a dash are not supported");
608 if (alias_command == "--help" || alias_command == "--long-help") {
609 result.AppendWarning("if trying to pass options to 'command alias' add "
610 "a -- at the end of the options");
611 }
612 result.SetStatus(eReturnStatusFailed);
613 return false;
614 }
615
616 // Strip the new alias name off 'raw_command_string' (leave it on args,
617 // which gets passed to 'Execute', which
618 // does the stripping itself.
619 size_t pos = raw_command_string.find(alias_command);
620 if (pos == 0) {
621 raw_command_string = raw_command_string.substr(alias_command.size());
622 pos = raw_command_string.find_first_not_of(' ');
623 if ((pos != std::string::npos) && (pos > 0))
624 raw_command_string = raw_command_string.substr(pos);
625 } else {
626 result.AppendError("Error parsing command string. No alias created.");
627 result.SetStatus(eReturnStatusFailed);
628 return false;
629 }
630
631 // Verify that the command is alias-able.
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000632 if (m_interpreter.CommandExists(alias_command)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000633 result.AppendErrorWithFormat(
634 "'%s' is a permanent debugger command and cannot be redefined.\n",
Zachary Turner4574a892016-12-08 01:31:04 +0000635 args[0].c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000636 result.SetStatus(eReturnStatusFailed);
637 return false;
638 }
639
640 // Get CommandObject that is being aliased. The command name is read from
Zachary Turnera01bccd2016-10-05 21:14:56 +0000641 // the front of raw_command_string. raw_command_string is returned with the
642 // name of the command object stripped off the front.
643 llvm::StringRef original_raw_command_string = raw_command_string;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000644 CommandObject *cmd_obj =
645 m_interpreter.GetCommandObjectForCommand(raw_command_string);
646
647 if (!cmd_obj) {
648 result.AppendErrorWithFormat("invalid command given to 'command alias'. "
649 "'%s' does not begin with a valid command."
650 " No alias created.",
Zachary Turnera01bccd2016-10-05 21:14:56 +0000651 original_raw_command_string.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000652 result.SetStatus(eReturnStatusFailed);
653 return false;
654 } else if (!cmd_obj->WantsRawCommandString()) {
655 // Note that args was initialized with the original command, and has not
656 // been updated to this point.
657 // Therefore can we pass it to the version of Execute that does not
658 // need/expect raw input in the alias.
659 return HandleAliasingNormalCommand(args, result);
660 } else {
661 return HandleAliasingRawCommand(alias_command, raw_command_string,
662 *cmd_obj, result);
663 }
664 return result.Succeeded();
665 }
666
Zachary Turnera01bccd2016-10-05 21:14:56 +0000667 bool HandleAliasingRawCommand(llvm::StringRef alias_command,
668 llvm::StringRef raw_command_string,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000669 CommandObject &cmd_obj,
670 CommandReturnObject &result) {
671 // Verify & handle any options/arguments passed to the alias command
672
673 OptionArgVectorSP option_arg_vector_sp =
674 OptionArgVectorSP(new OptionArgVector);
675
676 if (CommandObjectSP cmd_obj_sp =
677 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
Zachary Turnera01bccd2016-10-05 21:14:56 +0000678 if (m_interpreter.AliasExists(alias_command) ||
679 m_interpreter.UserCommandExists(alias_command)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000680 result.AppendWarningWithFormat(
681 "Overwriting existing definition for '%s'.\n",
Zachary Turnera01bccd2016-10-05 21:14:56 +0000682 alias_command.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000683 }
684 if (CommandAlias *alias = m_interpreter.AddAlias(
Zachary Turnera01bccd2016-10-05 21:14:56 +0000685 alias_command, cmd_obj_sp, raw_command_string)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000686 if (m_command_options.m_help.OptionWasSet())
687 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
688 if (m_command_options.m_long_help.OptionWasSet())
689 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
690 result.SetStatus(eReturnStatusSuccessFinishNoResult);
691 } else {
692 result.AppendError("Unable to create requested alias.\n");
693 result.SetStatus(eReturnStatusFailed);
694 }
695
696 } else {
697 result.AppendError("Unable to create requested alias.\n");
698 result.SetStatus(eReturnStatusFailed);
699 }
700
701 return result.Succeeded();
702 }
703
704 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
705 size_t argc = args.GetArgumentCount();
706
707 if (argc < 2) {
708 result.AppendError("'command alias' requires at least two arguments");
709 result.SetStatus(eReturnStatusFailed);
710 return false;
711 }
712
Zachary Turner4574a892016-12-08 01:31:04 +0000713 // Save these in std::strings since we're going to shift them off.
714 const std::string alias_command(args[0].ref);
715 const std::string actual_command(args[1].ref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000716
717 args.Shift(); // Shift the alias command word off the argument vector.
718 args.Shift(); // Shift the old command word off the argument vector.
719
720 // Verify that the command is alias'able, and get the appropriate command
721 // object.
722
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000723 if (m_interpreter.CommandExists(alias_command)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000724 result.AppendErrorWithFormat(
725 "'%s' is a permanent debugger command and cannot be redefined.\n",
726 alias_command.c_str());
727 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000728 return false;
729 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000730
Zachary Turner4574a892016-12-08 01:31:04 +0000731 CommandObjectSP command_obj_sp(
732 m_interpreter.GetCommandSPExact(actual_command, true));
733 CommandObjectSP subcommand_obj_sp;
734 bool use_subcommand = false;
735 if (!command_obj_sp) {
736 result.AppendErrorWithFormat("'%s' is not an existing command.\n",
737 actual_command.c_str());
738 result.SetStatus(eReturnStatusFailed);
739 return false;
740 }
741 CommandObject *cmd_obj = command_obj_sp.get();
742 CommandObject *sub_cmd_obj = nullptr;
743 OptionArgVectorSP option_arg_vector_sp =
744 OptionArgVectorSP(new OptionArgVector);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000745
Zachary Turner4574a892016-12-08 01:31:04 +0000746 while (cmd_obj->IsMultiwordObject() && !args.empty()) {
747 auto sub_command = args[0].ref;
748 assert(!sub_command.empty());
749 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command);
750 if (!subcommand_obj_sp) {
751 result.AppendErrorWithFormat(
752 "'%s' is not a valid sub-command of '%s'. "
753 "Unable to create alias.\n",
754 args[0].c_str(), actual_command.c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000755 result.SetStatus(eReturnStatusFailed);
756 return false;
757 }
Zachary Turner4574a892016-12-08 01:31:04 +0000758
759 sub_cmd_obj = subcommand_obj_sp.get();
760 use_subcommand = true;
761 args.Shift(); // Shift the sub_command word off the argument vector.
762 cmd_obj = sub_cmd_obj;
763 }
764
765 // Verify & handle any options/arguments passed to the alias command
766
767 std::string args_string;
768
769 if (!args.empty()) {
770 CommandObjectSP tmp_sp =
771 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
772 if (use_subcommand)
773 tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(),
774 false);
775
776 args.GetCommandString(args_string);
777 }
778
779 if (m_interpreter.AliasExists(alias_command) ||
780 m_interpreter.UserCommandExists(alias_command)) {
781 result.AppendWarningWithFormat(
782 "Overwriting existing definition for '%s'.\n", alias_command.c_str());
783 }
784
785 if (CommandAlias *alias = m_interpreter.AddAlias(
786 alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp,
787 args_string)) {
788 if (m_command_options.m_help.OptionWasSet())
789 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
790 if (m_command_options.m_long_help.OptionWasSet())
791 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
792 result.SetStatus(eReturnStatusSuccessFinishNoResult);
793 } else {
794 result.AppendError("Unable to create requested alias.\n");
795 result.SetStatus(eReturnStatusFailed);
796 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000797 }
798
799 return result.Succeeded();
800 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000801};
802
803#pragma mark CommandObjectCommandsUnalias
804//-------------------------------------------------------------------------
805// CommandObjectCommandsUnalias
806//-------------------------------------------------------------------------
807
Kate Stoneb9c1b512016-09-06 20:57:50 +0000808class CommandObjectCommandsUnalias : public CommandObjectParsed {
Jim Inghamebc09c32010-07-07 03:36:20 +0000809public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000810 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
811 : CommandObjectParsed(
812 interpreter, "command unalias",
813 "Delete one or more custom commands defined by 'command alias'.",
814 nullptr) {
815 CommandArgumentEntry arg;
816 CommandArgumentData alias_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000817
Kate Stoneb9c1b512016-09-06 20:57:50 +0000818 // Define the first (and only) variant of this arg.
819 alias_arg.arg_type = eArgTypeAliasName;
820 alias_arg.arg_repetition = eArgRepeatPlain;
821
822 // There is only one variant this argument could be; put it into the
823 // argument entry.
824 arg.push_back(alias_arg);
825
826 // Push the data for the first argument into the m_arguments vector.
827 m_arguments.push_back(arg);
828 }
829
830 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000831
Jim Ingham5a988412012-06-08 21:56:10 +0000832protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000833 bool DoExecute(Args &args, CommandReturnObject &result) override {
834 CommandObject::CommandMap::iterator pos;
835 CommandObject *cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000836
Zachary Turner11eb9c62016-10-05 20:03:37 +0000837 if (args.empty()) {
838 result.AppendError("must call 'unalias' with a valid alias");
839 result.SetStatus(eReturnStatusFailed);
840 return false;
841 }
842
Zachary Turner4574a892016-12-08 01:31:04 +0000843 auto command_name = args[0].ref;
Zachary Turner11eb9c62016-10-05 20:03:37 +0000844 cmd_obj = m_interpreter.GetCommandObject(command_name);
Zachary Turner4574a892016-12-08 01:31:04 +0000845 if (!cmd_obj) {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000846 result.AppendErrorWithFormat(
847 "'%s' is not a known command.\nTry 'help' to see a "
848 "current list of commands.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000849 args[0].c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000850 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000851 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000852 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000853
Zachary Turner4574a892016-12-08 01:31:04 +0000854 if (m_interpreter.CommandExists(command_name)) {
855 if (cmd_obj->IsRemovable()) {
856 result.AppendErrorWithFormat(
857 "'%s' is not an alias, it is a debugger command which can be "
858 "removed using the 'command delete' command.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000859 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000860 } else {
861 result.AppendErrorWithFormat(
862 "'%s' is a permanent debugger command and cannot be removed.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000863 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000864 }
865 result.SetStatus(eReturnStatusFailed);
866 return false;
867 }
868
869 if (!m_interpreter.RemoveAlias(command_name)) {
870 if (m_interpreter.AliasExists(command_name))
871 result.AppendErrorWithFormat(
Zachary Turner867e7d12016-12-09 01:20:58 +0000872 "Error occurred while attempting to unalias '%s'.\n",
873 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000874 else
875 result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000876 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000877 result.SetStatus(eReturnStatusFailed);
878 return false;
879 }
880
881 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000882 return result.Succeeded();
883 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000884};
885
Greg Claytonb5472782015-01-09 19:08:20 +0000886#pragma mark CommandObjectCommandsDelete
887//-------------------------------------------------------------------------
888// CommandObjectCommandsDelete
889//-------------------------------------------------------------------------
890
Kate Stoneb9c1b512016-09-06 20:57:50 +0000891class CommandObjectCommandsDelete : public CommandObjectParsed {
Greg Claytonb5472782015-01-09 19:08:20 +0000892public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000893 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
894 : CommandObjectParsed(
895 interpreter, "command delete",
896 "Delete one or more custom commands defined by 'command regex'.",
897 nullptr) {
898 CommandArgumentEntry arg;
899 CommandArgumentData alias_arg;
Greg Claytonb5472782015-01-09 19:08:20 +0000900
Kate Stoneb9c1b512016-09-06 20:57:50 +0000901 // Define the first (and only) variant of this arg.
902 alias_arg.arg_type = eArgTypeCommandName;
903 alias_arg.arg_repetition = eArgRepeatPlain;
Greg Claytonb5472782015-01-09 19:08:20 +0000904
Kate Stoneb9c1b512016-09-06 20:57:50 +0000905 // There is only one variant this argument could be; put it into the
906 // argument entry.
907 arg.push_back(alias_arg);
Greg Claytonb5472782015-01-09 19:08:20 +0000908
Kate Stoneb9c1b512016-09-06 20:57:50 +0000909 // Push the data for the first argument into the m_arguments vector.
910 m_arguments.push_back(arg);
911 }
Greg Claytonb5472782015-01-09 19:08:20 +0000912
Kate Stoneb9c1b512016-09-06 20:57:50 +0000913 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +0000914
915protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000916 bool DoExecute(Args &args, CommandReturnObject &result) override {
917 CommandObject::CommandMap::iterator pos;
Greg Claytonb5472782015-01-09 19:08:20 +0000918
Zachary Turner11eb9c62016-10-05 20:03:37 +0000919 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 result.AppendErrorWithFormat("must call '%s' with one or more valid user "
921 "defined regular expression command names",
Zachary Turnera4496982016-10-05 21:14:38 +0000922 GetCommandName().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000923 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000924 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000925
Zachary Turner4574a892016-12-08 01:31:04 +0000926 auto command_name = args[0].ref;
927 if (!m_interpreter.CommandExists(command_name)) {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000928 StreamString error_msg_stream;
929 const bool generate_apropos = true;
930 const bool generate_type_lookup = false;
931 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
Zachary Turner4574a892016-12-08 01:31:04 +0000932 &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(),
933 generate_apropos, generate_type_lookup);
Zachary Turnerc1564272016-11-16 21:15:24 +0000934 result.AppendError(error_msg_stream.GetString());
Zachary Turner11eb9c62016-10-05 20:03:37 +0000935 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +0000936 return false;
Zachary Turner11eb9c62016-10-05 20:03:37 +0000937 }
938
Zachary Turner4574a892016-12-08 01:31:04 +0000939 if (!m_interpreter.RemoveCommand(command_name)) {
940 result.AppendErrorWithFormat(
941 "'%s' is a permanent debugger command and cannot be removed.\n",
Zachary Turner867e7d12016-12-09 01:20:58 +0000942 args[0].c_str());
Zachary Turner4574a892016-12-08 01:31:04 +0000943 result.SetStatus(eReturnStatusFailed);
944 return false;
945 }
946
947 result.SetStatus(eReturnStatusSuccessFinishNoResult);
948 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000949 }
Greg Claytonb5472782015-01-09 19:08:20 +0000950};
951
Greg Claytonde164aa2011-04-20 16:37:46 +0000952//-------------------------------------------------------------------------
953// CommandObjectCommandsAddRegex
954//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000955
956static OptionDefinition g_regex_options[] = {
957 // clang-format off
958 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
959 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
960 // clang-format on
961};
962
Jim Ingham5a988412012-06-08 21:56:10 +0000963#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +0000964
Kate Stoneb9c1b512016-09-06 20:57:50 +0000965class CommandObjectCommandsAddRegex : public CommandObjectParsed,
966 public IOHandlerDelegateMultiline {
Greg Claytonde164aa2011-04-20 16:37:46 +0000967public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
969 : CommandObjectParsed(
970 interpreter, "command regex", "Define a custom command in terms of "
971 "existing commands by matching "
972 "regular expressions.",
973 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
974 IOHandlerDelegateMultiline("",
975 IOHandlerDelegate::Completion::LLDBCommand),
976 m_options() {
977 SetHelpLong(
978 R"(
979)"
980 "This command allows the user to create powerful regular expression commands \
Kate Stoneea671fb2015-07-14 05:48:36 +0000981with substitutions. The regular expressions and substitutions are specified \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000982using the regular expression substitution format of:"
983 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000984
985 s/<regex>/<subst>/
986
Kate Stoneb9c1b512016-09-06 20:57:50 +0000987)"
988 "<regex> is a regular expression that can use parenthesis to capture regular \
Kate Stoneea671fb2015-07-14 05:48:36 +0000989expression input and substitute the captured matches in the output using %1 \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000990for the first match, %2 for the second, and so on."
991 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000992
Kate Stoneb9c1b512016-09-06 20:57:50 +0000993)"
994 "The regular expressions can all be specified on the command line if more than \
Kate Stoneea671fb2015-07-14 05:48:36 +0000995one argument is provided. If just the command name is provided on the command \
996line, then the regular expressions and substitutions can be entered on separate \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997lines, followed by an empty line to terminate the command definition."
998 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000999
1000EXAMPLES
1001
Kate Stoneb9c1b512016-09-06 20:57:50 +00001002)"
1003 "The following example will define a regular expression command named 'f' that \
Kate Stoneea671fb2015-07-14 05:48:36 +00001004will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001005a number follows 'f':"
1006 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001007
Kate Stoneb9c1b512016-09-06 20:57:50 +00001008 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1009 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001010
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011 ~CommandObjectCommandsAddRegex() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001012
Jim Ingham5a988412012-06-08 21:56:10 +00001013protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001014 void IOHandlerActivated(IOHandler &io_handler) override {
1015 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1016 if (output_sp) {
1017 output_sp->PutCString("Enter one of more sed substitution commands in "
1018 "the form: 's/<regex>/<subst>/'.\nTerminate the "
1019 "substitution list with an empty line.\n");
1020 output_sp->Flush();
1021 }
1022 }
1023
1024 void IOHandlerInputComplete(IOHandler &io_handler,
1025 std::string &data) override {
1026 io_handler.SetIsDone(true);
1027 if (m_regex_cmd_ap) {
1028 StringList lines;
1029 if (lines.SplitIntoLines(data)) {
1030 const size_t num_lines = lines.GetSize();
1031 bool check_only = false;
1032 for (size_t i = 0; i < num_lines; ++i) {
1033 llvm::StringRef bytes_strref(lines[i]);
Zachary Turner97206d52017-05-12 04:51:55 +00001034 Status error = AppendRegexSubstitution(bytes_strref, check_only);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001035 if (error.Fail()) {
1036 if (!m_interpreter.GetDebugger()
1037 .GetCommandInterpreter()
1038 .GetBatchCommandMode()) {
1039 StreamSP out_stream =
1040 m_interpreter.GetDebugger().GetAsyncOutputStream();
1041 out_stream->Printf("error: %s\n", error.AsCString());
1042 }
1043 }
Greg Clayton44d93782014-01-27 23:43:24 +00001044 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001045 }
1046 if (m_regex_cmd_ap->HasRegexEntries()) {
1047 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1048 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1049 }
1050 }
1051 }
1052
1053 bool DoExecute(Args &command, CommandReturnObject &result) override {
1054 const size_t argc = command.GetArgumentCount();
1055 if (argc == 0) {
1056 result.AppendError("usage: 'command regex <command-name> "
1057 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1058 result.SetStatus(eReturnStatusFailed);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001059 return false;
1060 }
1061
Zachary Turner97206d52017-05-12 04:51:55 +00001062 Status error;
Zachary Turner4574a892016-12-08 01:31:04 +00001063 auto name = command[0].ref;
1064 m_regex_cmd_ap = llvm::make_unique<CommandObjectRegexCommand>(
1065 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0,
1066 true);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001067
1068 if (argc == 1) {
1069 Debugger &debugger = m_interpreter.GetDebugger();
1070 bool color_prompt = debugger.GetUseColor();
1071 const bool multiple_lines = true; // Get multiple lines
1072 IOHandlerSP io_handler_sp(new IOHandlerEditline(
1073 debugger, IOHandler::Type::Other,
1074 "lldb-regex", // Name of input reader for history
1075 llvm::StringRef("> "), // Prompt
1076 llvm::StringRef(), // Continuation prompt
1077 multiple_lines, color_prompt,
1078 0, // Don't show line numbers
1079 *this));
1080
1081 if (io_handler_sp) {
1082 debugger.PushIOHandler(io_handler_sp);
1083 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1084 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001085 } else {
Zachary Turner97d2c402016-10-05 23:40:23 +00001086 for (auto &entry : command.entries().drop_front()) {
Zachary Turner11eb9c62016-10-05 20:03:37 +00001087 bool check_only = false;
Zachary Turner97d2c402016-10-05 23:40:23 +00001088 error = AppendRegexSubstitution(entry.ref, check_only);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001089 if (error.Fail())
1090 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001091 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001092
1093 if (error.Success()) {
1094 AddRegexCommandToInterpreter();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001095 }
Greg Clayton44d93782014-01-27 23:43:24 +00001096 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001097 if (error.Fail()) {
1098 result.AppendError(error.AsCString());
1099 result.SetStatus(eReturnStatusFailed);
1100 }
Greg Clayton44d93782014-01-27 23:43:24 +00001101
Kate Stoneb9c1b512016-09-06 20:57:50 +00001102 return result.Succeeded();
1103 }
1104
Zachary Turner97206d52017-05-12 04:51:55 +00001105 Status AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1106 bool check_only) {
1107 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001108
1109 if (!m_regex_cmd_ap) {
1110 error.SetErrorStringWithFormat(
1111 "invalid regular expression command object for: '%.*s'",
1112 (int)regex_sed.size(), regex_sed.data());
1113 return error;
Greg Clayton44d93782014-01-27 23:43:24 +00001114 }
Greg Clayton44d93782014-01-27 23:43:24 +00001115
Kate Stoneb9c1b512016-09-06 20:57:50 +00001116 size_t regex_sed_size = regex_sed.size();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001117
Kate Stoneb9c1b512016-09-06 20:57:50 +00001118 if (regex_sed_size <= 1) {
1119 error.SetErrorStringWithFormat(
1120 "regular expression substitution string is too short: '%.*s'",
1121 (int)regex_sed.size(), regex_sed.data());
1122 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001123 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001124
Kate Stoneb9c1b512016-09-06 20:57:50 +00001125 if (regex_sed[0] != 's') {
1126 error.SetErrorStringWithFormat("regular expression substitution string "
1127 "doesn't start with 's': '%.*s'",
1128 (int)regex_sed.size(), regex_sed.data());
1129 return error;
1130 }
1131 const size_t first_separator_char_pos = 1;
1132 // use the char that follows 's' as the regex separator character
1133 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1134 const char separator_char = regex_sed[first_separator_char_pos];
1135 const size_t second_separator_char_pos =
1136 regex_sed.find(separator_char, first_separator_char_pos + 1);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001137
Kate Stoneb9c1b512016-09-06 20:57:50 +00001138 if (second_separator_char_pos == std::string::npos) {
1139 error.SetErrorStringWithFormat(
1140 "missing second '%c' separator char after '%.*s' in '%.*s'",
1141 separator_char,
1142 (int)(regex_sed.size() - first_separator_char_pos - 1),
1143 regex_sed.data() + (first_separator_char_pos + 1),
1144 (int)regex_sed.size(), regex_sed.data());
1145 return error;
1146 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001147
Kate Stoneb9c1b512016-09-06 20:57:50 +00001148 const size_t third_separator_char_pos =
1149 regex_sed.find(separator_char, second_separator_char_pos + 1);
Greg Clayton44d93782014-01-27 23:43:24 +00001150
Kate Stoneb9c1b512016-09-06 20:57:50 +00001151 if (third_separator_char_pos == std::string::npos) {
1152 error.SetErrorStringWithFormat(
1153 "missing third '%c' separator char after '%.*s' in '%.*s'",
1154 separator_char,
1155 (int)(regex_sed.size() - second_separator_char_pos - 1),
1156 regex_sed.data() + (second_separator_char_pos + 1),
1157 (int)regex_sed.size(), regex_sed.data());
1158 return error;
1159 }
1160
1161 if (third_separator_char_pos != regex_sed_size - 1) {
1162 // Make sure that everything that follows the last regex
1163 // separator char
1164 if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1165 third_separator_char_pos + 1) !=
1166 std::string::npos) {
1167 error.SetErrorStringWithFormat(
1168 "extra data found after the '%.*s' regular expression substitution "
1169 "string: '%.*s'",
1170 (int)third_separator_char_pos + 1, regex_sed.data(),
1171 (int)(regex_sed.size() - third_separator_char_pos - 1),
1172 regex_sed.data() + (third_separator_char_pos + 1));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001173 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001174 }
1175 } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1176 error.SetErrorStringWithFormat(
1177 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1178 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1179 regex_sed.data());
1180 return error;
1181 } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1182 error.SetErrorStringWithFormat(
1183 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1184 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1185 regex_sed.data());
1186 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001187 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001188
1189 if (!check_only) {
1190 std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1191 second_separator_char_pos -
1192 first_separator_char_pos - 1));
1193 std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1194 third_separator_char_pos -
1195 second_separator_char_pos - 1));
1196 m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001197 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001198 return error;
1199 }
1200
1201 void AddRegexCommandToInterpreter() {
1202 if (m_regex_cmd_ap) {
1203 if (m_regex_cmd_ap->HasRegexEntries()) {
1204 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1205 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1206 }
1207 }
1208 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001209
Greg Claytonde164aa2011-04-20 16:37:46 +00001210private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001211 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001212
Kate Stoneb9c1b512016-09-06 20:57:50 +00001213 class CommandOptions : public Options {
1214 public:
1215 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001216
Kate Stoneb9c1b512016-09-06 20:57:50 +00001217 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001218
Zachary Turner97206d52017-05-12 04:51:55 +00001219 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1220 ExecutionContext *execution_context) override {
1221 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001222 const int short_option = m_getopt_table[option_idx].val;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001223
Kate Stoneb9c1b512016-09-06 20:57:50 +00001224 switch (short_option) {
1225 case 'h':
1226 m_help.assign(option_arg);
1227 break;
1228 case 's':
1229 m_syntax.assign(option_arg);
1230 break;
1231 default:
1232 error.SetErrorStringWithFormat("unrecognized option '%c'",
1233 short_option);
1234 break;
1235 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001236
Kate Stoneb9c1b512016-09-06 20:57:50 +00001237 return error;
1238 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001239
Kate Stoneb9c1b512016-09-06 20:57:50 +00001240 void OptionParsingStarting(ExecutionContext *execution_context) override {
1241 m_help.clear();
1242 m_syntax.clear();
1243 }
1244
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001245 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001246 return llvm::makeArrayRef(g_regex_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001247 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001248
Zachary Turner11eb9c62016-10-05 20:03:37 +00001249 // TODO: Convert these functions to return StringRefs.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001250 const char *GetHelp() {
1251 return (m_help.empty() ? nullptr : m_help.c_str());
1252 }
1253
1254 const char *GetSyntax() {
1255 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1256 }
1257
1258 protected:
1259 // Instance variables to hold the values for command options.
1260
1261 std::string m_help;
1262 std::string m_syntax;
1263 };
1264
1265 Options *GetOptions() override { return &m_options; }
1266
1267 CommandOptions m_options;
Greg Claytonde164aa2011-04-20 16:37:46 +00001268};
1269
Kate Stoneb9c1b512016-09-06 20:57:50 +00001270class CommandObjectPythonFunction : public CommandObjectRaw {
Enrico Granata223383e2011-08-16 23:24:13 +00001271public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001272 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1273 std::string funct, std::string help,
1274 ScriptedCommandSynchronicity synch)
Zachary Turnera4496982016-10-05 21:14:38 +00001275 : CommandObjectRaw(interpreter, name),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001276 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1277 if (!help.empty())
Zachary Turner442f6532016-11-12 20:41:02 +00001278 SetHelp(help);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001279 else {
1280 StreamString stream;
1281 stream.Printf("For more information run 'help %s'", name.c_str());
Zachary Turnerc1564272016-11-16 21:15:24 +00001282 SetHelp(stream.GetString());
Enrico Granata223383e2011-08-16 23:24:13 +00001283 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001284 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001285
Kate Stoneb9c1b512016-09-06 20:57:50 +00001286 ~CommandObjectPythonFunction() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001287
Kate Stoneb9c1b512016-09-06 20:57:50 +00001288 bool IsRemovable() const override { return true; }
Jim Ingham5a988412012-06-08 21:56:10 +00001289
Kate Stoneb9c1b512016-09-06 20:57:50 +00001290 const std::string &GetFunctionName() { return m_function_name; }
Jim Ingham5a988412012-06-08 21:56:10 +00001291
Kate Stoneb9c1b512016-09-06 20:57:50 +00001292 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1293
Zachary Turner442f6532016-11-12 20:41:02 +00001294 llvm::StringRef GetHelpLong() override {
1295 if (m_fetched_help_long)
1296 return CommandObjectRaw::GetHelpLong();
1297
1298 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1299 if (!scripter)
1300 return CommandObjectRaw::GetHelpLong();
1301
1302 std::string docstring;
1303 m_fetched_help_long =
1304 scripter->GetDocumentationForItem(m_function_name.c_str(), docstring);
1305 if (!docstring.empty())
1306 SetHelpLong(docstring);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001307 return CommandObjectRaw::GetHelpLong();
1308 }
1309
Jim Ingham5a988412012-06-08 21:56:10 +00001310protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001311 bool DoExecute(const char *raw_command_line,
1312 CommandReturnObject &result) override {
1313 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1314
Zachary Turner97206d52017-05-12 04:51:55 +00001315 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001316
1317 result.SetStatus(eReturnStatusInvalid);
1318
1319 if (!scripter ||
1320 !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1321 raw_command_line, m_synchro, result,
1322 error, m_exe_ctx)) {
1323 result.AppendError(error.AsCString());
1324 result.SetStatus(eReturnStatusFailed);
1325 } else {
1326 // Don't change the status if the command already set it...
1327 if (result.GetStatus() == eReturnStatusInvalid) {
Zachary Turnerc1564272016-11-16 21:15:24 +00001328 if (result.GetOutputData().empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001329 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata223383e2011-08-16 23:24:13 +00001330 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001331 result.SetStatus(eReturnStatusSuccessFinishResult);
1332 }
Enrico Granata223383e2011-08-16 23:24:13 +00001333 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001334
Kate Stoneb9c1b512016-09-06 20:57:50 +00001335 return result.Succeeded();
1336 }
1337
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001338private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001339 std::string m_function_name;
1340 ScriptedCommandSynchronicity m_synchro;
1341 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001342};
1343
Kate Stoneb9c1b512016-09-06 20:57:50 +00001344class CommandObjectScriptingObject : public CommandObjectRaw {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001345public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001346 CommandObjectScriptingObject(CommandInterpreter &interpreter,
1347 std::string name,
1348 StructuredData::GenericSP cmd_obj_sp,
1349 ScriptedCommandSynchronicity synch)
Zachary Turnera4496982016-10-05 21:14:38 +00001350 : CommandObjectRaw(interpreter, name),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001351 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1352 m_fetched_help_long(false) {
1353 StreamString stream;
1354 stream.Printf("For more information run 'help %s'", name.c_str());
Zachary Turnerc1564272016-11-16 21:15:24 +00001355 SetHelp(stream.GetString());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001356 if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1357 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1358 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001359
Kate Stoneb9c1b512016-09-06 20:57:50 +00001360 ~CommandObjectScriptingObject() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001361
Kate Stoneb9c1b512016-09-06 20:57:50 +00001362 bool IsRemovable() const override { return true; }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001363
Kate Stoneb9c1b512016-09-06 20:57:50 +00001364 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1365
1366 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1367
Zachary Turner442f6532016-11-12 20:41:02 +00001368 llvm::StringRef GetHelp() override {
1369 if (m_fetched_help_short)
1370 return CommandObjectRaw::GetHelp();
1371 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1372 if (!scripter)
1373 return CommandObjectRaw::GetHelp();
1374 std::string docstring;
1375 m_fetched_help_short =
1376 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1377 if (!docstring.empty())
1378 SetHelp(docstring);
1379
Kate Stoneb9c1b512016-09-06 20:57:50 +00001380 return CommandObjectRaw::GetHelp();
1381 }
1382
Zachary Turner442f6532016-11-12 20:41:02 +00001383 llvm::StringRef GetHelpLong() override {
1384 if (m_fetched_help_long)
1385 return CommandObjectRaw::GetHelpLong();
1386
1387 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1388 if (!scripter)
1389 return CommandObjectRaw::GetHelpLong();
1390
1391 std::string docstring;
1392 m_fetched_help_long =
1393 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1394 if (!docstring.empty())
1395 SetHelpLong(docstring);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001396 return CommandObjectRaw::GetHelpLong();
1397 }
1398
Enrico Granata9fe00e52015-03-13 02:20:41 +00001399protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001400 bool DoExecute(const char *raw_command_line,
1401 CommandReturnObject &result) override {
1402 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1403
Zachary Turner97206d52017-05-12 04:51:55 +00001404 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001405
1406 result.SetStatus(eReturnStatusInvalid);
1407
1408 if (!scripter ||
1409 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1410 m_synchro, result, error, m_exe_ctx)) {
1411 result.AppendError(error.AsCString());
1412 result.SetStatus(eReturnStatusFailed);
1413 } else {
1414 // Don't change the status if the command already set it...
1415 if (result.GetStatus() == eReturnStatusInvalid) {
Zachary Turnerc1564272016-11-16 21:15:24 +00001416 if (result.GetOutputData().empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001417 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata9fe00e52015-03-13 02:20:41 +00001418 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001419 result.SetStatus(eReturnStatusSuccessFinishResult);
1420 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001421 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001422
Kate Stoneb9c1b512016-09-06 20:57:50 +00001423 return result.Succeeded();
1424 }
1425
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001426private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001427 StructuredData::GenericSP m_cmd_obj_sp;
1428 ScriptedCommandSynchronicity m_synchro;
1429 bool m_fetched_help_short : 1;
1430 bool m_fetched_help_long : 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001431};
1432
Enrico Granataa9dbf432011-10-17 21:45:27 +00001433//-------------------------------------------------------------------------
1434// CommandObjectCommandsScriptImport
1435//-------------------------------------------------------------------------
1436
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001437OptionDefinition g_script_import_options[] = {
1438 // clang-format off
1439 { 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." },
1440 // clang-format on
1441};
1442
Kate Stoneb9c1b512016-09-06 20:57:50 +00001443class CommandObjectCommandsScriptImport : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001444public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001445 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1446 : CommandObjectParsed(interpreter, "command script import",
1447 "Import a scripting module in LLDB.", nullptr),
1448 m_options() {
1449 CommandArgumentEntry arg1;
1450 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001451
Kate Stoneb9c1b512016-09-06 20:57:50 +00001452 // Define the first (and only) variant of this arg.
1453 cmd_arg.arg_type = eArgTypeFilename;
1454 cmd_arg.arg_repetition = eArgRepeatPlus;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001455
Kate Stoneb9c1b512016-09-06 20:57:50 +00001456 // There is only one variant this argument could be; put it into the
1457 // argument entry.
1458 arg1.push_back(cmd_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +00001459
Kate Stoneb9c1b512016-09-06 20:57:50 +00001460 // Push the data for the first argument into the m_arguments vector.
1461 m_arguments.push_back(arg1);
1462 }
1463
1464 ~CommandObjectCommandsScriptImport() override = default;
1465
1466 int HandleArgumentCompletion(Args &input, int &cursor_index,
1467 int &cursor_char_position,
1468 OptionElementVector &opt_element_vector,
1469 int match_start_point, int max_return_elements,
1470 bool &word_complete,
1471 StringList &matches) override {
Zachary Turnerd6a24752016-11-22 17:10:15 +00001472 llvm::StringRef completion_str = input[cursor_index].ref;
1473 completion_str = completion_str.take_front(cursor_char_position);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001474
1475 CommandCompletions::InvokeCommonCompletionCallbacks(
1476 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
Zachary Turnerd6a24752016-11-22 17:10:15 +00001477 completion_str, match_start_point, max_return_elements, nullptr,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001478 word_complete, matches);
1479 return matches.GetSize();
1480 }
1481
1482 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +00001483
1484protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001485 class CommandOptions : public Options {
1486 public:
1487 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001488
Kate Stoneb9c1b512016-09-06 20:57:50 +00001489 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001490
Zachary Turner97206d52017-05-12 04:51:55 +00001491 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1492 ExecutionContext *execution_context) override {
1493 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001494 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001495
Kate Stoneb9c1b512016-09-06 20:57:50 +00001496 switch (short_option) {
1497 case 'r':
1498 m_allow_reload = true;
1499 break;
1500 default:
1501 error.SetErrorStringWithFormat("unrecognized option '%c'",
1502 short_option);
1503 break;
1504 }
1505
1506 return error;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001507 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001508
1509 void OptionParsingStarting(ExecutionContext *execution_context) override {
1510 m_allow_reload = true;
1511 }
1512
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001513 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001514 return llvm::makeArrayRef(g_script_import_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001515 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001516
1517 // Instance variables to hold the values for command options.
1518
1519 bool m_allow_reload;
1520 };
1521
1522 bool DoExecute(Args &command, CommandReturnObject &result) override {
1523 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1524 lldb::eScriptLanguagePython) {
1525 result.AppendError("only scripting language supported for module "
1526 "importing is currently Python");
1527 result.SetStatus(eReturnStatusFailed);
1528 return false;
1529 }
1530
Zachary Turner11eb9c62016-10-05 20:03:37 +00001531 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001532 result.AppendError("command script import needs one or more arguments");
1533 result.SetStatus(eReturnStatusFailed);
1534 return false;
1535 }
1536
Zachary Turner11eb9c62016-10-05 20:03:37 +00001537 for (auto &entry : command.entries()) {
Zachary Turner97206d52017-05-12 04:51:55 +00001538 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001539
1540 const bool init_session = true;
1541 // FIXME: this is necessary because CommandObject::CheckRequirements()
Zachary Turner11eb9c62016-10-05 20:03:37 +00001542 // assumes that commands won't ever be recursively invoked, but it's
1543 // actually possible to craft a Python script that does other "command
1544 // script imports" in __lldb_init_module the real fix is to have recursive
1545 // commands possible with a CommandInvocation object separate from the
1546 // CommandObject itself, so that recursive command invocations won't stomp
1547 // on each other (wrt to execution contents, options, and more)
Kate Stoneb9c1b512016-09-06 20:57:50 +00001548 m_exe_ctx.Clear();
1549 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
Zachary Turner11eb9c62016-10-05 20:03:37 +00001550 entry.c_str(), m_options.m_allow_reload, init_session, error)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001551 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1552 } else {
1553 result.AppendErrorWithFormat("module importing failed: %s",
1554 error.AsCString());
1555 result.SetStatus(eReturnStatusFailed);
1556 }
1557 }
1558
1559 return result.Succeeded();
1560 }
1561
1562 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001563};
Enrico Granata223383e2011-08-16 23:24:13 +00001564
1565//-------------------------------------------------------------------------
1566// CommandObjectCommandsScriptAdd
1567//-------------------------------------------------------------------------
1568
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001569static OptionEnumValueElement g_script_synchro_type[] = {
1570 {eScriptedCommandSynchronicitySynchronous, "synchronous",
1571 "Run synchronous"},
1572 {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1573 "Run asynchronous"},
1574 {eScriptedCommandSynchronicityCurrentValue, "current",
1575 "Do not alter current setting"},
1576 {0, nullptr, nullptr}};
1577
1578static OptionDefinition g_script_add_options[] = {
1579 // clang-format off
1580 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
1581 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
1582 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." },
1583 { 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." },
1584 // clang-format on
1585};
1586
Kate Stoneb9c1b512016-09-06 20:57:50 +00001587class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1588 public IOHandlerDelegateMultiline {
Jim Ingham5a988412012-06-08 21:56:10 +00001589public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001590 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1591 : CommandObjectParsed(interpreter, "command script add",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001592 "Add a scripted function as an LLDB command.",
1593 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001594 IOHandlerDelegateMultiline("DONE"), m_options() {
1595 CommandArgumentEntry arg1;
1596 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001597
Kate Stoneb9c1b512016-09-06 20:57:50 +00001598 // Define the first (and only) variant of this arg.
1599 cmd_arg.arg_type = eArgTypeCommandName;
1600 cmd_arg.arg_repetition = eArgRepeatPlain;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001601
Kate Stoneb9c1b512016-09-06 20:57:50 +00001602 // There is only one variant this argument could be; put it into the
1603 // argument entry.
1604 arg1.push_back(cmd_arg);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001605
Kate Stoneb9c1b512016-09-06 20:57:50 +00001606 // Push the data for the first argument into the m_arguments vector.
1607 m_arguments.push_back(arg1);
1608 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001609
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610 ~CommandObjectCommandsScriptAdd() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001611
Kate Stoneb9c1b512016-09-06 20:57:50 +00001612 Options *GetOptions() override { return &m_options; }
Greg Clayton44d93782014-01-27 23:43:24 +00001613
Jim Ingham5a988412012-06-08 21:56:10 +00001614protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001615 class CommandOptions : public Options {
1616 public:
1617 CommandOptions()
1618 : Options(), m_class_name(), m_funct_name(), m_short_help(),
1619 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
Enrico Granata223383e2011-08-16 23:24:13 +00001620
Kate Stoneb9c1b512016-09-06 20:57:50 +00001621 ~CommandOptions() override = default;
1622
Zachary Turner97206d52017-05-12 04:51:55 +00001623 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1624 ExecutionContext *execution_context) override {
1625 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001626 const int short_option = m_getopt_table[option_idx].val;
1627
1628 switch (short_option) {
1629 case 'f':
Zachary Turnerfe114832016-11-12 16:56:47 +00001630 if (!option_arg.empty())
1631 m_funct_name = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001632 break;
1633 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +00001634 if (!option_arg.empty())
1635 m_class_name = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001636 break;
1637 case 'h':
Zachary Turnerfe114832016-11-12 16:56:47 +00001638 if (!option_arg.empty())
1639 m_short_help = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001640 break;
1641 case 's':
1642 m_synchronicity =
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001643 (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum(
Zachary Turnerfe114832016-11-12 16:56:47 +00001644 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001645 if (!error.Success())
1646 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001647 "unrecognized value for synchronicity '%s'",
1648 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001649 break;
1650 default:
1651 error.SetErrorStringWithFormat("unrecognized option '%c'",
1652 short_option);
1653 break;
1654 }
1655
1656 return error;
Enrico Granata223383e2011-08-16 23:24:13 +00001657 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001658
1659 void OptionParsingStarting(ExecutionContext *execution_context) override {
1660 m_class_name.clear();
1661 m_funct_name.clear();
1662 m_short_help.clear();
1663 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1664 }
1665
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001666 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001667 return llvm::makeArrayRef(g_script_add_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001668 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001669
1670 // Instance variables to hold the values for command options.
1671
1672 std::string m_class_name;
1673 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001674 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001675 ScriptedCommandSynchronicity m_synchronicity;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001676 };
1677
1678 void IOHandlerActivated(IOHandler &io_handler) override {
1679 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1680 if (output_sp) {
1681 output_sp->PutCString(g_python_command_instructions);
1682 output_sp->Flush();
1683 }
1684 }
1685
1686 void IOHandlerInputComplete(IOHandler &io_handler,
1687 std::string &data) override {
1688 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1689
1690 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1691 if (interpreter) {
1692
1693 StringList lines;
1694 lines.SplitIntoLines(data);
1695 if (lines.GetSize() > 0) {
1696 std::string funct_name_str;
1697 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1698 if (funct_name_str.empty()) {
1699 error_sp->Printf("error: unable to obtain a function name, didn't "
1700 "add python command.\n");
1701 error_sp->Flush();
1702 } else {
1703 // everything should be fine now, let's add this alias
1704
1705 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00001706 m_interpreter, m_cmd_name, funct_name_str, m_short_help,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001707 m_synchronicity));
1708
1709 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1710 true)) {
1711 error_sp->Printf("error: unable to add selected command, didn't "
1712 "add python command.\n");
1713 error_sp->Flush();
1714 }
1715 }
1716 } else {
1717 error_sp->Printf(
1718 "error: unable to create function, didn't add python command.\n");
1719 error_sp->Flush();
1720 }
1721 } else {
1722 error_sp->Printf("error: empty function, didn't add python command.\n");
1723 error_sp->Flush();
1724 }
1725 } else {
1726 error_sp->Printf(
1727 "error: script interpreter missing, didn't add python command.\n");
1728 error_sp->Flush();
1729 }
1730
1731 io_handler.SetIsDone(true);
1732 }
1733
1734protected:
1735 bool DoExecute(Args &command, CommandReturnObject &result) override {
1736 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1737 lldb::eScriptLanguagePython) {
1738 result.AppendError("only scripting language supported for scripted "
1739 "commands is currently Python");
1740 result.SetStatus(eReturnStatusFailed);
1741 return false;
1742 }
1743
Zachary Turner11eb9c62016-10-05 20:03:37 +00001744 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001745 result.AppendError("'command script add' requires one argument");
1746 result.SetStatus(eReturnStatusFailed);
1747 return false;
1748 }
1749
1750 // Store the options in case we get multi-line input
Zachary Turner4574a892016-12-08 01:31:04 +00001751 m_cmd_name = command[0].ref;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001752 m_short_help.assign(m_options.m_short_help);
1753 m_synchronicity = m_options.m_synchronicity;
1754
1755 if (m_options.m_class_name.empty()) {
1756 if (m_options.m_funct_name.empty()) {
1757 m_interpreter.GetPythonCommandsFromIOHandler(
1758 " ", // Prompt
1759 *this, // IOHandlerDelegate
1760 true, // Run IOHandler in async mode
1761 nullptr); // Baton for the "io_handler" that will be passed back
1762 // into our IOHandlerDelegate functions
1763 } else {
1764 CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1765 m_interpreter, m_cmd_name, m_options.m_funct_name,
1766 m_options.m_short_help, m_synchronicity));
1767 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1768 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1769 } else {
1770 result.AppendError("cannot add command");
1771 result.SetStatus(eReturnStatusFailed);
1772 }
1773 }
1774 } else {
1775 ScriptInterpreter *interpreter =
1776 GetCommandInterpreter().GetScriptInterpreter();
1777 if (!interpreter) {
1778 result.AppendError("cannot find ScriptInterpreter");
1779 result.SetStatus(eReturnStatusFailed);
1780 return false;
1781 }
1782
1783 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1784 m_options.m_class_name.c_str());
1785 if (!cmd_obj_sp) {
1786 result.AppendError("cannot create helper object");
1787 result.SetStatus(eReturnStatusFailed);
1788 return false;
1789 }
1790
1791 CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1792 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1793 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1794 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1795 } else {
1796 result.AppendError("cannot add command");
1797 result.SetStatus(eReturnStatusFailed);
1798 }
1799 }
1800
1801 return result.Succeeded();
1802 }
1803
1804 CommandOptions m_options;
1805 std::string m_cmd_name;
1806 std::string m_short_help;
1807 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001808};
1809
Enrico Granata223383e2011-08-16 23:24:13 +00001810//-------------------------------------------------------------------------
1811// CommandObjectCommandsScriptList
1812//-------------------------------------------------------------------------
1813
Kate Stoneb9c1b512016-09-06 20:57:50 +00001814class CommandObjectCommandsScriptList : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001815public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001816 CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1817 : CommandObjectParsed(interpreter, "command script list",
1818 "List defined scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001819
Kate Stoneb9c1b512016-09-06 20:57:50 +00001820 ~CommandObjectCommandsScriptList() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001821
Kate Stoneb9c1b512016-09-06 20:57:50 +00001822 bool DoExecute(Args &command, CommandReturnObject &result) override {
1823 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1824
1825 result.SetStatus(eReturnStatusSuccessFinishResult);
1826
1827 return true;
1828 }
Enrico Granata223383e2011-08-16 23:24:13 +00001829};
1830
1831//-------------------------------------------------------------------------
1832// CommandObjectCommandsScriptClear
1833//-------------------------------------------------------------------------
1834
Kate Stoneb9c1b512016-09-06 20:57:50 +00001835class CommandObjectCommandsScriptClear : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001836public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001837 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1838 : CommandObjectParsed(interpreter, "command script clear",
1839 "Delete all scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001840
Kate Stoneb9c1b512016-09-06 20:57:50 +00001841 ~CommandObjectCommandsScriptClear() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001842
Jim Ingham5a988412012-06-08 21:56:10 +00001843protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001844 bool DoExecute(Args &command, CommandReturnObject &result) override {
1845 m_interpreter.RemoveAllUser();
1846
1847 result.SetStatus(eReturnStatusSuccessFinishResult);
1848
1849 return true;
1850 }
Enrico Granata223383e2011-08-16 23:24:13 +00001851};
1852
1853//-------------------------------------------------------------------------
1854// CommandObjectCommandsScriptDelete
1855//-------------------------------------------------------------------------
1856
Kate Stoneb9c1b512016-09-06 20:57:50 +00001857class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001858public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001859 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1860 : CommandObjectParsed(interpreter, "command script delete",
1861 "Delete a scripted command.", nullptr) {
1862 CommandArgumentEntry arg1;
1863 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001864
Kate Stoneb9c1b512016-09-06 20:57:50 +00001865 // Define the first (and only) variant of this arg.
1866 cmd_arg.arg_type = eArgTypeCommandName;
1867 cmd_arg.arg_repetition = eArgRepeatPlain;
1868
1869 // There is only one variant this argument could be; put it into the
1870 // argument entry.
1871 arg1.push_back(cmd_arg);
1872
1873 // Push the data for the first argument into the m_arguments vector.
1874 m_arguments.push_back(arg1);
1875 }
1876
1877 ~CommandObjectCommandsScriptDelete() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001878
Jim Ingham5a988412012-06-08 21:56:10 +00001879protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001880 bool DoExecute(Args &command, CommandReturnObject &result) override {
1881
Zachary Turner11eb9c62016-10-05 20:03:37 +00001882 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001883 result.AppendError("'command script delete' requires one argument");
1884 result.SetStatus(eReturnStatusFailed);
1885 return false;
Enrico Granata223383e2011-08-16 23:24:13 +00001886 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001887
Zachary Turner4574a892016-12-08 01:31:04 +00001888 auto cmd_name = command[0].ref;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001889
Zachary Turner4574a892016-12-08 01:31:04 +00001890 if (cmd_name.empty() || !m_interpreter.HasUserCommands() ||
1891 !m_interpreter.UserCommandExists(cmd_name)) {
Zachary Turner867e7d12016-12-09 01:20:58 +00001892 result.AppendErrorWithFormat("command %s not found", command[0].c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001893 result.SetStatus(eReturnStatusFailed);
Zachary Turner4574a892016-12-08 01:31:04 +00001894 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001895 }
1896
Zachary Turner4574a892016-12-08 01:31:04 +00001897 m_interpreter.RemoveUser(cmd_name);
1898 result.SetStatus(eReturnStatusSuccessFinishResult);
1899 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001900 }
Enrico Granata223383e2011-08-16 23:24:13 +00001901};
1902
1903#pragma mark CommandObjectMultiwordCommandsScript
1904
1905//-------------------------------------------------------------------------
1906// CommandObjectMultiwordCommandsScript
1907//-------------------------------------------------------------------------
1908
Kate Stoneb9c1b512016-09-06 20:57:50 +00001909class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
Enrico Granata223383e2011-08-16 23:24:13 +00001910public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001911 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1912 : CommandObjectMultiword(
1913 interpreter, "command script", "Commands for managing custom "
1914 "commands implemented by "
1915 "interpreter scripts.",
1916 "command script <subcommand> [<subcommand-options>]") {
1917 LoadSubCommand("add", CommandObjectSP(
1918 new CommandObjectCommandsScriptAdd(interpreter)));
1919 LoadSubCommand(
1920 "delete",
1921 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1922 LoadSubCommand(
1923 "clear",
1924 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1925 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1926 interpreter)));
1927 LoadSubCommand(
1928 "import",
1929 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1930 }
Enrico Granata223383e2011-08-16 23:24:13 +00001931
Kate Stoneb9c1b512016-09-06 20:57:50 +00001932 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00001933};
1934
Jim Inghamebc09c32010-07-07 03:36:20 +00001935#pragma mark CommandObjectMultiwordCommands
1936
1937//-------------------------------------------------------------------------
1938// CommandObjectMultiwordCommands
1939//-------------------------------------------------------------------------
1940
Kate Stoneb9c1b512016-09-06 20:57:50 +00001941CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1942 CommandInterpreter &interpreter)
1943 : CommandObjectMultiword(interpreter, "command",
1944 "Commands for managing custom LLDB commands.",
1945 "command <subcommand> [<subcommand-options>]") {
1946 LoadSubCommand("source",
1947 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1948 LoadSubCommand("alias",
1949 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1950 LoadSubCommand("unalias", CommandObjectSP(
1951 new CommandObjectCommandsUnalias(interpreter)));
1952 LoadSubCommand("delete",
1953 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1954 LoadSubCommand(
1955 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1956 LoadSubCommand("history", CommandObjectSP(
1957 new CommandObjectCommandsHistory(interpreter)));
1958 LoadSubCommand(
1959 "script",
1960 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00001961}
1962
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001963CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;