blob: c24e05d0eec63039bbce7f58e5fd85a32ff651dc [file] [log] [blame]
Jim Inghamebc09c32010-07-07 03:36:20 +00001//===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===//
2//
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"
Enrico Granatabe93a352011-08-16 16:49:25 +000020#include "lldb/Core/StringList.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"
Enrico Granata012d4fc2013-06-11 01:26:35 +000026#include "lldb/Interpreter/OptionValueBoolean.h"
Enrico Granata45d0e232016-03-31 01:10:54 +000027#include "lldb/Interpreter/OptionValueString.h"
Enrico Granata7594f142013-06-17 22:51:50 +000028#include "lldb/Interpreter/OptionValueUInt64.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000029#include "lldb/Interpreter/Options.h"
Enrico Granata99f0b8f2011-08-17 01:30:04 +000030#include "lldb/Interpreter/ScriptInterpreter.h"
Jim Inghamebc09c32010-07-07 03:36:20 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Jim Inghamebc09c32010-07-07 03:36:20 +000035//-------------------------------------------------------------------------
36// CommandObjectCommandsSource
37//-------------------------------------------------------------------------
38
Zachary Turner1f0f5b52016-09-22 20:22:55 +000039static OptionDefinition g_history_options[] = {
40 // clang-format off
41 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
42 { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." },
43 { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
44 { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." },
45 // clang-format on
46};
47
Kate Stoneb9c1b512016-09-06 20:57:50 +000048class CommandObjectCommandsHistory : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +000049public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 CommandObjectCommandsHistory(CommandInterpreter &interpreter)
51 : CommandObjectParsed(interpreter, "command history",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000052 "Dump the history of commands in this session.",
53 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 m_options() {}
Jim Ingham5a988412012-06-08 21:56:10 +000055
Kate Stoneb9c1b512016-09-06 20:57:50 +000056 ~CommandObjectCommandsHistory() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +000059
60protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 class CommandOptions : public Options {
62 public:
63 CommandOptions()
64 : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
Jim Inghama5a97eb2011-07-12 03:12:18 +000065 }
Jim Ingham5a988412012-06-08 21:56:10 +000066
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 ~CommandOptions() override = default;
68
69 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
70 ExecutionContext *execution_context) override {
71 Error error;
72 const int short_option = m_getopt_table[option_idx].val;
Zachary Turner8cef4b02016-09-23 17:48:13 +000073 llvm::StringRef option_strref =
74 llvm::StringRef::withNullAsEmpty(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +000075
76 switch (short_option) {
77 case 'c':
Zachary Turner8cef4b02016-09-23 17:48:13 +000078 error =
79 m_count.SetValueFromString(option_strref, eVarSetOperationAssign);
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 break;
81 case 's':
82 if (option_arg && strcmp("end", option_arg) == 0) {
83 m_start_idx.SetCurrentValue(UINT64_MAX);
84 m_start_idx.SetOptionWasSet();
85 } else
Zachary Turner8cef4b02016-09-23 17:48:13 +000086 error = m_start_idx.SetValueFromString(option_strref,
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 eVarSetOperationAssign);
88 break;
89 case 'e':
Zachary Turner8cef4b02016-09-23 17:48:13 +000090 error = m_stop_idx.SetValueFromString(option_strref,
91 eVarSetOperationAssign);
Kate Stoneb9c1b512016-09-06 20:57:50 +000092 break;
93 case 'C':
94 m_clear.SetCurrentValue(true);
95 m_clear.SetOptionWasSet();
96 break;
97 default:
98 error.SetErrorStringWithFormat("unrecognized option '%c'",
99 short_option);
100 break;
101 }
102
103 return error;
104 }
105
106 void OptionParsingStarting(ExecutionContext *execution_context) override {
107 m_start_idx.Clear();
108 m_stop_idx.Clear();
109 m_count.Clear();
110 m_clear.Clear();
111 }
112
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000113 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000114 return llvm::makeArrayRef(g_history_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000115 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116
117 // Instance variables to hold the values for command options.
118
119 OptionValueUInt64 m_start_idx;
120 OptionValueUInt64 m_stop_idx;
121 OptionValueUInt64 m_count;
122 OptionValueBoolean m_clear;
123 };
124
125 bool DoExecute(Args &command, CommandReturnObject &result) override {
126 if (m_options.m_clear.GetCurrentValue() &&
127 m_options.m_clear.OptionWasSet()) {
128 m_interpreter.GetCommandHistory().Clear();
129 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
130 } else {
131 if (m_options.m_start_idx.OptionWasSet() &&
132 m_options.m_stop_idx.OptionWasSet() &&
133 m_options.m_count.OptionWasSet()) {
134 result.AppendError("--count, --start-index and --end-index cannot be "
135 "all specified in the same invocation");
136 result.SetStatus(lldb::eReturnStatusFailed);
137 } else {
138 std::pair<bool, uint64_t> start_idx(
139 m_options.m_start_idx.OptionWasSet(),
140 m_options.m_start_idx.GetCurrentValue());
141 std::pair<bool, uint64_t> stop_idx(
142 m_options.m_stop_idx.OptionWasSet(),
143 m_options.m_stop_idx.GetCurrentValue());
144 std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
145 m_options.m_count.GetCurrentValue());
146
147 const CommandHistory &history(m_interpreter.GetCommandHistory());
148
149 if (start_idx.first && start_idx.second == UINT64_MAX) {
150 if (count.first) {
151 start_idx.second = history.GetSize() - count.second;
152 stop_idx.second = history.GetSize() - 1;
153 } else if (stop_idx.first) {
154 start_idx.second = stop_idx.second;
155 stop_idx.second = history.GetSize() - 1;
156 } else {
157 start_idx.second = 0;
158 stop_idx.second = history.GetSize() - 1;
159 }
160 } else {
161 if (!start_idx.first && !stop_idx.first && !count.first) {
162 start_idx.second = 0;
163 stop_idx.second = history.GetSize() - 1;
164 } else if (start_idx.first) {
165 if (count.first) {
166 stop_idx.second = start_idx.second + count.second - 1;
167 } else if (!stop_idx.first) {
168 stop_idx.second = history.GetSize() - 1;
169 }
170 } else if (stop_idx.first) {
171 if (count.first) {
172 if (stop_idx.second >= count.second)
173 start_idx.second = stop_idx.second - count.second + 1;
174 else
175 start_idx.second = 0;
176 }
177 } else /* if (count.first) */
178 {
179 start_idx.second = 0;
180 stop_idx.second = count.second - 1;
181 }
182 }
183 history.Dump(result.GetOutputStream(), start_idx.second,
184 stop_idx.second);
185 }
186 }
187 return result.Succeeded();
188 }
189
190 CommandOptions m_options;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000191};
192
Jim Inghama5a97eb2011-07-12 03:12:18 +0000193//-------------------------------------------------------------------------
194// CommandObjectCommandsSource
195//-------------------------------------------------------------------------
196
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000197static OptionDefinition g_source_options[] = {
198 // clang-format off
199 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
200 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
201 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
202 // clang-format on
203};
204
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205class CommandObjectCommandsSource : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000206public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000207 CommandObjectCommandsSource(CommandInterpreter &interpreter)
208 : CommandObjectParsed(
209 interpreter, "command source",
210 "Read and execute LLDB commands from the file <filename>.",
211 nullptr),
212 m_options() {
213 CommandArgumentEntry arg;
214 CommandArgumentData file_arg;
Jim Ingham5a988412012-06-08 21:56:10 +0000215
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216 // Define the first (and only) variant of this arg.
217 file_arg.arg_type = eArgTypeFilename;
218 file_arg.arg_repetition = eArgRepeatPlain;
Jim Ingham5a988412012-06-08 21:56:10 +0000219
Kate Stoneb9c1b512016-09-06 20:57:50 +0000220 // There is only one variant this argument could be; put it into the
221 // argument entry.
222 arg.push_back(file_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +0000223
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224 // Push the data for the first argument into the m_arguments vector.
225 m_arguments.push_back(arg);
226 }
Jim Ingham5a988412012-06-08 21:56:10 +0000227
Kate Stoneb9c1b512016-09-06 20:57:50 +0000228 ~CommandObjectCommandsSource() override = default;
229
230 const char *GetRepeatCommand(Args &current_command_args,
231 uint32_t index) override {
232 return "";
233 }
234
235 int HandleArgumentCompletion(Args &input, int &cursor_index,
236 int &cursor_char_position,
237 OptionElementVector &opt_element_vector,
238 int match_start_point, int max_return_elements,
239 bool &word_complete,
240 StringList &matches) override {
241 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
242 completion_str.erase(cursor_char_position);
243
244 CommandCompletions::InvokeCommonCompletionCallbacks(
245 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
246 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
247 word_complete, matches);
248 return matches.GetSize();
249 }
250
251 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +0000252
253protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000254 class CommandOptions : public Options {
255 public:
256 CommandOptions()
257 : Options(), m_stop_on_error(true), m_silent_run(false),
258 m_stop_on_continue(true) {}
Jim Inghame16c50a2011-02-18 00:54:25 +0000259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260 ~CommandOptions() override = default;
Jim Inghame16c50a2011-02-18 00:54:25 +0000261
Kate Stoneb9c1b512016-09-06 20:57:50 +0000262 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
263 ExecutionContext *execution_context) override {
264 Error error;
265 const int short_option = m_getopt_table[option_idx].val;
Zachary Turner8cef4b02016-09-23 17:48:13 +0000266 llvm::StringRef option_strref =
267 llvm::StringRef::withNullAsEmpty(option_arg);
Greg Clayton340b0302014-02-05 17:57:57 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 switch (short_option) {
270 case 'e':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000271 error = m_stop_on_error.SetValueFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000273
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 case 'c':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000275 error = m_stop_on_continue.SetValueFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000277
Kate Stoneb9c1b512016-09-06 20:57:50 +0000278 case 's':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000279 error = m_silent_run.SetValueFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 break;
Jim Inghame16c50a2011-02-18 00:54:25 +0000281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 default:
283 error.SetErrorStringWithFormat("unrecognized option '%c'",
284 short_option);
285 break;
286 }
Jim Inghame16c50a2011-02-18 00:54:25 +0000287
Kate Stoneb9c1b512016-09-06 20:57:50 +0000288 return error;
Jim Inghamebc09c32010-07-07 03:36:20 +0000289 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000290
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 void OptionParsingStarting(ExecutionContext *execution_context) override {
292 m_stop_on_error.Clear();
293 m_silent_run.Clear();
294 m_stop_on_continue.Clear();
295 }
296
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000297 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000298 return llvm::makeArrayRef(g_source_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000299 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300
301 // Instance variables to hold the values for command options.
302
303 OptionValueBoolean m_stop_on_error;
304 OptionValueBoolean m_silent_run;
305 OptionValueBoolean m_stop_on_continue;
306 };
307
308 bool DoExecute(Args &command, CommandReturnObject &result) override {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000309 if (command.GetArgumentCount() == 1) {
310 llvm::StringRef filename = command.GetArgumentAtIndex(0);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311
312 FileSpec cmd_file(filename, true);
313 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
314
315 // If any options were set, then use them
316 if (m_options.m_stop_on_error.OptionWasSet() ||
317 m_options.m_silent_run.OptionWasSet() ||
318 m_options.m_stop_on_continue.OptionWasSet()) {
319 // Use user set settings
320 CommandInterpreterRunOptions options;
321 options.SetStopOnContinue(
322 m_options.m_stop_on_continue.GetCurrentValue());
323 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
324 options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
325 options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
326
327 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
328 result);
329 } else {
330 // No options were set, inherit any settings from nested "command
331 // source" commands,
332 // or set to sane default settings...
333 CommandInterpreterRunOptions options;
334 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
335 result);
336 }
337 } else {
338 result.AppendErrorWithFormat(
339 "'%s' takes exactly one executable filename argument.\n",
Zachary Turnera4496982016-10-05 21:14:38 +0000340 GetCommandName().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341 result.SetStatus(eReturnStatusFailed);
342 }
343 return result.Succeeded();
344 }
345
346 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000347};
348
349#pragma mark CommandObjectCommandsAlias
350//-------------------------------------------------------------------------
351// CommandObjectCommandsAlias
352//-------------------------------------------------------------------------
353
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000354static OptionDefinition g_alias_options[] = {
355 // clang-format off
356 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
357 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
358 // clang-format on
359};
360
Kate Stoneb9c1b512016-09-06 20:57:50 +0000361static const char *g_python_command_instructions =
362 "Enter your Python command(s). Type 'DONE' to end.\n"
363 "You must define a Python function with this signature:\n"
364 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000365
Kate Stoneb9c1b512016-09-06 20:57:50 +0000366class CommandObjectCommandsAlias : public CommandObjectRaw {
Enrico Granata45d0e232016-03-31 01:10:54 +0000367protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000368 class CommandOptions : public OptionGroup {
369 public:
370 CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
Enrico Granata45d0e232016-03-31 01:10:54 +0000371
Kate Stoneb9c1b512016-09-06 20:57:50 +0000372 ~CommandOptions() override = default;
373
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000374 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000375 return llvm::makeArrayRef(g_alias_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000376 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377
Zachary Turner8cef4b02016-09-23 17:48:13 +0000378 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379 ExecutionContext *execution_context) override {
380 Error error;
381
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000382 const int short_option = GetDefinitions()[option_idx].short_option;
Zachary Turner8cef4b02016-09-23 17:48:13 +0000383 std::string option_str(option_value);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384
385 switch (short_option) {
386 case 'h':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000387 m_help.SetCurrentValue(option_str);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388 m_help.SetOptionWasSet();
389 break;
390
391 case 'H':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000392 m_long_help.SetCurrentValue(option_str);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000393 m_long_help.SetOptionWasSet();
394 break;
395
396 default:
397 error.SetErrorStringWithFormat("invalid short option character '%c'",
398 short_option);
399 break;
400 }
401
402 return error;
Enrico Granata45d0e232016-03-31 01:10:54 +0000403 }
Zachary Turner8cef4b02016-09-23 17:48:13 +0000404 Error SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
Enrico Granata45d0e232016-03-31 01:10:54 +0000405
Kate Stoneb9c1b512016-09-06 20:57:50 +0000406 void OptionParsingStarting(ExecutionContext *execution_context) override {
407 m_help.Clear();
408 m_long_help.Clear();
409 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000410
Kate Stoneb9c1b512016-09-06 20:57:50 +0000411 OptionValueString m_help;
412 OptionValueString m_long_help;
413 };
414
415 OptionGroupOptions m_option_group;
416 CommandOptions m_command_options;
417
418public:
419 Options *GetOptions() override { return &m_option_group; }
420
421 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
422 : CommandObjectRaw(
423 interpreter, "command alias",
Zachary Turnera4496982016-10-05 21:14:38 +0000424 "Define a custom command in terms of an existing command."),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425 m_option_group(), m_command_options() {
426 m_option_group.Append(&m_command_options);
427 m_option_group.Finalize();
428
429 SetHelpLong(
430 "'alias' allows the user to create a short-cut or abbreviation for long \
Kate Stoneea671fb2015-07-14 05:48:36 +0000431commands, multi-word commands, and commands that take particular options. \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432Below are some simple examples of how one might use the 'alias' command:"
433 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000434
435(lldb) command alias sc script
436
437 Creates the abbreviation 'sc' for the 'script' command.
438
439(lldb) command alias bp breakpoint
440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441)"
442 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
Kate Stoneea671fb2015-07-14 05:48:36 +0000443breakpoint commands are two-word commands, the user would still need to \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000444enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
445 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000446
447(lldb) command alias bpl breakpoint list
448
449 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
450
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451)"
452 "An alias can include some options for the command, with the values either \
Kate Stoneea671fb2015-07-14 05:48:36 +0000453filled in at the time the alias is created, or specified as positional \
454arguments, to be filled in when the alias is invoked. The following example \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455shows how to create aliases with options:"
456 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000457
458(lldb) command alias bfl breakpoint set -f %1 -l %2
459
Kate Stoneb9c1b512016-09-06 20:57:50 +0000460)"
461 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
Kate Stoneea671fb2015-07-14 05:48:36 +0000462options already part of the alias. So if the user wants to set a breakpoint \
463by file and line without explicitly having to use the -f and -l options, the \
464user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
465for the actual arguments that will be passed when the alias command is used. \
466The number in the placeholder refers to the position/order the actual value \
467occupies when the alias is used. All the occurrences of '%1' in the alias \
468will be replaced with the first argument, all the occurrences of '%2' in the \
469alias will be replaced with the second argument, and so on. This also allows \
470actual arguments to be used multiple times within an alias (see 'process \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471launch' example below)."
472 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000473
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474)"
475 "Note: the positional arguments must substitute as whole words in the resultant \
Kate Stoneea671fb2015-07-14 05:48:36 +0000476command, so you can't at present do something like this to append the file extension \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477\".cpp\":"
478 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000479
480(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
481
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482)"
483 "For more complex aliasing, use the \"command regex\" command instead. In the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000484'bfl' case above, the actual file value will be filled in with the first argument \
485following 'bfl' and the actual line number value will be filled in with the second \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486argument. The user would use this alias as follows:"
487 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000488
489(lldb) command alias bfl breakpoint set -f %1 -l %2
490(lldb) bfl my-file.c 137
491
492This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
493
494Another example:
495
496(lldb) command alias pltty process launch -s -o %1 -e %1
497(lldb) pltty /dev/tty0
498
499 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
500
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501)"
502 "If the user always wanted to pass the same value to a particular option, the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000503alias could be defined with that value directly in the alias as a constant, \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000504rather than using a positional placeholder:"
505 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000506
507(lldb) command alias bl3 breakpoint set -f %1 -l 3
508
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509 Always sets a breakpoint on line 3 of whatever file is indicated.)");
Jim Inghamebc09c32010-07-07 03:36:20 +0000510
Kate Stoneb9c1b512016-09-06 20:57:50 +0000511 CommandArgumentEntry arg1;
512 CommandArgumentEntry arg2;
513 CommandArgumentEntry arg3;
514 CommandArgumentData alias_arg;
515 CommandArgumentData cmd_arg;
516 CommandArgumentData options_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000517
Kate Stoneb9c1b512016-09-06 20:57:50 +0000518 // Define the first (and only) variant of this arg.
519 alias_arg.arg_type = eArgTypeAliasName;
520 alias_arg.arg_repetition = eArgRepeatPlain;
521
522 // There is only one variant this argument could be; put it into the
523 // argument entry.
524 arg1.push_back(alias_arg);
525
526 // Define the first (and only) variant of this arg.
527 cmd_arg.arg_type = eArgTypeCommandName;
528 cmd_arg.arg_repetition = eArgRepeatPlain;
529
530 // There is only one variant this argument could be; put it into the
531 // argument entry.
532 arg2.push_back(cmd_arg);
533
534 // Define the first (and only) variant of this arg.
535 options_arg.arg_type = eArgTypeAliasOptions;
536 options_arg.arg_repetition = eArgRepeatOptional;
537
538 // There is only one variant this argument could be; put it into the
539 // argument entry.
540 arg3.push_back(options_arg);
541
542 // Push the data for the first argument into the m_arguments vector.
543 m_arguments.push_back(arg1);
544 m_arguments.push_back(arg2);
545 m_arguments.push_back(arg3);
546 }
547
548 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000549
Jim Ingham5a988412012-06-08 21:56:10 +0000550protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000551 bool DoExecute(const char *raw_command_line,
552 CommandReturnObject &result) override {
553 if (!raw_command_line || !raw_command_line[0]) {
554 result.AppendError("'command alias' requires at least two arguments");
555 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000556 }
557
Kate Stoneb9c1b512016-09-06 20:57:50 +0000558 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
559 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
Caroline Ticeca90c472011-05-06 21:37:15 +0000560
Kate Stoneb9c1b512016-09-06 20:57:50 +0000561 const char *remainder = nullptr;
Enrico Granata212130a2016-03-08 05:37:15 +0000562
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563 if (raw_command_line[0] == '-') {
564 // We have some options and these options MUST end with --.
565 const char *end_options = nullptr;
566 const char *s = raw_command_line;
567 while (s && s[0]) {
568 end_options = ::strstr(s, "--");
569 if (end_options) {
570 end_options += 2; // Get past the "--"
571 if (::isspace(end_options[0])) {
572 remainder = end_options;
573 while (::isspace(*remainder))
574 ++remainder;
575 break;
576 }
577 }
578 s = end_options;
579 }
580
581 if (end_options) {
582 Args args(
583 llvm::StringRef(raw_command_line, end_options - raw_command_line));
584 if (!ParseOptions(args, result))
585 return false;
586
587 Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
588 if (error.Fail()) {
589 result.AppendError(error.AsCString());
590 result.SetStatus(eReturnStatusFailed);
591 return false;
592 }
593 }
Caroline Tice844d2302010-12-09 22:52:49 +0000594 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000595 if (nullptr == remainder)
596 remainder = raw_command_line;
Jim Inghamebc09c32010-07-07 03:36:20 +0000597
Kate Stoneb9c1b512016-09-06 20:57:50 +0000598 std::string raw_command_string(remainder);
599 Args args(raw_command_string.c_str());
Jim Inghamebc09c32010-07-07 03:36:20 +0000600
Zachary Turner11eb9c62016-10-05 20:03:37 +0000601 if (args.GetArgumentCount() < 2) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000602 result.AppendError("'command alias' requires at least two arguments");
603 result.SetStatus(eReturnStatusFailed);
604 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000605 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000606
607 // Get the alias command.
608
Zachary Turner11eb9c62016-10-05 20:03:37 +0000609 // TODO: Convert this function to use StringRef. Requires converting
610 // GetCommandObjectForCommand.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000611 const std::string alias_command = args.GetArgumentAtIndex(0);
612 if (alias_command.size() > 1 && alias_command[0] == '-') {
613 result.AppendError("aliases starting with a dash are not supported");
614 if (alias_command == "--help" || alias_command == "--long-help") {
615 result.AppendWarning("if trying to pass options to 'command alias' add "
616 "a -- at the end of the options");
617 }
618 result.SetStatus(eReturnStatusFailed);
619 return false;
620 }
621
622 // Strip the new alias name off 'raw_command_string' (leave it on args,
623 // which gets passed to 'Execute', which
624 // does the stripping itself.
625 size_t pos = raw_command_string.find(alias_command);
626 if (pos == 0) {
627 raw_command_string = raw_command_string.substr(alias_command.size());
628 pos = raw_command_string.find_first_not_of(' ');
629 if ((pos != std::string::npos) && (pos > 0))
630 raw_command_string = raw_command_string.substr(pos);
631 } else {
632 result.AppendError("Error parsing command string. No alias created.");
633 result.SetStatus(eReturnStatusFailed);
634 return false;
635 }
636
637 // Verify that the command is alias-able.
638 if (m_interpreter.CommandExists(alias_command.c_str())) {
639 result.AppendErrorWithFormat(
640 "'%s' is a permanent debugger command and cannot be redefined.\n",
641 alias_command.c_str());
642 result.SetStatus(eReturnStatusFailed);
643 return false;
644 }
645
646 // Get CommandObject that is being aliased. The command name is read from
647 // the front of raw_command_string.
648 // raw_command_string is returned with the name of the command object
649 // stripped off the front.
650 std::string original_raw_command_string(raw_command_string);
651 CommandObject *cmd_obj =
652 m_interpreter.GetCommandObjectForCommand(raw_command_string);
653
654 if (!cmd_obj) {
655 result.AppendErrorWithFormat("invalid command given to 'command alias'. "
656 "'%s' does not begin with a valid command."
657 " No alias created.",
658 original_raw_command_string.c_str());
659 result.SetStatus(eReturnStatusFailed);
660 return false;
661 } else if (!cmd_obj->WantsRawCommandString()) {
662 // Note that args was initialized with the original command, and has not
663 // been updated to this point.
664 // Therefore can we pass it to the version of Execute that does not
665 // need/expect raw input in the alias.
666 return HandleAliasingNormalCommand(args, result);
667 } else {
668 return HandleAliasingRawCommand(alias_command, raw_command_string,
669 *cmd_obj, result);
670 }
671 return result.Succeeded();
672 }
673
674 bool HandleAliasingRawCommand(const std::string &alias_command,
675 std::string &raw_command_string,
676 CommandObject &cmd_obj,
677 CommandReturnObject &result) {
678 // Verify & handle any options/arguments passed to the alias command
679
680 OptionArgVectorSP option_arg_vector_sp =
681 OptionArgVectorSP(new OptionArgVector);
682
683 if (CommandObjectSP cmd_obj_sp =
684 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
685 if (m_interpreter.AliasExists(alias_command.c_str()) ||
686 m_interpreter.UserCommandExists(alias_command.c_str())) {
687 result.AppendWarningWithFormat(
688 "Overwriting existing definition for '%s'.\n",
689 alias_command.c_str());
690 }
691 if (CommandAlias *alias = m_interpreter.AddAlias(
692 alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) {
693 if (m_command_options.m_help.OptionWasSet())
694 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
695 if (m_command_options.m_long_help.OptionWasSet())
696 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
697 result.SetStatus(eReturnStatusSuccessFinishNoResult);
698 } else {
699 result.AppendError("Unable to create requested alias.\n");
700 result.SetStatus(eReturnStatusFailed);
701 }
702
703 } else {
704 result.AppendError("Unable to create requested alias.\n");
705 result.SetStatus(eReturnStatusFailed);
706 }
707
708 return result.Succeeded();
709 }
710
711 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
712 size_t argc = args.GetArgumentCount();
713
714 if (argc < 2) {
715 result.AppendError("'command alias' requires at least two arguments");
716 result.SetStatus(eReturnStatusFailed);
717 return false;
718 }
719
Zachary Turner11eb9c62016-10-05 20:03:37 +0000720 // TODO: Convert these to StringRefs. Should convert other dependent
721 // functions (CommandExists, UserCommandExists, AliasExists, AddAlias,
722 // etc at the same time.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000723 const std::string alias_command = args.GetArgumentAtIndex(0);
724 const std::string actual_command = args.GetArgumentAtIndex(1);
725
726 args.Shift(); // Shift the alias command word off the argument vector.
727 args.Shift(); // Shift the old command word off the argument vector.
728
729 // Verify that the command is alias'able, and get the appropriate command
730 // object.
731
732 if (m_interpreter.CommandExists(alias_command.c_str())) {
733 result.AppendErrorWithFormat(
734 "'%s' is a permanent debugger command and cannot be redefined.\n",
735 alias_command.c_str());
736 result.SetStatus(eReturnStatusFailed);
737 } else {
738 CommandObjectSP command_obj_sp(
Zachary Turnera4496982016-10-05 21:14:38 +0000739 m_interpreter.GetCommandSPExact(actual_command, true));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000740 CommandObjectSP subcommand_obj_sp;
741 bool use_subcommand = false;
742 if (command_obj_sp) {
743 CommandObject *cmd_obj = command_obj_sp.get();
744 CommandObject *sub_cmd_obj = nullptr;
745 OptionArgVectorSP option_arg_vector_sp =
746 OptionArgVectorSP(new OptionArgVector);
747
Zachary Turner11eb9c62016-10-05 20:03:37 +0000748 while (cmd_obj->IsMultiwordObject() && !args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000749 if (argc >= 3) {
Zachary Turnera4496982016-10-05 21:14:38 +0000750 const std::string sub_command = args.GetArgumentAtIndex(0);
Zachary Turner11eb9c62016-10-05 20:03:37 +0000751 assert(!sub_command.empty());
752 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command.data());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000753 if (subcommand_obj_sp) {
754 sub_cmd_obj = subcommand_obj_sp.get();
755 use_subcommand = true;
756 args.Shift(); // Shift the sub_command word off the argument
757 // vector.
758 cmd_obj = sub_cmd_obj;
759 } else {
760 result.AppendErrorWithFormat(
761 "'%s' is not a valid sub-command of '%s'. "
762 "Unable to create alias.\n",
Zachary Turnera4496982016-10-05 21:14:38 +0000763 sub_command.c_str(), actual_command.c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000764 result.SetStatus(eReturnStatusFailed);
765 return false;
766 }
767 }
768 }
769
770 // Verify & handle any options/arguments passed to the alias command
771
772 std::string args_string;
773
Zachary Turner11eb9c62016-10-05 20:03:37 +0000774 if (!args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000775 CommandObjectSP tmp_sp =
776 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
777 if (use_subcommand)
778 tmp_sp = m_interpreter.GetCommandSPExact(
779 sub_cmd_obj->GetCommandName(), false);
780
781 args.GetCommandString(args_string);
782 }
783
784 if (m_interpreter.AliasExists(alias_command.c_str()) ||
785 m_interpreter.UserCommandExists(alias_command.c_str())) {
786 result.AppendWarningWithFormat(
787 "Overwriting existing definition for '%s'.\n",
788 alias_command.c_str());
789 }
790
791 if (CommandAlias *alias = m_interpreter.AddAlias(
792 alias_command.c_str(),
793 use_subcommand ? subcommand_obj_sp : command_obj_sp,
794 args_string.c_str())) {
795 if (m_command_options.m_help.OptionWasSet())
796 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
797 if (m_command_options.m_long_help.OptionWasSet())
798 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
799 result.SetStatus(eReturnStatusSuccessFinishNoResult);
800 } else {
801 result.AppendError("Unable to create requested alias.\n");
802 result.SetStatus(eReturnStatusFailed);
803 return false;
804 }
805 } else {
806 result.AppendErrorWithFormat("'%s' is not an existing command.\n",
807 actual_command.c_str());
808 result.SetStatus(eReturnStatusFailed);
809 return false;
810 }
811 }
812
813 return result.Succeeded();
814 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000815};
816
817#pragma mark CommandObjectCommandsUnalias
818//-------------------------------------------------------------------------
819// CommandObjectCommandsUnalias
820//-------------------------------------------------------------------------
821
Kate Stoneb9c1b512016-09-06 20:57:50 +0000822class CommandObjectCommandsUnalias : public CommandObjectParsed {
Jim Inghamebc09c32010-07-07 03:36:20 +0000823public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000824 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
825 : CommandObjectParsed(
826 interpreter, "command unalias",
827 "Delete one or more custom commands defined by 'command alias'.",
828 nullptr) {
829 CommandArgumentEntry arg;
830 CommandArgumentData alias_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000831
Kate Stoneb9c1b512016-09-06 20:57:50 +0000832 // Define the first (and only) variant of this arg.
833 alias_arg.arg_type = eArgTypeAliasName;
834 alias_arg.arg_repetition = eArgRepeatPlain;
835
836 // There is only one variant this argument could be; put it into the
837 // argument entry.
838 arg.push_back(alias_arg);
839
840 // Push the data for the first argument into the m_arguments vector.
841 m_arguments.push_back(arg);
842 }
843
844 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000845
Jim Ingham5a988412012-06-08 21:56:10 +0000846protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000847 bool DoExecute(Args &args, CommandReturnObject &result) override {
848 CommandObject::CommandMap::iterator pos;
849 CommandObject *cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000850
Zachary Turner11eb9c62016-10-05 20:03:37 +0000851 if (args.empty()) {
852 result.AppendError("must call 'unalias' with a valid alias");
853 result.SetStatus(eReturnStatusFailed);
854 return false;
855 }
856
857 // TODO: Convert this function to return a StringRef. Should also convert
858 // dependent functions GetCommandObject, CommandExists, RemoveAlias,
859 // AliasExists, etc.
860 const char *command_name = args.GetArgumentAtIndex(0);
861 cmd_obj = m_interpreter.GetCommandObject(command_name);
862 if (cmd_obj) {
863 if (m_interpreter.CommandExists(command_name)) {
864 if (cmd_obj->IsRemovable()) {
865 result.AppendErrorWithFormat(
866 "'%s' is not an alias, it is a debugger command which can be "
867 "removed using the 'command delete' command.\n",
868 command_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000869 } else {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000870 result.AppendErrorWithFormat(
871 "'%s' is a permanent debugger command and cannot be removed.\n",
872 command_name);
Jim Inghamebc09c32010-07-07 03:36:20 +0000873 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000874 result.SetStatus(eReturnStatusFailed);
Zachary Turner11eb9c62016-10-05 20:03:37 +0000875 } else {
876 if (!m_interpreter.RemoveAlias(command_name)) {
877 if (m_interpreter.AliasExists(command_name))
878 result.AppendErrorWithFormat(
879 "Error occurred while attempting to unalias '%s'.\n",
880 command_name);
881 else
882 result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
883 command_name);
884 result.SetStatus(eReturnStatusFailed);
885 } else
886 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000887 }
888 } else {
Zachary Turner11eb9c62016-10-05 20:03:37 +0000889 result.AppendErrorWithFormat(
890 "'%s' is not a known command.\nTry 'help' to see a "
891 "current list of commands.\n",
892 command_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000893 result.SetStatus(eReturnStatusFailed);
Jim Inghamebc09c32010-07-07 03:36:20 +0000894 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000895
896 return result.Succeeded();
897 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000898};
899
Greg Claytonb5472782015-01-09 19:08:20 +0000900#pragma mark CommandObjectCommandsDelete
901//-------------------------------------------------------------------------
902// CommandObjectCommandsDelete
903//-------------------------------------------------------------------------
904
Kate Stoneb9c1b512016-09-06 20:57:50 +0000905class CommandObjectCommandsDelete : public CommandObjectParsed {
Greg Claytonb5472782015-01-09 19:08:20 +0000906public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000907 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
908 : CommandObjectParsed(
909 interpreter, "command delete",
910 "Delete one or more custom commands defined by 'command regex'.",
911 nullptr) {
912 CommandArgumentEntry arg;
913 CommandArgumentData alias_arg;
Greg Claytonb5472782015-01-09 19:08:20 +0000914
Kate Stoneb9c1b512016-09-06 20:57:50 +0000915 // Define the first (and only) variant of this arg.
916 alias_arg.arg_type = eArgTypeCommandName;
917 alias_arg.arg_repetition = eArgRepeatPlain;
Greg Claytonb5472782015-01-09 19:08:20 +0000918
Kate Stoneb9c1b512016-09-06 20:57:50 +0000919 // There is only one variant this argument could be; put it into the
920 // argument entry.
921 arg.push_back(alias_arg);
Greg Claytonb5472782015-01-09 19:08:20 +0000922
Kate Stoneb9c1b512016-09-06 20:57:50 +0000923 // Push the data for the first argument into the m_arguments vector.
924 m_arguments.push_back(arg);
925 }
Greg Claytonb5472782015-01-09 19:08:20 +0000926
Kate Stoneb9c1b512016-09-06 20:57:50 +0000927 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +0000928
929protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000930 bool DoExecute(Args &args, CommandReturnObject &result) override {
931 CommandObject::CommandMap::iterator pos;
Greg Claytonb5472782015-01-09 19:08:20 +0000932
Zachary Turner11eb9c62016-10-05 20:03:37 +0000933 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000934 result.AppendErrorWithFormat("must call '%s' with one or more valid user "
935 "defined regular expression command names",
Zachary Turnera4496982016-10-05 21:14:38 +0000936 GetCommandName().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000937 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000938 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000939
Zachary Turner11eb9c62016-10-05 20:03:37 +0000940 // TODO: Convert this to accept a stringRef.
941 const char *command_name = args.GetArgumentAtIndex(0);
942 if (m_interpreter.CommandExists(command_name)) {
943 if (m_interpreter.RemoveCommand(command_name)) {
944 result.SetStatus(eReturnStatusSuccessFinishNoResult);
945 } else {
946 result.AppendErrorWithFormat(
947 "'%s' is a permanent debugger command and cannot be removed.\n",
948 command_name);
949 result.SetStatus(eReturnStatusFailed);
950 }
951 } else {
952 StreamString error_msg_stream;
953 const bool generate_apropos = true;
954 const bool generate_type_lookup = false;
955 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
956 &error_msg_stream, command_name, nullptr, nullptr, generate_apropos,
957 generate_type_lookup);
958 result.AppendErrorWithFormat("%s", error_msg_stream.GetData());
959 result.SetStatus(eReturnStatusFailed);
960 }
961
Kate Stoneb9c1b512016-09-06 20:57:50 +0000962 return result.Succeeded();
963 }
Greg Claytonb5472782015-01-09 19:08:20 +0000964};
965
Greg Claytonde164aa2011-04-20 16:37:46 +0000966//-------------------------------------------------------------------------
967// CommandObjectCommandsAddRegex
968//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000969
970static OptionDefinition g_regex_options[] = {
971 // clang-format off
972 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
973 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
974 // clang-format on
975};
976
Jim Ingham5a988412012-06-08 21:56:10 +0000977#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +0000978
Kate Stoneb9c1b512016-09-06 20:57:50 +0000979class CommandObjectCommandsAddRegex : public CommandObjectParsed,
980 public IOHandlerDelegateMultiline {
Greg Claytonde164aa2011-04-20 16:37:46 +0000981public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000982 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
983 : CommandObjectParsed(
984 interpreter, "command regex", "Define a custom command in terms of "
985 "existing commands by matching "
986 "regular expressions.",
987 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
988 IOHandlerDelegateMultiline("",
989 IOHandlerDelegate::Completion::LLDBCommand),
990 m_options() {
991 SetHelpLong(
992 R"(
993)"
994 "This command allows the user to create powerful regular expression commands \
Kate Stoneea671fb2015-07-14 05:48:36 +0000995with substitutions. The regular expressions and substitutions are specified \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000996using the regular expression substitution format of:"
997 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000998
999 s/<regex>/<subst>/
1000
Kate Stoneb9c1b512016-09-06 20:57:50 +00001001)"
1002 "<regex> is a regular expression that can use parenthesis to capture regular \
Kate Stoneea671fb2015-07-14 05:48:36 +00001003expression input and substitute the captured matches in the output using %1 \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001004for the first match, %2 for the second, and so on."
1005 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001006
Kate Stoneb9c1b512016-09-06 20:57:50 +00001007)"
1008 "The regular expressions can all be specified on the command line if more than \
Kate Stoneea671fb2015-07-14 05:48:36 +00001009one argument is provided. If just the command name is provided on the command \
1010line, then the regular expressions and substitutions can be entered on separate \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011lines, followed by an empty line to terminate the command definition."
1012 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001013
1014EXAMPLES
1015
Kate Stoneb9c1b512016-09-06 20:57:50 +00001016)"
1017 "The following example will define a regular expression command named 'f' that \
Kate Stoneea671fb2015-07-14 05:48:36 +00001018will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001019a number follows 'f':"
1020 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001021
Kate Stoneb9c1b512016-09-06 20:57:50 +00001022 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1023 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001024
Kate Stoneb9c1b512016-09-06 20:57:50 +00001025 ~CommandObjectCommandsAddRegex() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001026
Jim Ingham5a988412012-06-08 21:56:10 +00001027protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001028 void IOHandlerActivated(IOHandler &io_handler) override {
1029 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1030 if (output_sp) {
1031 output_sp->PutCString("Enter one of more sed substitution commands in "
1032 "the form: 's/<regex>/<subst>/'.\nTerminate the "
1033 "substitution list with an empty line.\n");
1034 output_sp->Flush();
1035 }
1036 }
1037
1038 void IOHandlerInputComplete(IOHandler &io_handler,
1039 std::string &data) override {
1040 io_handler.SetIsDone(true);
1041 if (m_regex_cmd_ap) {
1042 StringList lines;
1043 if (lines.SplitIntoLines(data)) {
1044 const size_t num_lines = lines.GetSize();
1045 bool check_only = false;
1046 for (size_t i = 0; i < num_lines; ++i) {
1047 llvm::StringRef bytes_strref(lines[i]);
1048 Error error = AppendRegexSubstitution(bytes_strref, check_only);
1049 if (error.Fail()) {
1050 if (!m_interpreter.GetDebugger()
1051 .GetCommandInterpreter()
1052 .GetBatchCommandMode()) {
1053 StreamSP out_stream =
1054 m_interpreter.GetDebugger().GetAsyncOutputStream();
1055 out_stream->Printf("error: %s\n", error.AsCString());
1056 }
1057 }
Greg Clayton44d93782014-01-27 23:43:24 +00001058 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001059 }
1060 if (m_regex_cmd_ap->HasRegexEntries()) {
1061 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1062 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1063 }
1064 }
1065 }
1066
1067 bool DoExecute(Args &command, CommandReturnObject &result) override {
1068 const size_t argc = command.GetArgumentCount();
1069 if (argc == 0) {
1070 result.AppendError("usage: 'command regex <command-name> "
1071 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1072 result.SetStatus(eReturnStatusFailed);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001073 return false;
1074 }
1075
1076 Error error;
1077 const char *name = command.GetArgumentAtIndex(0);
1078 m_regex_cmd_ap.reset(
1079 new CommandObjectRegexCommand(m_interpreter, name, m_options.GetHelp(),
1080 m_options.GetSyntax(), 10, 0, true));
1081
1082 if (argc == 1) {
1083 Debugger &debugger = m_interpreter.GetDebugger();
1084 bool color_prompt = debugger.GetUseColor();
1085 const bool multiple_lines = true; // Get multiple lines
1086 IOHandlerSP io_handler_sp(new IOHandlerEditline(
1087 debugger, IOHandler::Type::Other,
1088 "lldb-regex", // Name of input reader for history
1089 llvm::StringRef("> "), // Prompt
1090 llvm::StringRef(), // Continuation prompt
1091 multiple_lines, color_prompt,
1092 0, // Don't show line numbers
1093 *this));
1094
1095 if (io_handler_sp) {
1096 debugger.PushIOHandler(io_handler_sp);
1097 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1098 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001099 } else {
Zachary Turner11eb9c62016-10-05 20:03:37 +00001100 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) {
1101 llvm::StringRef arg_strref(command.GetArgumentAtIndex(arg_idx));
1102 bool check_only = false;
1103 error = AppendRegexSubstitution(arg_strref, check_only);
1104 if (error.Fail())
1105 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001106 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001107
1108 if (error.Success()) {
1109 AddRegexCommandToInterpreter();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001110 }
Greg Clayton44d93782014-01-27 23:43:24 +00001111 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001112 if (error.Fail()) {
1113 result.AppendError(error.AsCString());
1114 result.SetStatus(eReturnStatusFailed);
1115 }
Greg Clayton44d93782014-01-27 23:43:24 +00001116
Kate Stoneb9c1b512016-09-06 20:57:50 +00001117 return result.Succeeded();
1118 }
1119
1120 Error AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1121 bool check_only) {
1122 Error error;
1123
1124 if (!m_regex_cmd_ap) {
1125 error.SetErrorStringWithFormat(
1126 "invalid regular expression command object for: '%.*s'",
1127 (int)regex_sed.size(), regex_sed.data());
1128 return error;
Greg Clayton44d93782014-01-27 23:43:24 +00001129 }
Greg Clayton44d93782014-01-27 23:43:24 +00001130
Kate Stoneb9c1b512016-09-06 20:57:50 +00001131 size_t regex_sed_size = regex_sed.size();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001132
Kate Stoneb9c1b512016-09-06 20:57:50 +00001133 if (regex_sed_size <= 1) {
1134 error.SetErrorStringWithFormat(
1135 "regular expression substitution string is too short: '%.*s'",
1136 (int)regex_sed.size(), regex_sed.data());
1137 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001138 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001139
Kate Stoneb9c1b512016-09-06 20:57:50 +00001140 if (regex_sed[0] != 's') {
1141 error.SetErrorStringWithFormat("regular expression substitution string "
1142 "doesn't start with 's': '%.*s'",
1143 (int)regex_sed.size(), regex_sed.data());
1144 return error;
1145 }
1146 const size_t first_separator_char_pos = 1;
1147 // use the char that follows 's' as the regex separator character
1148 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1149 const char separator_char = regex_sed[first_separator_char_pos];
1150 const size_t second_separator_char_pos =
1151 regex_sed.find(separator_char, first_separator_char_pos + 1);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001152
Kate Stoneb9c1b512016-09-06 20:57:50 +00001153 if (second_separator_char_pos == std::string::npos) {
1154 error.SetErrorStringWithFormat(
1155 "missing second '%c' separator char after '%.*s' in '%.*s'",
1156 separator_char,
1157 (int)(regex_sed.size() - first_separator_char_pos - 1),
1158 regex_sed.data() + (first_separator_char_pos + 1),
1159 (int)regex_sed.size(), regex_sed.data());
1160 return error;
1161 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001162
Kate Stoneb9c1b512016-09-06 20:57:50 +00001163 const size_t third_separator_char_pos =
1164 regex_sed.find(separator_char, second_separator_char_pos + 1);
Greg Clayton44d93782014-01-27 23:43:24 +00001165
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166 if (third_separator_char_pos == std::string::npos) {
1167 error.SetErrorStringWithFormat(
1168 "missing third '%c' separator char after '%.*s' in '%.*s'",
1169 separator_char,
1170 (int)(regex_sed.size() - second_separator_char_pos - 1),
1171 regex_sed.data() + (second_separator_char_pos + 1),
1172 (int)regex_sed.size(), regex_sed.data());
1173 return error;
1174 }
1175
1176 if (third_separator_char_pos != regex_sed_size - 1) {
1177 // Make sure that everything that follows the last regex
1178 // separator char
1179 if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1180 third_separator_char_pos + 1) !=
1181 std::string::npos) {
1182 error.SetErrorStringWithFormat(
1183 "extra data found after the '%.*s' regular expression substitution "
1184 "string: '%.*s'",
1185 (int)third_separator_char_pos + 1, regex_sed.data(),
1186 (int)(regex_sed.size() - third_separator_char_pos - 1),
1187 regex_sed.data() + (third_separator_char_pos + 1));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001188 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001189 }
1190 } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1191 error.SetErrorStringWithFormat(
1192 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1193 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1194 regex_sed.data());
1195 return error;
1196 } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1197 error.SetErrorStringWithFormat(
1198 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1199 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1200 regex_sed.data());
1201 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001202 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001203
1204 if (!check_only) {
1205 std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1206 second_separator_char_pos -
1207 first_separator_char_pos - 1));
1208 std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1209 third_separator_char_pos -
1210 second_separator_char_pos - 1));
1211 m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001212 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001213 return error;
1214 }
1215
1216 void AddRegexCommandToInterpreter() {
1217 if (m_regex_cmd_ap) {
1218 if (m_regex_cmd_ap->HasRegexEntries()) {
1219 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1220 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1221 }
1222 }
1223 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001224
Greg Claytonde164aa2011-04-20 16:37:46 +00001225private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001226 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001227
Kate Stoneb9c1b512016-09-06 20:57:50 +00001228 class CommandOptions : public Options {
1229 public:
1230 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001231
Kate Stoneb9c1b512016-09-06 20:57:50 +00001232 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001233
Kate Stoneb9c1b512016-09-06 20:57:50 +00001234 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1235 ExecutionContext *execution_context) override {
1236 Error error;
1237 const int short_option = m_getopt_table[option_idx].val;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001238
Kate Stoneb9c1b512016-09-06 20:57:50 +00001239 switch (short_option) {
1240 case 'h':
1241 m_help.assign(option_arg);
1242 break;
1243 case 's':
1244 m_syntax.assign(option_arg);
1245 break;
1246 default:
1247 error.SetErrorStringWithFormat("unrecognized option '%c'",
1248 short_option);
1249 break;
1250 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001251
Kate Stoneb9c1b512016-09-06 20:57:50 +00001252 return error;
1253 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001254
Kate Stoneb9c1b512016-09-06 20:57:50 +00001255 void OptionParsingStarting(ExecutionContext *execution_context) override {
1256 m_help.clear();
1257 m_syntax.clear();
1258 }
1259
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001260 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001261 return llvm::makeArrayRef(g_regex_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001262 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001263
Zachary Turner11eb9c62016-10-05 20:03:37 +00001264 // TODO: Convert these functions to return StringRefs.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001265 const char *GetHelp() {
1266 return (m_help.empty() ? nullptr : m_help.c_str());
1267 }
1268
1269 const char *GetSyntax() {
1270 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1271 }
1272
1273 protected:
1274 // Instance variables to hold the values for command options.
1275
1276 std::string m_help;
1277 std::string m_syntax;
1278 };
1279
1280 Options *GetOptions() override { return &m_options; }
1281
1282 CommandOptions m_options;
Greg Claytonde164aa2011-04-20 16:37:46 +00001283};
1284
Kate Stoneb9c1b512016-09-06 20:57:50 +00001285class CommandObjectPythonFunction : public CommandObjectRaw {
Enrico Granata223383e2011-08-16 23:24:13 +00001286public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001287 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1288 std::string funct, std::string help,
1289 ScriptedCommandSynchronicity synch)
Zachary Turnera4496982016-10-05 21:14:38 +00001290 : CommandObjectRaw(interpreter, name),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001291 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1292 if (!help.empty())
1293 SetHelp(help.c_str());
1294 else {
1295 StreamString stream;
1296 stream.Printf("For more information run 'help %s'", name.c_str());
1297 SetHelp(stream.GetData());
Enrico Granata223383e2011-08-16 23:24:13 +00001298 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001299 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001300
Kate Stoneb9c1b512016-09-06 20:57:50 +00001301 ~CommandObjectPythonFunction() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001302
Kate Stoneb9c1b512016-09-06 20:57:50 +00001303 bool IsRemovable() const override { return true; }
Jim Ingham5a988412012-06-08 21:56:10 +00001304
Kate Stoneb9c1b512016-09-06 20:57:50 +00001305 const std::string &GetFunctionName() { return m_function_name; }
Jim Ingham5a988412012-06-08 21:56:10 +00001306
Kate Stoneb9c1b512016-09-06 20:57:50 +00001307 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1308
1309 const char *GetHelpLong() override {
1310 if (!m_fetched_help_long) {
1311 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1312 if (scripter) {
1313 std::string docstring;
1314 m_fetched_help_long = scripter->GetDocumentationForItem(
1315 m_function_name.c_str(), docstring);
1316 if (!docstring.empty())
1317 SetHelpLong(docstring.c_str());
1318 }
Jim Ingham5a988412012-06-08 21:56:10 +00001319 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001320 return CommandObjectRaw::GetHelpLong();
1321 }
1322
Jim Ingham5a988412012-06-08 21:56:10 +00001323protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001324 bool DoExecute(const char *raw_command_line,
1325 CommandReturnObject &result) override {
1326 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1327
1328 Error error;
1329
1330 result.SetStatus(eReturnStatusInvalid);
1331
1332 if (!scripter ||
1333 !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1334 raw_command_line, m_synchro, result,
1335 error, m_exe_ctx)) {
1336 result.AppendError(error.AsCString());
1337 result.SetStatus(eReturnStatusFailed);
1338 } else {
1339 // Don't change the status if the command already set it...
1340 if (result.GetStatus() == eReturnStatusInvalid) {
1341 if (result.GetOutputData() == nullptr ||
1342 result.GetOutputData()[0] == '\0')
1343 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata223383e2011-08-16 23:24:13 +00001344 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001345 result.SetStatus(eReturnStatusSuccessFinishResult);
1346 }
Enrico Granata223383e2011-08-16 23:24:13 +00001347 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001348
Kate Stoneb9c1b512016-09-06 20:57:50 +00001349 return result.Succeeded();
1350 }
1351
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001352private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001353 std::string m_function_name;
1354 ScriptedCommandSynchronicity m_synchro;
1355 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001356};
1357
Kate Stoneb9c1b512016-09-06 20:57:50 +00001358class CommandObjectScriptingObject : public CommandObjectRaw {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001359public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001360 CommandObjectScriptingObject(CommandInterpreter &interpreter,
1361 std::string name,
1362 StructuredData::GenericSP cmd_obj_sp,
1363 ScriptedCommandSynchronicity synch)
Zachary Turnera4496982016-10-05 21:14:38 +00001364 : CommandObjectRaw(interpreter, name),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001365 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1366 m_fetched_help_long(false) {
1367 StreamString stream;
1368 stream.Printf("For more information run 'help %s'", name.c_str());
1369 SetHelp(stream.GetData());
1370 if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1371 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1372 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001373
Kate Stoneb9c1b512016-09-06 20:57:50 +00001374 ~CommandObjectScriptingObject() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001375
Kate Stoneb9c1b512016-09-06 20:57:50 +00001376 bool IsRemovable() const override { return true; }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001377
Kate Stoneb9c1b512016-09-06 20:57:50 +00001378 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1379
1380 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1381
1382 const char *GetHelp() override {
1383 if (!m_fetched_help_short) {
1384 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1385 if (scripter) {
1386 std::string docstring;
1387 m_fetched_help_short =
1388 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1389 if (!docstring.empty())
1390 SetHelp(docstring.c_str());
1391 }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001392 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001393 return CommandObjectRaw::GetHelp();
1394 }
1395
1396 const char *GetHelpLong() override {
1397 if (!m_fetched_help_long) {
1398 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1399 if (scripter) {
1400 std::string docstring;
1401 m_fetched_help_long =
1402 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1403 if (!docstring.empty())
1404 SetHelpLong(docstring.c_str());
1405 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001406 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001407 return CommandObjectRaw::GetHelpLong();
1408 }
1409
Enrico Granata9fe00e52015-03-13 02:20:41 +00001410protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001411 bool DoExecute(const char *raw_command_line,
1412 CommandReturnObject &result) override {
1413 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1414
1415 Error error;
1416
1417 result.SetStatus(eReturnStatusInvalid);
1418
1419 if (!scripter ||
1420 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1421 m_synchro, result, error, m_exe_ctx)) {
1422 result.AppendError(error.AsCString());
1423 result.SetStatus(eReturnStatusFailed);
1424 } else {
1425 // Don't change the status if the command already set it...
1426 if (result.GetStatus() == eReturnStatusInvalid) {
1427 if (result.GetOutputData() == nullptr ||
1428 result.GetOutputData()[0] == '\0')
1429 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata9fe00e52015-03-13 02:20:41 +00001430 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001431 result.SetStatus(eReturnStatusSuccessFinishResult);
1432 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001433 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001434
Kate Stoneb9c1b512016-09-06 20:57:50 +00001435 return result.Succeeded();
1436 }
1437
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001438private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001439 StructuredData::GenericSP m_cmd_obj_sp;
1440 ScriptedCommandSynchronicity m_synchro;
1441 bool m_fetched_help_short : 1;
1442 bool m_fetched_help_long : 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001443};
1444
Enrico Granataa9dbf432011-10-17 21:45:27 +00001445//-------------------------------------------------------------------------
1446// CommandObjectCommandsScriptImport
1447//-------------------------------------------------------------------------
1448
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001449OptionDefinition g_script_import_options[] = {
1450 // clang-format off
1451 { 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." },
1452 // clang-format on
1453};
1454
Kate Stoneb9c1b512016-09-06 20:57:50 +00001455class CommandObjectCommandsScriptImport : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001456public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001457 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1458 : CommandObjectParsed(interpreter, "command script import",
1459 "Import a scripting module in LLDB.", nullptr),
1460 m_options() {
1461 CommandArgumentEntry arg1;
1462 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001463
Kate Stoneb9c1b512016-09-06 20:57:50 +00001464 // Define the first (and only) variant of this arg.
1465 cmd_arg.arg_type = eArgTypeFilename;
1466 cmd_arg.arg_repetition = eArgRepeatPlus;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001467
Kate Stoneb9c1b512016-09-06 20:57:50 +00001468 // There is only one variant this argument could be; put it into the
1469 // argument entry.
1470 arg1.push_back(cmd_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +00001471
Kate Stoneb9c1b512016-09-06 20:57:50 +00001472 // Push the data for the first argument into the m_arguments vector.
1473 m_arguments.push_back(arg1);
1474 }
1475
1476 ~CommandObjectCommandsScriptImport() override = default;
1477
1478 int HandleArgumentCompletion(Args &input, int &cursor_index,
1479 int &cursor_char_position,
1480 OptionElementVector &opt_element_vector,
1481 int match_start_point, int max_return_elements,
1482 bool &word_complete,
1483 StringList &matches) override {
1484 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1485 completion_str.erase(cursor_char_position);
1486
1487 CommandCompletions::InvokeCommonCompletionCallbacks(
1488 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1489 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1490 word_complete, matches);
1491 return matches.GetSize();
1492 }
1493
1494 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +00001495
1496protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001497 class CommandOptions : public Options {
1498 public:
1499 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001500
Kate Stoneb9c1b512016-09-06 20:57:50 +00001501 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001502
Kate Stoneb9c1b512016-09-06 20:57:50 +00001503 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1504 ExecutionContext *execution_context) override {
1505 Error error;
1506 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001507
Kate Stoneb9c1b512016-09-06 20:57:50 +00001508 switch (short_option) {
1509 case 'r':
1510 m_allow_reload = true;
1511 break;
1512 default:
1513 error.SetErrorStringWithFormat("unrecognized option '%c'",
1514 short_option);
1515 break;
1516 }
1517
1518 return error;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001519 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001520
1521 void OptionParsingStarting(ExecutionContext *execution_context) override {
1522 m_allow_reload = true;
1523 }
1524
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001525 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001526 return llvm::makeArrayRef(g_script_import_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001527 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001528
1529 // Instance variables to hold the values for command options.
1530
1531 bool m_allow_reload;
1532 };
1533
1534 bool DoExecute(Args &command, CommandReturnObject &result) override {
1535 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1536 lldb::eScriptLanguagePython) {
1537 result.AppendError("only scripting language supported for module "
1538 "importing is currently Python");
1539 result.SetStatus(eReturnStatusFailed);
1540 return false;
1541 }
1542
Zachary Turner11eb9c62016-10-05 20:03:37 +00001543 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001544 result.AppendError("command script import needs one or more arguments");
1545 result.SetStatus(eReturnStatusFailed);
1546 return false;
1547 }
1548
Zachary Turner11eb9c62016-10-05 20:03:37 +00001549 for (auto &entry : command.entries()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001550 Error error;
1551
1552 const bool init_session = true;
1553 // FIXME: this is necessary because CommandObject::CheckRequirements()
Zachary Turner11eb9c62016-10-05 20:03:37 +00001554 // assumes that commands won't ever be recursively invoked, but it's
1555 // actually possible to craft a Python script that does other "command
1556 // script imports" in __lldb_init_module the real fix is to have recursive
1557 // commands possible with a CommandInvocation object separate from the
1558 // CommandObject itself, so that recursive command invocations won't stomp
1559 // on each other (wrt to execution contents, options, and more)
Kate Stoneb9c1b512016-09-06 20:57:50 +00001560 m_exe_ctx.Clear();
1561 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
Zachary Turner11eb9c62016-10-05 20:03:37 +00001562 entry.c_str(), m_options.m_allow_reload, init_session, error)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001563 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1564 } else {
1565 result.AppendErrorWithFormat("module importing failed: %s",
1566 error.AsCString());
1567 result.SetStatus(eReturnStatusFailed);
1568 }
1569 }
1570
1571 return result.Succeeded();
1572 }
1573
1574 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001575};
Enrico Granata223383e2011-08-16 23:24:13 +00001576
1577//-------------------------------------------------------------------------
1578// CommandObjectCommandsScriptAdd
1579//-------------------------------------------------------------------------
1580
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001581static OptionEnumValueElement g_script_synchro_type[] = {
1582 {eScriptedCommandSynchronicitySynchronous, "synchronous",
1583 "Run synchronous"},
1584 {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1585 "Run asynchronous"},
1586 {eScriptedCommandSynchronicityCurrentValue, "current",
1587 "Do not alter current setting"},
1588 {0, nullptr, nullptr}};
1589
1590static OptionDefinition g_script_add_options[] = {
1591 // clang-format off
1592 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
1593 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
1594 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." },
1595 { 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." },
1596 // clang-format on
1597};
1598
Kate Stoneb9c1b512016-09-06 20:57:50 +00001599class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1600 public IOHandlerDelegateMultiline {
Jim Ingham5a988412012-06-08 21:56:10 +00001601public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001602 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1603 : CommandObjectParsed(interpreter, "command script add",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001604 "Add a scripted function as an LLDB command.",
1605 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001606 IOHandlerDelegateMultiline("DONE"), m_options() {
1607 CommandArgumentEntry arg1;
1608 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001609
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610 // Define the first (and only) variant of this arg.
1611 cmd_arg.arg_type = eArgTypeCommandName;
1612 cmd_arg.arg_repetition = eArgRepeatPlain;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001613
Kate Stoneb9c1b512016-09-06 20:57:50 +00001614 // There is only one variant this argument could be; put it into the
1615 // argument entry.
1616 arg1.push_back(cmd_arg);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001617
Kate Stoneb9c1b512016-09-06 20:57:50 +00001618 // Push the data for the first argument into the m_arguments vector.
1619 m_arguments.push_back(arg1);
1620 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001621
Kate Stoneb9c1b512016-09-06 20:57:50 +00001622 ~CommandObjectCommandsScriptAdd() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001623
Kate Stoneb9c1b512016-09-06 20:57:50 +00001624 Options *GetOptions() override { return &m_options; }
Greg Clayton44d93782014-01-27 23:43:24 +00001625
Jim Ingham5a988412012-06-08 21:56:10 +00001626protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001627 class CommandOptions : public Options {
1628 public:
1629 CommandOptions()
1630 : Options(), m_class_name(), m_funct_name(), m_short_help(),
1631 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
Enrico Granata223383e2011-08-16 23:24:13 +00001632
Kate Stoneb9c1b512016-09-06 20:57:50 +00001633 ~CommandOptions() override = default;
1634
1635 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1636 ExecutionContext *execution_context) override {
1637 Error error;
1638 const int short_option = m_getopt_table[option_idx].val;
1639
1640 switch (short_option) {
1641 case 'f':
1642 if (option_arg)
1643 m_funct_name.assign(option_arg);
1644 break;
1645 case 'c':
1646 if (option_arg)
1647 m_class_name.assign(option_arg);
1648 break;
1649 case 'h':
1650 if (option_arg)
1651 m_short_help.assign(option_arg);
1652 break;
1653 case 's':
1654 m_synchronicity =
1655 (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001656 llvm::StringRef::withNullAsEmpty(option_arg),
1657 GetDefinitions()[option_idx].enum_values, 0, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001658 if (!error.Success())
1659 error.SetErrorStringWithFormat(
1660 "unrecognized value for synchronicity '%s'", option_arg);
1661 break;
1662 default:
1663 error.SetErrorStringWithFormat("unrecognized option '%c'",
1664 short_option);
1665 break;
1666 }
1667
1668 return error;
Enrico Granata223383e2011-08-16 23:24:13 +00001669 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001670
1671 void OptionParsingStarting(ExecutionContext *execution_context) override {
1672 m_class_name.clear();
1673 m_funct_name.clear();
1674 m_short_help.clear();
1675 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1676 }
1677
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001678 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001679 return llvm::makeArrayRef(g_script_add_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001680 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001681
1682 // Instance variables to hold the values for command options.
1683
1684 std::string m_class_name;
1685 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001686 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001687 ScriptedCommandSynchronicity m_synchronicity;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001688 };
1689
1690 void IOHandlerActivated(IOHandler &io_handler) override {
1691 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1692 if (output_sp) {
1693 output_sp->PutCString(g_python_command_instructions);
1694 output_sp->Flush();
1695 }
1696 }
1697
1698 void IOHandlerInputComplete(IOHandler &io_handler,
1699 std::string &data) override {
1700 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1701
1702 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1703 if (interpreter) {
1704
1705 StringList lines;
1706 lines.SplitIntoLines(data);
1707 if (lines.GetSize() > 0) {
1708 std::string funct_name_str;
1709 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1710 if (funct_name_str.empty()) {
1711 error_sp->Printf("error: unable to obtain a function name, didn't "
1712 "add python command.\n");
1713 error_sp->Flush();
1714 } else {
1715 // everything should be fine now, let's add this alias
1716
1717 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1718 m_interpreter, m_cmd_name, funct_name_str.c_str(), m_short_help,
1719 m_synchronicity));
1720
1721 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1722 true)) {
1723 error_sp->Printf("error: unable to add selected command, didn't "
1724 "add python command.\n");
1725 error_sp->Flush();
1726 }
1727 }
1728 } else {
1729 error_sp->Printf(
1730 "error: unable to create function, didn't add python command.\n");
1731 error_sp->Flush();
1732 }
1733 } else {
1734 error_sp->Printf("error: empty function, didn't add python command.\n");
1735 error_sp->Flush();
1736 }
1737 } else {
1738 error_sp->Printf(
1739 "error: script interpreter missing, didn't add python command.\n");
1740 error_sp->Flush();
1741 }
1742
1743 io_handler.SetIsDone(true);
1744 }
1745
1746protected:
1747 bool DoExecute(Args &command, CommandReturnObject &result) override {
1748 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1749 lldb::eScriptLanguagePython) {
1750 result.AppendError("only scripting language supported for scripted "
1751 "commands is currently Python");
1752 result.SetStatus(eReturnStatusFailed);
1753 return false;
1754 }
1755
Zachary Turner11eb9c62016-10-05 20:03:37 +00001756 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001757 result.AppendError("'command script add' requires one argument");
1758 result.SetStatus(eReturnStatusFailed);
1759 return false;
1760 }
1761
1762 // Store the options in case we get multi-line input
1763 m_cmd_name = command.GetArgumentAtIndex(0);
1764 m_short_help.assign(m_options.m_short_help);
1765 m_synchronicity = m_options.m_synchronicity;
1766
1767 if (m_options.m_class_name.empty()) {
1768 if (m_options.m_funct_name.empty()) {
1769 m_interpreter.GetPythonCommandsFromIOHandler(
1770 " ", // Prompt
1771 *this, // IOHandlerDelegate
1772 true, // Run IOHandler in async mode
1773 nullptr); // Baton for the "io_handler" that will be passed back
1774 // into our IOHandlerDelegate functions
1775 } else {
1776 CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1777 m_interpreter, m_cmd_name, m_options.m_funct_name,
1778 m_options.m_short_help, m_synchronicity));
1779 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1780 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1781 } else {
1782 result.AppendError("cannot add command");
1783 result.SetStatus(eReturnStatusFailed);
1784 }
1785 }
1786 } else {
1787 ScriptInterpreter *interpreter =
1788 GetCommandInterpreter().GetScriptInterpreter();
1789 if (!interpreter) {
1790 result.AppendError("cannot find ScriptInterpreter");
1791 result.SetStatus(eReturnStatusFailed);
1792 return false;
1793 }
1794
1795 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1796 m_options.m_class_name.c_str());
1797 if (!cmd_obj_sp) {
1798 result.AppendError("cannot create helper object");
1799 result.SetStatus(eReturnStatusFailed);
1800 return false;
1801 }
1802
1803 CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1804 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1805 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1806 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1807 } else {
1808 result.AppendError("cannot add command");
1809 result.SetStatus(eReturnStatusFailed);
1810 }
1811 }
1812
1813 return result.Succeeded();
1814 }
1815
1816 CommandOptions m_options;
1817 std::string m_cmd_name;
1818 std::string m_short_help;
1819 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001820};
1821
Enrico Granata223383e2011-08-16 23:24:13 +00001822//-------------------------------------------------------------------------
1823// CommandObjectCommandsScriptList
1824//-------------------------------------------------------------------------
1825
Kate Stoneb9c1b512016-09-06 20:57:50 +00001826class CommandObjectCommandsScriptList : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001827public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001828 CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1829 : CommandObjectParsed(interpreter, "command script list",
1830 "List defined scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001831
Kate Stoneb9c1b512016-09-06 20:57:50 +00001832 ~CommandObjectCommandsScriptList() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001833
Kate Stoneb9c1b512016-09-06 20:57:50 +00001834 bool DoExecute(Args &command, CommandReturnObject &result) override {
1835 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1836
1837 result.SetStatus(eReturnStatusSuccessFinishResult);
1838
1839 return true;
1840 }
Enrico Granata223383e2011-08-16 23:24:13 +00001841};
1842
1843//-------------------------------------------------------------------------
1844// CommandObjectCommandsScriptClear
1845//-------------------------------------------------------------------------
1846
Kate Stoneb9c1b512016-09-06 20:57:50 +00001847class CommandObjectCommandsScriptClear : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001848public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001849 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1850 : CommandObjectParsed(interpreter, "command script clear",
1851 "Delete all scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001852
Kate Stoneb9c1b512016-09-06 20:57:50 +00001853 ~CommandObjectCommandsScriptClear() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001854
Jim Ingham5a988412012-06-08 21:56:10 +00001855protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001856 bool DoExecute(Args &command, CommandReturnObject &result) override {
1857 m_interpreter.RemoveAllUser();
1858
1859 result.SetStatus(eReturnStatusSuccessFinishResult);
1860
1861 return true;
1862 }
Enrico Granata223383e2011-08-16 23:24:13 +00001863};
1864
1865//-------------------------------------------------------------------------
1866// CommandObjectCommandsScriptDelete
1867//-------------------------------------------------------------------------
1868
Kate Stoneb9c1b512016-09-06 20:57:50 +00001869class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001870public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001871 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1872 : CommandObjectParsed(interpreter, "command script delete",
1873 "Delete a scripted command.", nullptr) {
1874 CommandArgumentEntry arg1;
1875 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001876
Kate Stoneb9c1b512016-09-06 20:57:50 +00001877 // Define the first (and only) variant of this arg.
1878 cmd_arg.arg_type = eArgTypeCommandName;
1879 cmd_arg.arg_repetition = eArgRepeatPlain;
1880
1881 // There is only one variant this argument could be; put it into the
1882 // argument entry.
1883 arg1.push_back(cmd_arg);
1884
1885 // Push the data for the first argument into the m_arguments vector.
1886 m_arguments.push_back(arg1);
1887 }
1888
1889 ~CommandObjectCommandsScriptDelete() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001890
Jim Ingham5a988412012-06-08 21:56:10 +00001891protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001892 bool DoExecute(Args &command, CommandReturnObject &result) override {
1893
Zachary Turner11eb9c62016-10-05 20:03:37 +00001894 if (command.GetArgumentCount() != 1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001895 result.AppendError("'command script delete' requires one argument");
1896 result.SetStatus(eReturnStatusFailed);
1897 return false;
Enrico Granata223383e2011-08-16 23:24:13 +00001898 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001899
1900 const char *cmd_name = command.GetArgumentAtIndex(0);
1901
1902 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() &&
1903 m_interpreter.UserCommandExists(cmd_name)) {
1904 m_interpreter.RemoveUser(cmd_name);
1905 result.SetStatus(eReturnStatusSuccessFinishResult);
1906 } else {
1907 result.AppendErrorWithFormat("command %s not found", cmd_name);
1908 result.SetStatus(eReturnStatusFailed);
1909 }
1910
1911 return result.Succeeded();
1912 }
Enrico Granata223383e2011-08-16 23:24:13 +00001913};
1914
1915#pragma mark CommandObjectMultiwordCommandsScript
1916
1917//-------------------------------------------------------------------------
1918// CommandObjectMultiwordCommandsScript
1919//-------------------------------------------------------------------------
1920
Kate Stoneb9c1b512016-09-06 20:57:50 +00001921class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
Enrico Granata223383e2011-08-16 23:24:13 +00001922public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001923 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1924 : CommandObjectMultiword(
1925 interpreter, "command script", "Commands for managing custom "
1926 "commands implemented by "
1927 "interpreter scripts.",
1928 "command script <subcommand> [<subcommand-options>]") {
1929 LoadSubCommand("add", CommandObjectSP(
1930 new CommandObjectCommandsScriptAdd(interpreter)));
1931 LoadSubCommand(
1932 "delete",
1933 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1934 LoadSubCommand(
1935 "clear",
1936 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1937 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1938 interpreter)));
1939 LoadSubCommand(
1940 "import",
1941 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1942 }
Enrico Granata223383e2011-08-16 23:24:13 +00001943
Kate Stoneb9c1b512016-09-06 20:57:50 +00001944 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00001945};
1946
Jim Inghamebc09c32010-07-07 03:36:20 +00001947#pragma mark CommandObjectMultiwordCommands
1948
1949//-------------------------------------------------------------------------
1950// CommandObjectMultiwordCommands
1951//-------------------------------------------------------------------------
1952
Kate Stoneb9c1b512016-09-06 20:57:50 +00001953CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1954 CommandInterpreter &interpreter)
1955 : CommandObjectMultiword(interpreter, "command",
1956 "Commands for managing custom LLDB commands.",
1957 "command <subcommand> [<subcommand-options>]") {
1958 LoadSubCommand("source",
1959 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1960 LoadSubCommand("alias",
1961 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1962 LoadSubCommand("unalias", CommandObjectSP(
1963 new CommandObjectCommandsUnalias(interpreter)));
1964 LoadSubCommand("delete",
1965 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1966 LoadSubCommand(
1967 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1968 LoadSubCommand("history", CommandObjectSP(
1969 new CommandObjectCommandsHistory(interpreter)));
1970 LoadSubCommand(
1971 "script",
1972 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00001973}
1974
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001975CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;