blob: 74f0362b251bd00f70e632afa9c2292575409534 [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;
73
74 switch (short_option) {
75 case 'c':
76 error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
77 break;
78 case 's':
79 if (option_arg && strcmp("end", option_arg) == 0) {
80 m_start_idx.SetCurrentValue(UINT64_MAX);
81 m_start_idx.SetOptionWasSet();
82 } else
83 error = m_start_idx.SetValueFromString(option_arg,
84 eVarSetOperationAssign);
85 break;
86 case 'e':
87 error =
88 m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
89 break;
90 case 'C':
91 m_clear.SetCurrentValue(true);
92 m_clear.SetOptionWasSet();
93 break;
94 default:
95 error.SetErrorStringWithFormat("unrecognized option '%c'",
96 short_option);
97 break;
98 }
99
100 return error;
101 }
102
103 void OptionParsingStarting(ExecutionContext *execution_context) override {
104 m_start_idx.Clear();
105 m_stop_idx.Clear();
106 m_count.Clear();
107 m_clear.Clear();
108 }
109
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000110 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
111 return g_history_options;
112 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000113
114 // Instance variables to hold the values for command options.
115
116 OptionValueUInt64 m_start_idx;
117 OptionValueUInt64 m_stop_idx;
118 OptionValueUInt64 m_count;
119 OptionValueBoolean m_clear;
120 };
121
122 bool DoExecute(Args &command, CommandReturnObject &result) override {
123 if (m_options.m_clear.GetCurrentValue() &&
124 m_options.m_clear.OptionWasSet()) {
125 m_interpreter.GetCommandHistory().Clear();
126 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
127 } else {
128 if (m_options.m_start_idx.OptionWasSet() &&
129 m_options.m_stop_idx.OptionWasSet() &&
130 m_options.m_count.OptionWasSet()) {
131 result.AppendError("--count, --start-index and --end-index cannot be "
132 "all specified in the same invocation");
133 result.SetStatus(lldb::eReturnStatusFailed);
134 } else {
135 std::pair<bool, uint64_t> start_idx(
136 m_options.m_start_idx.OptionWasSet(),
137 m_options.m_start_idx.GetCurrentValue());
138 std::pair<bool, uint64_t> stop_idx(
139 m_options.m_stop_idx.OptionWasSet(),
140 m_options.m_stop_idx.GetCurrentValue());
141 std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
142 m_options.m_count.GetCurrentValue());
143
144 const CommandHistory &history(m_interpreter.GetCommandHistory());
145
146 if (start_idx.first && start_idx.second == UINT64_MAX) {
147 if (count.first) {
148 start_idx.second = history.GetSize() - count.second;
149 stop_idx.second = history.GetSize() - 1;
150 } else if (stop_idx.first) {
151 start_idx.second = stop_idx.second;
152 stop_idx.second = history.GetSize() - 1;
153 } else {
154 start_idx.second = 0;
155 stop_idx.second = history.GetSize() - 1;
156 }
157 } else {
158 if (!start_idx.first && !stop_idx.first && !count.first) {
159 start_idx.second = 0;
160 stop_idx.second = history.GetSize() - 1;
161 } else if (start_idx.first) {
162 if (count.first) {
163 stop_idx.second = start_idx.second + count.second - 1;
164 } else if (!stop_idx.first) {
165 stop_idx.second = history.GetSize() - 1;
166 }
167 } else if (stop_idx.first) {
168 if (count.first) {
169 if (stop_idx.second >= count.second)
170 start_idx.second = stop_idx.second - count.second + 1;
171 else
172 start_idx.second = 0;
173 }
174 } else /* if (count.first) */
175 {
176 start_idx.second = 0;
177 stop_idx.second = count.second - 1;
178 }
179 }
180 history.Dump(result.GetOutputStream(), start_idx.second,
181 stop_idx.second);
182 }
183 }
184 return result.Succeeded();
185 }
186
187 CommandOptions m_options;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000188};
189
Jim Inghama5a97eb2011-07-12 03:12:18 +0000190//-------------------------------------------------------------------------
191// CommandObjectCommandsSource
192//-------------------------------------------------------------------------
193
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000194static OptionDefinition g_source_options[] = {
195 // clang-format off
196 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
197 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
198 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
199 // clang-format on
200};
201
Kate Stoneb9c1b512016-09-06 20:57:50 +0000202class CommandObjectCommandsSource : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000203public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 CommandObjectCommandsSource(CommandInterpreter &interpreter)
205 : CommandObjectParsed(
206 interpreter, "command source",
207 "Read and execute LLDB commands from the file <filename>.",
208 nullptr),
209 m_options() {
210 CommandArgumentEntry arg;
211 CommandArgumentData file_arg;
Jim Ingham5a988412012-06-08 21:56:10 +0000212
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213 // Define the first (and only) variant of this arg.
214 file_arg.arg_type = eArgTypeFilename;
215 file_arg.arg_repetition = eArgRepeatPlain;
Jim Ingham5a988412012-06-08 21:56:10 +0000216
Kate Stoneb9c1b512016-09-06 20:57:50 +0000217 // There is only one variant this argument could be; put it into the
218 // argument entry.
219 arg.push_back(file_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +0000220
Kate Stoneb9c1b512016-09-06 20:57:50 +0000221 // Push the data for the first argument into the m_arguments vector.
222 m_arguments.push_back(arg);
223 }
Jim Ingham5a988412012-06-08 21:56:10 +0000224
Kate Stoneb9c1b512016-09-06 20:57:50 +0000225 ~CommandObjectCommandsSource() override = default;
226
227 const char *GetRepeatCommand(Args &current_command_args,
228 uint32_t index) override {
229 return "";
230 }
231
232 int HandleArgumentCompletion(Args &input, int &cursor_index,
233 int &cursor_char_position,
234 OptionElementVector &opt_element_vector,
235 int match_start_point, int max_return_elements,
236 bool &word_complete,
237 StringList &matches) override {
238 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
239 completion_str.erase(cursor_char_position);
240
241 CommandCompletions::InvokeCommonCompletionCallbacks(
242 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
243 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
244 word_complete, matches);
245 return matches.GetSize();
246 }
247
248 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +0000249
250protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000251 class CommandOptions : public Options {
252 public:
253 CommandOptions()
254 : Options(), m_stop_on_error(true), m_silent_run(false),
255 m_stop_on_continue(true) {}
Jim Inghame16c50a2011-02-18 00:54:25 +0000256
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257 ~CommandOptions() override = default;
Jim Inghame16c50a2011-02-18 00:54:25 +0000258
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
260 ExecutionContext *execution_context) override {
261 Error error;
262 const int short_option = m_getopt_table[option_idx].val;
Greg Clayton340b0302014-02-05 17:57:57 +0000263
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264 switch (short_option) {
265 case 'e':
266 error = m_stop_on_error.SetValueFromString(option_arg);
267 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 case 'c':
270 error = m_stop_on_continue.SetValueFromString(option_arg);
271 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000272
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273 case 's':
274 error = m_silent_run.SetValueFromString(option_arg);
275 break;
Jim Inghame16c50a2011-02-18 00:54:25 +0000276
Kate Stoneb9c1b512016-09-06 20:57:50 +0000277 default:
278 error.SetErrorStringWithFormat("unrecognized option '%c'",
279 short_option);
280 break;
281 }
Jim Inghame16c50a2011-02-18 00:54:25 +0000282
Kate Stoneb9c1b512016-09-06 20:57:50 +0000283 return error;
Jim Inghamebc09c32010-07-07 03:36:20 +0000284 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000285
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 void OptionParsingStarting(ExecutionContext *execution_context) override {
287 m_stop_on_error.Clear();
288 m_silent_run.Clear();
289 m_stop_on_continue.Clear();
290 }
291
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000292 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
293 return g_source_options;
294 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295
296 // Instance variables to hold the values for command options.
297
298 OptionValueBoolean m_stop_on_error;
299 OptionValueBoolean m_silent_run;
300 OptionValueBoolean m_stop_on_continue;
301 };
302
303 bool DoExecute(Args &command, CommandReturnObject &result) override {
304 const size_t argc = command.GetArgumentCount();
305 if (argc == 1) {
306 const char *filename = command.GetArgumentAtIndex(0);
307
308 FileSpec cmd_file(filename, true);
309 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
310
311 // If any options were set, then use them
312 if (m_options.m_stop_on_error.OptionWasSet() ||
313 m_options.m_silent_run.OptionWasSet() ||
314 m_options.m_stop_on_continue.OptionWasSet()) {
315 // Use user set settings
316 CommandInterpreterRunOptions options;
317 options.SetStopOnContinue(
318 m_options.m_stop_on_continue.GetCurrentValue());
319 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
320 options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
321 options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
322
323 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
324 result);
325 } else {
326 // No options were set, inherit any settings from nested "command
327 // source" commands,
328 // or set to sane default settings...
329 CommandInterpreterRunOptions options;
330 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
331 result);
332 }
333 } else {
334 result.AppendErrorWithFormat(
335 "'%s' takes exactly one executable filename argument.\n",
336 GetCommandName());
337 result.SetStatus(eReturnStatusFailed);
338 }
339 return result.Succeeded();
340 }
341
342 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000343};
344
345#pragma mark CommandObjectCommandsAlias
346//-------------------------------------------------------------------------
347// CommandObjectCommandsAlias
348//-------------------------------------------------------------------------
349
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000350static OptionDefinition g_alias_options[] = {
351 // clang-format off
352 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
353 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
354 // clang-format on
355};
356
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357static const char *g_python_command_instructions =
358 "Enter your Python command(s). Type 'DONE' to end.\n"
359 "You must define a Python function with this signature:\n"
360 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000361
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362class CommandObjectCommandsAlias : public CommandObjectRaw {
Enrico Granata45d0e232016-03-31 01:10:54 +0000363protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 class CommandOptions : public OptionGroup {
365 public:
366 CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
Enrico Granata45d0e232016-03-31 01:10:54 +0000367
Kate Stoneb9c1b512016-09-06 20:57:50 +0000368 ~CommandOptions() override = default;
369
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000370 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
371 return g_alias_options;
372 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373
374 Error SetOptionValue(uint32_t option_idx, const char *option_value,
375 ExecutionContext *execution_context) override {
376 Error error;
377
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000378 const int short_option = GetDefinitions()[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379
380 switch (short_option) {
381 case 'h':
382 m_help.SetCurrentValue(option_value);
383 m_help.SetOptionWasSet();
384 break;
385
386 case 'H':
387 m_long_help.SetCurrentValue(option_value);
388 m_long_help.SetOptionWasSet();
389 break;
390
391 default:
392 error.SetErrorStringWithFormat("invalid short option character '%c'",
393 short_option);
394 break;
395 }
396
397 return error;
Enrico Granata45d0e232016-03-31 01:10:54 +0000398 }
399
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400 void OptionParsingStarting(ExecutionContext *execution_context) override {
401 m_help.Clear();
402 m_long_help.Clear();
403 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000404
Kate Stoneb9c1b512016-09-06 20:57:50 +0000405 OptionValueString m_help;
406 OptionValueString m_long_help;
407 };
408
409 OptionGroupOptions m_option_group;
410 CommandOptions m_command_options;
411
412public:
413 Options *GetOptions() override { return &m_option_group; }
414
415 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
416 : CommandObjectRaw(
417 interpreter, "command alias",
418 "Define a custom command in terms of an existing command.",
419 nullptr),
420 m_option_group(), m_command_options() {
421 m_option_group.Append(&m_command_options);
422 m_option_group.Finalize();
423
424 SetHelpLong(
425 "'alias' allows the user to create a short-cut or abbreviation for long \
Kate Stoneea671fb2015-07-14 05:48:36 +0000426commands, multi-word commands, and commands that take particular options. \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427Below are some simple examples of how one might use the 'alias' command:"
428 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000429
430(lldb) command alias sc script
431
432 Creates the abbreviation 'sc' for the 'script' command.
433
434(lldb) command alias bp breakpoint
435
Kate Stoneb9c1b512016-09-06 20:57:50 +0000436)"
437 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
Kate Stoneea671fb2015-07-14 05:48:36 +0000438breakpoint commands are two-word commands, the user would still need to \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
440 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000441
442(lldb) command alias bpl breakpoint list
443
444 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
445
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446)"
447 "An alias can include some options for the command, with the values either \
Kate Stoneea671fb2015-07-14 05:48:36 +0000448filled in at the time the alias is created, or specified as positional \
449arguments, to be filled in when the alias is invoked. The following example \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000450shows how to create aliases with options:"
451 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000452
453(lldb) command alias bfl breakpoint set -f %1 -l %2
454
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455)"
456 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
Kate Stoneea671fb2015-07-14 05:48:36 +0000457options already part of the alias. So if the user wants to set a breakpoint \
458by file and line without explicitly having to use the -f and -l options, the \
459user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
460for the actual arguments that will be passed when the alias command is used. \
461The number in the placeholder refers to the position/order the actual value \
462occupies when the alias is used. All the occurrences of '%1' in the alias \
463will be replaced with the first argument, all the occurrences of '%2' in the \
464alias will be replaced with the second argument, and so on. This also allows \
465actual arguments to be used multiple times within an alias (see 'process \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466launch' example below)."
467 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000468
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469)"
470 "Note: the positional arguments must substitute as whole words in the resultant \
Kate Stoneea671fb2015-07-14 05:48:36 +0000471command, so you can't at present do something like this to append the file extension \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000472\".cpp\":"
473 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000474
475(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
476
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477)"
478 "For more complex aliasing, use the \"command regex\" command instead. In the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000479'bfl' case above, the actual file value will be filled in with the first argument \
480following 'bfl' and the actual line number value will be filled in with the second \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481argument. The user would use this alias as follows:"
482 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000483
484(lldb) command alias bfl breakpoint set -f %1 -l %2
485(lldb) bfl my-file.c 137
486
487This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
488
489Another example:
490
491(lldb) command alias pltty process launch -s -o %1 -e %1
492(lldb) pltty /dev/tty0
493
494 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
495
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496)"
497 "If the user always wanted to pass the same value to a particular option, the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000498alias could be defined with that value directly in the alias as a constant, \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499rather than using a positional placeholder:"
500 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000501
502(lldb) command alias bl3 breakpoint set -f %1 -l 3
503
Kate Stoneb9c1b512016-09-06 20:57:50 +0000504 Always sets a breakpoint on line 3 of whatever file is indicated.)");
Jim Inghamebc09c32010-07-07 03:36:20 +0000505
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506 CommandArgumentEntry arg1;
507 CommandArgumentEntry arg2;
508 CommandArgumentEntry arg3;
509 CommandArgumentData alias_arg;
510 CommandArgumentData cmd_arg;
511 CommandArgumentData options_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000512
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513 // Define the first (and only) variant of this arg.
514 alias_arg.arg_type = eArgTypeAliasName;
515 alias_arg.arg_repetition = eArgRepeatPlain;
516
517 // There is only one variant this argument could be; put it into the
518 // argument entry.
519 arg1.push_back(alias_arg);
520
521 // Define the first (and only) variant of this arg.
522 cmd_arg.arg_type = eArgTypeCommandName;
523 cmd_arg.arg_repetition = eArgRepeatPlain;
524
525 // There is only one variant this argument could be; put it into the
526 // argument entry.
527 arg2.push_back(cmd_arg);
528
529 // Define the first (and only) variant of this arg.
530 options_arg.arg_type = eArgTypeAliasOptions;
531 options_arg.arg_repetition = eArgRepeatOptional;
532
533 // There is only one variant this argument could be; put it into the
534 // argument entry.
535 arg3.push_back(options_arg);
536
537 // Push the data for the first argument into the m_arguments vector.
538 m_arguments.push_back(arg1);
539 m_arguments.push_back(arg2);
540 m_arguments.push_back(arg3);
541 }
542
543 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000544
Jim Ingham5a988412012-06-08 21:56:10 +0000545protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546 bool DoExecute(const char *raw_command_line,
547 CommandReturnObject &result) override {
548 if (!raw_command_line || !raw_command_line[0]) {
549 result.AppendError("'command alias' requires at least two arguments");
550 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000551 }
552
Kate Stoneb9c1b512016-09-06 20:57:50 +0000553 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
554 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
Caroline Ticeca90c472011-05-06 21:37:15 +0000555
Kate Stoneb9c1b512016-09-06 20:57:50 +0000556 const char *remainder = nullptr;
Enrico Granata212130a2016-03-08 05:37:15 +0000557
Kate Stoneb9c1b512016-09-06 20:57:50 +0000558 if (raw_command_line[0] == '-') {
559 // We have some options and these options MUST end with --.
560 const char *end_options = nullptr;
561 const char *s = raw_command_line;
562 while (s && s[0]) {
563 end_options = ::strstr(s, "--");
564 if (end_options) {
565 end_options += 2; // Get past the "--"
566 if (::isspace(end_options[0])) {
567 remainder = end_options;
568 while (::isspace(*remainder))
569 ++remainder;
570 break;
571 }
572 }
573 s = end_options;
574 }
575
576 if (end_options) {
577 Args args(
578 llvm::StringRef(raw_command_line, end_options - raw_command_line));
579 if (!ParseOptions(args, result))
580 return false;
581
582 Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
583 if (error.Fail()) {
584 result.AppendError(error.AsCString());
585 result.SetStatus(eReturnStatusFailed);
586 return false;
587 }
588 }
Caroline Tice844d2302010-12-09 22:52:49 +0000589 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000590 if (nullptr == remainder)
591 remainder = raw_command_line;
Jim Inghamebc09c32010-07-07 03:36:20 +0000592
Kate Stoneb9c1b512016-09-06 20:57:50 +0000593 std::string raw_command_string(remainder);
594 Args args(raw_command_string.c_str());
Jim Inghamebc09c32010-07-07 03:36:20 +0000595
Kate Stoneb9c1b512016-09-06 20:57:50 +0000596 size_t argc = args.GetArgumentCount();
Jim Inghamebc09c32010-07-07 03:36:20 +0000597
Kate Stoneb9c1b512016-09-06 20:57:50 +0000598 if (argc < 2) {
599 result.AppendError("'command alias' requires at least two arguments");
600 result.SetStatus(eReturnStatusFailed);
601 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000602 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000603
604 // Get the alias command.
605
606 const std::string alias_command = args.GetArgumentAtIndex(0);
607 if (alias_command.size() > 1 && alias_command[0] == '-') {
608 result.AppendError("aliases starting with a dash are not supported");
609 if (alias_command == "--help" || alias_command == "--long-help") {
610 result.AppendWarning("if trying to pass options to 'command alias' add "
611 "a -- at the end of the options");
612 }
613 result.SetStatus(eReturnStatusFailed);
614 return false;
615 }
616
617 // Strip the new alias name off 'raw_command_string' (leave it on args,
618 // which gets passed to 'Execute', which
619 // does the stripping itself.
620 size_t pos = raw_command_string.find(alias_command);
621 if (pos == 0) {
622 raw_command_string = raw_command_string.substr(alias_command.size());
623 pos = raw_command_string.find_first_not_of(' ');
624 if ((pos != std::string::npos) && (pos > 0))
625 raw_command_string = raw_command_string.substr(pos);
626 } else {
627 result.AppendError("Error parsing command string. No alias created.");
628 result.SetStatus(eReturnStatusFailed);
629 return false;
630 }
631
632 // Verify that the command is alias-able.
633 if (m_interpreter.CommandExists(alias_command.c_str())) {
634 result.AppendErrorWithFormat(
635 "'%s' is a permanent debugger command and cannot be redefined.\n",
636 alias_command.c_str());
637 result.SetStatus(eReturnStatusFailed);
638 return false;
639 }
640
641 // Get CommandObject that is being aliased. The command name is read from
642 // the front of raw_command_string.
643 // raw_command_string is returned with the name of the command object
644 // stripped off the front.
645 std::string original_raw_command_string(raw_command_string);
646 CommandObject *cmd_obj =
647 m_interpreter.GetCommandObjectForCommand(raw_command_string);
648
649 if (!cmd_obj) {
650 result.AppendErrorWithFormat("invalid command given to 'command alias'. "
651 "'%s' does not begin with a valid command."
652 " No alias created.",
653 original_raw_command_string.c_str());
654 result.SetStatus(eReturnStatusFailed);
655 return false;
656 } else if (!cmd_obj->WantsRawCommandString()) {
657 // Note that args was initialized with the original command, and has not
658 // been updated to this point.
659 // Therefore can we pass it to the version of Execute that does not
660 // need/expect raw input in the alias.
661 return HandleAliasingNormalCommand(args, result);
662 } else {
663 return HandleAliasingRawCommand(alias_command, raw_command_string,
664 *cmd_obj, result);
665 }
666 return result.Succeeded();
667 }
668
669 bool HandleAliasingRawCommand(const std::string &alias_command,
670 std::string &raw_command_string,
671 CommandObject &cmd_obj,
672 CommandReturnObject &result) {
673 // Verify & handle any options/arguments passed to the alias command
674
675 OptionArgVectorSP option_arg_vector_sp =
676 OptionArgVectorSP(new OptionArgVector);
677
678 if (CommandObjectSP cmd_obj_sp =
679 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
680 if (m_interpreter.AliasExists(alias_command.c_str()) ||
681 m_interpreter.UserCommandExists(alias_command.c_str())) {
682 result.AppendWarningWithFormat(
683 "Overwriting existing definition for '%s'.\n",
684 alias_command.c_str());
685 }
686 if (CommandAlias *alias = m_interpreter.AddAlias(
687 alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) {
688 if (m_command_options.m_help.OptionWasSet())
689 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
690 if (m_command_options.m_long_help.OptionWasSet())
691 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
692 result.SetStatus(eReturnStatusSuccessFinishNoResult);
693 } else {
694 result.AppendError("Unable to create requested alias.\n");
695 result.SetStatus(eReturnStatusFailed);
696 }
697
698 } else {
699 result.AppendError("Unable to create requested alias.\n");
700 result.SetStatus(eReturnStatusFailed);
701 }
702
703 return result.Succeeded();
704 }
705
706 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
707 size_t argc = args.GetArgumentCount();
708
709 if (argc < 2) {
710 result.AppendError("'command alias' requires at least two arguments");
711 result.SetStatus(eReturnStatusFailed);
712 return false;
713 }
714
715 const std::string alias_command = args.GetArgumentAtIndex(0);
716 const std::string actual_command = args.GetArgumentAtIndex(1);
717
718 args.Shift(); // Shift the alias command word off the argument vector.
719 args.Shift(); // Shift the old command word off the argument vector.
720
721 // Verify that the command is alias'able, and get the appropriate command
722 // object.
723
724 if (m_interpreter.CommandExists(alias_command.c_str())) {
725 result.AppendErrorWithFormat(
726 "'%s' is a permanent debugger command and cannot be redefined.\n",
727 alias_command.c_str());
728 result.SetStatus(eReturnStatusFailed);
729 } else {
730 CommandObjectSP command_obj_sp(
731 m_interpreter.GetCommandSPExact(actual_command.c_str(), true));
732 CommandObjectSP subcommand_obj_sp;
733 bool use_subcommand = false;
734 if (command_obj_sp) {
735 CommandObject *cmd_obj = command_obj_sp.get();
736 CommandObject *sub_cmd_obj = nullptr;
737 OptionArgVectorSP option_arg_vector_sp =
738 OptionArgVectorSP(new OptionArgVector);
739
740 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) {
741 if (argc >= 3) {
742 const std::string sub_command = args.GetArgumentAtIndex(0);
743 assert(sub_command.length() != 0);
744 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command.c_str());
745 if (subcommand_obj_sp) {
746 sub_cmd_obj = subcommand_obj_sp.get();
747 use_subcommand = true;
748 args.Shift(); // Shift the sub_command word off the argument
749 // vector.
750 cmd_obj = sub_cmd_obj;
751 } else {
752 result.AppendErrorWithFormat(
753 "'%s' is not a valid sub-command of '%s'. "
754 "Unable to create alias.\n",
755 sub_command.c_str(), actual_command.c_str());
756 result.SetStatus(eReturnStatusFailed);
757 return false;
758 }
759 }
760 }
761
762 // Verify & handle any options/arguments passed to the alias command
763
764 std::string args_string;
765
766 if (args.GetArgumentCount() > 0) {
767 CommandObjectSP tmp_sp =
768 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
769 if (use_subcommand)
770 tmp_sp = m_interpreter.GetCommandSPExact(
771 sub_cmd_obj->GetCommandName(), false);
772
773 args.GetCommandString(args_string);
774 }
775
776 if (m_interpreter.AliasExists(alias_command.c_str()) ||
777 m_interpreter.UserCommandExists(alias_command.c_str())) {
778 result.AppendWarningWithFormat(
779 "Overwriting existing definition for '%s'.\n",
780 alias_command.c_str());
781 }
782
783 if (CommandAlias *alias = m_interpreter.AddAlias(
784 alias_command.c_str(),
785 use_subcommand ? subcommand_obj_sp : command_obj_sp,
786 args_string.c_str())) {
787 if (m_command_options.m_help.OptionWasSet())
788 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
789 if (m_command_options.m_long_help.OptionWasSet())
790 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
791 result.SetStatus(eReturnStatusSuccessFinishNoResult);
792 } else {
793 result.AppendError("Unable to create requested alias.\n");
794 result.SetStatus(eReturnStatusFailed);
795 return false;
796 }
797 } else {
798 result.AppendErrorWithFormat("'%s' is not an existing command.\n",
799 actual_command.c_str());
800 result.SetStatus(eReturnStatusFailed);
801 return false;
802 }
803 }
804
805 return result.Succeeded();
806 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000807};
808
809#pragma mark CommandObjectCommandsUnalias
810//-------------------------------------------------------------------------
811// CommandObjectCommandsUnalias
812//-------------------------------------------------------------------------
813
Kate Stoneb9c1b512016-09-06 20:57:50 +0000814class CommandObjectCommandsUnalias : public CommandObjectParsed {
Jim Inghamebc09c32010-07-07 03:36:20 +0000815public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000816 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
817 : CommandObjectParsed(
818 interpreter, "command unalias",
819 "Delete one or more custom commands defined by 'command alias'.",
820 nullptr) {
821 CommandArgumentEntry arg;
822 CommandArgumentData alias_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000823
Kate Stoneb9c1b512016-09-06 20:57:50 +0000824 // Define the first (and only) variant of this arg.
825 alias_arg.arg_type = eArgTypeAliasName;
826 alias_arg.arg_repetition = eArgRepeatPlain;
827
828 // There is only one variant this argument could be; put it into the
829 // argument entry.
830 arg.push_back(alias_arg);
831
832 // Push the data for the first argument into the m_arguments vector.
833 m_arguments.push_back(arg);
834 }
835
836 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000837
Jim Ingham5a988412012-06-08 21:56:10 +0000838protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000839 bool DoExecute(Args &args, CommandReturnObject &result) override {
840 CommandObject::CommandMap::iterator pos;
841 CommandObject *cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000842
Kate Stoneb9c1b512016-09-06 20:57:50 +0000843 if (args.GetArgumentCount() != 0) {
844 const char *command_name = args.GetArgumentAtIndex(0);
845 cmd_obj = m_interpreter.GetCommandObject(command_name);
846 if (cmd_obj) {
847 if (m_interpreter.CommandExists(command_name)) {
848 if (cmd_obj->IsRemovable()) {
849 result.AppendErrorWithFormat(
850 "'%s' is not an alias, it is a debugger command which can be "
851 "removed using the 'command delete' command.\n",
852 command_name);
853 } else {
854 result.AppendErrorWithFormat(
855 "'%s' is a permanent debugger command and cannot be removed.\n",
856 command_name);
857 }
858 result.SetStatus(eReturnStatusFailed);
859 } else {
860 if (!m_interpreter.RemoveAlias(command_name)) {
861 if (m_interpreter.AliasExists(command_name))
862 result.AppendErrorWithFormat(
863 "Error occurred while attempting to unalias '%s'.\n",
864 command_name);
Jim Inghamebc09c32010-07-07 03:36:20 +0000865 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000866 result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
867 command_name);
868 result.SetStatus(eReturnStatusFailed);
869 } else
870 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Jim Inghamebc09c32010-07-07 03:36:20 +0000871 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000872 } else {
873 result.AppendErrorWithFormat(
874 "'%s' is not a known command.\nTry 'help' to see a "
875 "current list of commands.\n",
876 command_name);
877 result.SetStatus(eReturnStatusFailed);
878 }
879 } else {
880 result.AppendError("must call 'unalias' with a valid alias");
881 result.SetStatus(eReturnStatusFailed);
Jim Inghamebc09c32010-07-07 03:36:20 +0000882 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000883
884 return result.Succeeded();
885 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000886};
887
Greg Claytonb5472782015-01-09 19:08:20 +0000888#pragma mark CommandObjectCommandsDelete
889//-------------------------------------------------------------------------
890// CommandObjectCommandsDelete
891//-------------------------------------------------------------------------
892
Kate Stoneb9c1b512016-09-06 20:57:50 +0000893class CommandObjectCommandsDelete : public CommandObjectParsed {
Greg Claytonb5472782015-01-09 19:08:20 +0000894public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000895 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
896 : CommandObjectParsed(
897 interpreter, "command delete",
898 "Delete one or more custom commands defined by 'command regex'.",
899 nullptr) {
900 CommandArgumentEntry arg;
901 CommandArgumentData alias_arg;
Greg Claytonb5472782015-01-09 19:08:20 +0000902
Kate Stoneb9c1b512016-09-06 20:57:50 +0000903 // Define the first (and only) variant of this arg.
904 alias_arg.arg_type = eArgTypeCommandName;
905 alias_arg.arg_repetition = eArgRepeatPlain;
Greg Claytonb5472782015-01-09 19:08:20 +0000906
Kate Stoneb9c1b512016-09-06 20:57:50 +0000907 // There is only one variant this argument could be; put it into the
908 // argument entry.
909 arg.push_back(alias_arg);
Greg Claytonb5472782015-01-09 19:08:20 +0000910
Kate Stoneb9c1b512016-09-06 20:57:50 +0000911 // Push the data for the first argument into the m_arguments vector.
912 m_arguments.push_back(arg);
913 }
Greg Claytonb5472782015-01-09 19:08:20 +0000914
Kate Stoneb9c1b512016-09-06 20:57:50 +0000915 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +0000916
917protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000918 bool DoExecute(Args &args, CommandReturnObject &result) override {
919 CommandObject::CommandMap::iterator pos;
Greg Claytonb5472782015-01-09 19:08:20 +0000920
Kate Stoneb9c1b512016-09-06 20:57:50 +0000921 if (args.GetArgumentCount() != 0) {
922 const char *command_name = args.GetArgumentAtIndex(0);
923 if (m_interpreter.CommandExists(command_name)) {
924 if (m_interpreter.RemoveCommand(command_name)) {
925 result.SetStatus(eReturnStatusSuccessFinishNoResult);
926 } else {
927 result.AppendErrorWithFormat(
928 "'%s' is a permanent debugger command and cannot be removed.\n",
929 command_name);
930 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000931 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000932 } else {
933 StreamString error_msg_stream;
934 const bool generate_apropos = true;
935 const bool generate_type_lookup = false;
936 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
937 &error_msg_stream, command_name, nullptr, nullptr, generate_apropos,
938 generate_type_lookup);
939 result.AppendErrorWithFormat("%s", error_msg_stream.GetData());
940 result.SetStatus(eReturnStatusFailed);
941 }
942 } else {
943 result.AppendErrorWithFormat("must call '%s' with one or more valid user "
944 "defined regular expression command names",
945 GetCommandName());
946 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000947 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000948
949 return result.Succeeded();
950 }
Greg Claytonb5472782015-01-09 19:08:20 +0000951};
952
Greg Claytonde164aa2011-04-20 16:37:46 +0000953//-------------------------------------------------------------------------
954// CommandObjectCommandsAddRegex
955//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000956
957static OptionDefinition g_regex_options[] = {
958 // clang-format off
959 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
960 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
961 // clang-format on
962};
963
Jim Ingham5a988412012-06-08 21:56:10 +0000964#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +0000965
Kate Stoneb9c1b512016-09-06 20:57:50 +0000966class CommandObjectCommandsAddRegex : public CommandObjectParsed,
967 public IOHandlerDelegateMultiline {
Greg Claytonde164aa2011-04-20 16:37:46 +0000968public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000969 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
970 : CommandObjectParsed(
971 interpreter, "command regex", "Define a custom command in terms of "
972 "existing commands by matching "
973 "regular expressions.",
974 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
975 IOHandlerDelegateMultiline("",
976 IOHandlerDelegate::Completion::LLDBCommand),
977 m_options() {
978 SetHelpLong(
979 R"(
980)"
981 "This command allows the user to create powerful regular expression commands \
Kate Stoneea671fb2015-07-14 05:48:36 +0000982with substitutions. The regular expressions and substitutions are specified \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000983using the regular expression substitution format of:"
984 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000985
986 s/<regex>/<subst>/
987
Kate Stoneb9c1b512016-09-06 20:57:50 +0000988)"
989 "<regex> is a regular expression that can use parenthesis to capture regular \
Kate Stoneea671fb2015-07-14 05:48:36 +0000990expression input and substitute the captured matches in the output using %1 \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000991for the first match, %2 for the second, and so on."
992 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000993
Kate Stoneb9c1b512016-09-06 20:57:50 +0000994)"
995 "The regular expressions can all be specified on the command line if more than \
Kate Stoneea671fb2015-07-14 05:48:36 +0000996one argument is provided. If just the command name is provided on the command \
997line, then the regular expressions and substitutions can be entered on separate \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000998lines, followed by an empty line to terminate the command definition."
999 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001000
1001EXAMPLES
1002
Kate Stoneb9c1b512016-09-06 20:57:50 +00001003)"
1004 "The following example will define a regular expression command named 'f' that \
Kate Stoneea671fb2015-07-14 05:48:36 +00001005will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001006a number follows 'f':"
1007 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001008
Kate Stoneb9c1b512016-09-06 20:57:50 +00001009 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1010 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001011
Kate Stoneb9c1b512016-09-06 20:57:50 +00001012 ~CommandObjectCommandsAddRegex() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001013
Jim Ingham5a988412012-06-08 21:56:10 +00001014protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001015 void IOHandlerActivated(IOHandler &io_handler) override {
1016 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1017 if (output_sp) {
1018 output_sp->PutCString("Enter one of more sed substitution commands in "
1019 "the form: 's/<regex>/<subst>/'.\nTerminate the "
1020 "substitution list with an empty line.\n");
1021 output_sp->Flush();
1022 }
1023 }
1024
1025 void IOHandlerInputComplete(IOHandler &io_handler,
1026 std::string &data) override {
1027 io_handler.SetIsDone(true);
1028 if (m_regex_cmd_ap) {
1029 StringList lines;
1030 if (lines.SplitIntoLines(data)) {
1031 const size_t num_lines = lines.GetSize();
1032 bool check_only = false;
1033 for (size_t i = 0; i < num_lines; ++i) {
1034 llvm::StringRef bytes_strref(lines[i]);
1035 Error error = AppendRegexSubstitution(bytes_strref, check_only);
1036 if (error.Fail()) {
1037 if (!m_interpreter.GetDebugger()
1038 .GetCommandInterpreter()
1039 .GetBatchCommandMode()) {
1040 StreamSP out_stream =
1041 m_interpreter.GetDebugger().GetAsyncOutputStream();
1042 out_stream->Printf("error: %s\n", error.AsCString());
1043 }
1044 }
Greg Clayton44d93782014-01-27 23:43:24 +00001045 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046 }
1047 if (m_regex_cmd_ap->HasRegexEntries()) {
1048 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1049 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1050 }
1051 }
1052 }
1053
1054 bool DoExecute(Args &command, CommandReturnObject &result) override {
1055 const size_t argc = command.GetArgumentCount();
1056 if (argc == 0) {
1057 result.AppendError("usage: 'command regex <command-name> "
1058 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1059 result.SetStatus(eReturnStatusFailed);
1060 } else {
1061 Error error;
1062 const char *name = command.GetArgumentAtIndex(0);
1063 m_regex_cmd_ap.reset(new CommandObjectRegexCommand(
1064 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10,
1065 0, true));
1066
1067 if (argc == 1) {
1068 Debugger &debugger = m_interpreter.GetDebugger();
1069 bool color_prompt = debugger.GetUseColor();
1070 const bool multiple_lines = true; // Get multiple lines
1071 IOHandlerSP io_handler_sp(new IOHandlerEditline(
1072 debugger, IOHandler::Type::Other,
1073 "lldb-regex", // Name of input reader for history
1074 "> ", // Prompt
1075 nullptr, // Continuation prompt
1076 multiple_lines, color_prompt,
1077 0, // Don't show line numbers
1078 *this));
1079
1080 if (io_handler_sp) {
1081 debugger.PushIOHandler(io_handler_sp);
1082 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1083 }
1084 } else {
1085 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) {
1086 llvm::StringRef arg_strref(command.GetArgumentAtIndex(arg_idx));
1087 bool check_only = false;
1088 error = AppendRegexSubstitution(arg_strref, check_only);
1089 if (error.Fail())
1090 break;
1091 }
1092
1093 if (error.Success()) {
1094 AddRegexCommandToInterpreter();
1095 }
1096 }
1097 if (error.Fail()) {
1098 result.AppendError(error.AsCString());
1099 result.SetStatus(eReturnStatusFailed);
1100 }
Greg Clayton44d93782014-01-27 23:43:24 +00001101 }
1102
Kate Stoneb9c1b512016-09-06 20:57:50 +00001103 return result.Succeeded();
1104 }
1105
1106 Error AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1107 bool check_only) {
1108 Error error;
1109
1110 if (!m_regex_cmd_ap) {
1111 error.SetErrorStringWithFormat(
1112 "invalid regular expression command object for: '%.*s'",
1113 (int)regex_sed.size(), regex_sed.data());
1114 return error;
Greg Clayton44d93782014-01-27 23:43:24 +00001115 }
Greg Clayton44d93782014-01-27 23:43:24 +00001116
Kate Stoneb9c1b512016-09-06 20:57:50 +00001117 size_t regex_sed_size = regex_sed.size();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001118
Kate Stoneb9c1b512016-09-06 20:57:50 +00001119 if (regex_sed_size <= 1) {
1120 error.SetErrorStringWithFormat(
1121 "regular expression substitution string is too short: '%.*s'",
1122 (int)regex_sed.size(), regex_sed.data());
1123 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001124 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001125
Kate Stoneb9c1b512016-09-06 20:57:50 +00001126 if (regex_sed[0] != 's') {
1127 error.SetErrorStringWithFormat("regular expression substitution string "
1128 "doesn't start with 's': '%.*s'",
1129 (int)regex_sed.size(), regex_sed.data());
1130 return error;
1131 }
1132 const size_t first_separator_char_pos = 1;
1133 // use the char that follows 's' as the regex separator character
1134 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1135 const char separator_char = regex_sed[first_separator_char_pos];
1136 const size_t second_separator_char_pos =
1137 regex_sed.find(separator_char, first_separator_char_pos + 1);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001138
Kate Stoneb9c1b512016-09-06 20:57:50 +00001139 if (second_separator_char_pos == std::string::npos) {
1140 error.SetErrorStringWithFormat(
1141 "missing second '%c' separator char after '%.*s' in '%.*s'",
1142 separator_char,
1143 (int)(regex_sed.size() - first_separator_char_pos - 1),
1144 regex_sed.data() + (first_separator_char_pos + 1),
1145 (int)regex_sed.size(), regex_sed.data());
1146 return error;
1147 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001148
Kate Stoneb9c1b512016-09-06 20:57:50 +00001149 const size_t third_separator_char_pos =
1150 regex_sed.find(separator_char, second_separator_char_pos + 1);
Greg Clayton44d93782014-01-27 23:43:24 +00001151
Kate Stoneb9c1b512016-09-06 20:57:50 +00001152 if (third_separator_char_pos == std::string::npos) {
1153 error.SetErrorStringWithFormat(
1154 "missing third '%c' separator char after '%.*s' in '%.*s'",
1155 separator_char,
1156 (int)(regex_sed.size() - second_separator_char_pos - 1),
1157 regex_sed.data() + (second_separator_char_pos + 1),
1158 (int)regex_sed.size(), regex_sed.data());
1159 return error;
1160 }
1161
1162 if (third_separator_char_pos != regex_sed_size - 1) {
1163 // Make sure that everything that follows the last regex
1164 // separator char
1165 if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1166 third_separator_char_pos + 1) !=
1167 std::string::npos) {
1168 error.SetErrorStringWithFormat(
1169 "extra data found after the '%.*s' regular expression substitution "
1170 "string: '%.*s'",
1171 (int)third_separator_char_pos + 1, regex_sed.data(),
1172 (int)(regex_sed.size() - third_separator_char_pos - 1),
1173 regex_sed.data() + (third_separator_char_pos + 1));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001174 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001175 }
1176 } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1177 error.SetErrorStringWithFormat(
1178 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1179 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1180 regex_sed.data());
1181 return error;
1182 } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1183 error.SetErrorStringWithFormat(
1184 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1185 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1186 regex_sed.data());
1187 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001188 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001189
1190 if (!check_only) {
1191 std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1192 second_separator_char_pos -
1193 first_separator_char_pos - 1));
1194 std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1195 third_separator_char_pos -
1196 second_separator_char_pos - 1));
1197 m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001198 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001199 return error;
1200 }
1201
1202 void AddRegexCommandToInterpreter() {
1203 if (m_regex_cmd_ap) {
1204 if (m_regex_cmd_ap->HasRegexEntries()) {
1205 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1206 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1207 }
1208 }
1209 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001210
Greg Claytonde164aa2011-04-20 16:37:46 +00001211private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001212 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001213
Kate Stoneb9c1b512016-09-06 20:57:50 +00001214 class CommandOptions : public Options {
1215 public:
1216 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001217
Kate Stoneb9c1b512016-09-06 20:57:50 +00001218 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001219
Kate Stoneb9c1b512016-09-06 20:57:50 +00001220 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1221 ExecutionContext *execution_context) override {
1222 Error error;
1223 const int short_option = m_getopt_table[option_idx].val;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001224
Kate Stoneb9c1b512016-09-06 20:57:50 +00001225 switch (short_option) {
1226 case 'h':
1227 m_help.assign(option_arg);
1228 break;
1229 case 's':
1230 m_syntax.assign(option_arg);
1231 break;
1232 default:
1233 error.SetErrorStringWithFormat("unrecognized option '%c'",
1234 short_option);
1235 break;
1236 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001237
Kate Stoneb9c1b512016-09-06 20:57:50 +00001238 return error;
1239 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001240
Kate Stoneb9c1b512016-09-06 20:57:50 +00001241 void OptionParsingStarting(ExecutionContext *execution_context) override {
1242 m_help.clear();
1243 m_syntax.clear();
1244 }
1245
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001246 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1247 return g_regex_options;
1248 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001249
1250 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)
1275 : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1276 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1277 if (!help.empty())
1278 SetHelp(help.c_str());
1279 else {
1280 StreamString stream;
1281 stream.Printf("For more information run 'help %s'", name.c_str());
1282 SetHelp(stream.GetData());
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
1294 const char *GetHelpLong() override {
1295 if (!m_fetched_help_long) {
1296 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1297 if (scripter) {
1298 std::string docstring;
1299 m_fetched_help_long = scripter->GetDocumentationForItem(
1300 m_function_name.c_str(), docstring);
1301 if (!docstring.empty())
1302 SetHelpLong(docstring.c_str());
1303 }
Jim Ingham5a988412012-06-08 21:56:10 +00001304 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001305 return CommandObjectRaw::GetHelpLong();
1306 }
1307
Jim Ingham5a988412012-06-08 21:56:10 +00001308protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001309 bool DoExecute(const char *raw_command_line,
1310 CommandReturnObject &result) override {
1311 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1312
1313 Error error;
1314
1315 result.SetStatus(eReturnStatusInvalid);
1316
1317 if (!scripter ||
1318 !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1319 raw_command_line, m_synchro, result,
1320 error, m_exe_ctx)) {
1321 result.AppendError(error.AsCString());
1322 result.SetStatus(eReturnStatusFailed);
1323 } else {
1324 // Don't change the status if the command already set it...
1325 if (result.GetStatus() == eReturnStatusInvalid) {
1326 if (result.GetOutputData() == nullptr ||
1327 result.GetOutputData()[0] == '\0')
1328 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata223383e2011-08-16 23:24:13 +00001329 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001330 result.SetStatus(eReturnStatusSuccessFinishResult);
1331 }
Enrico Granata223383e2011-08-16 23:24:13 +00001332 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001333
Kate Stoneb9c1b512016-09-06 20:57:50 +00001334 return result.Succeeded();
1335 }
1336
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001337private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001338 std::string m_function_name;
1339 ScriptedCommandSynchronicity m_synchro;
1340 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001341};
1342
Kate Stoneb9c1b512016-09-06 20:57:50 +00001343class CommandObjectScriptingObject : public CommandObjectRaw {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001344public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001345 CommandObjectScriptingObject(CommandInterpreter &interpreter,
1346 std::string name,
1347 StructuredData::GenericSP cmd_obj_sp,
1348 ScriptedCommandSynchronicity synch)
1349 : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1350 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1351 m_fetched_help_long(false) {
1352 StreamString stream;
1353 stream.Printf("For more information run 'help %s'", name.c_str());
1354 SetHelp(stream.GetData());
1355 if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1356 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1357 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001358
Kate Stoneb9c1b512016-09-06 20:57:50 +00001359 ~CommandObjectScriptingObject() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001360
Kate Stoneb9c1b512016-09-06 20:57:50 +00001361 bool IsRemovable() const override { return true; }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001362
Kate Stoneb9c1b512016-09-06 20:57:50 +00001363 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1364
1365 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1366
1367 const char *GetHelp() override {
1368 if (!m_fetched_help_short) {
1369 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1370 if (scripter) {
1371 std::string docstring;
1372 m_fetched_help_short =
1373 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1374 if (!docstring.empty())
1375 SetHelp(docstring.c_str());
1376 }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001377 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001378 return CommandObjectRaw::GetHelp();
1379 }
1380
1381 const char *GetHelpLong() override {
1382 if (!m_fetched_help_long) {
1383 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1384 if (scripter) {
1385 std::string docstring;
1386 m_fetched_help_long =
1387 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1388 if (!docstring.empty())
1389 SetHelpLong(docstring.c_str());
1390 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001391 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001392 return CommandObjectRaw::GetHelpLong();
1393 }
1394
Enrico Granata9fe00e52015-03-13 02:20:41 +00001395protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001396 bool DoExecute(const char *raw_command_line,
1397 CommandReturnObject &result) override {
1398 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1399
1400 Error error;
1401
1402 result.SetStatus(eReturnStatusInvalid);
1403
1404 if (!scripter ||
1405 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1406 m_synchro, result, error, m_exe_ctx)) {
1407 result.AppendError(error.AsCString());
1408 result.SetStatus(eReturnStatusFailed);
1409 } else {
1410 // Don't change the status if the command already set it...
1411 if (result.GetStatus() == eReturnStatusInvalid) {
1412 if (result.GetOutputData() == nullptr ||
1413 result.GetOutputData()[0] == '\0')
1414 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata9fe00e52015-03-13 02:20:41 +00001415 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001416 result.SetStatus(eReturnStatusSuccessFinishResult);
1417 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001418 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001419
Kate Stoneb9c1b512016-09-06 20:57:50 +00001420 return result.Succeeded();
1421 }
1422
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001423private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001424 StructuredData::GenericSP m_cmd_obj_sp;
1425 ScriptedCommandSynchronicity m_synchro;
1426 bool m_fetched_help_short : 1;
1427 bool m_fetched_help_long : 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001428};
1429
Enrico Granataa9dbf432011-10-17 21:45:27 +00001430//-------------------------------------------------------------------------
1431// CommandObjectCommandsScriptImport
1432//-------------------------------------------------------------------------
1433
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001434OptionDefinition g_script_import_options[] = {
1435 // clang-format off
1436 { 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." },
1437 // clang-format on
1438};
1439
Kate Stoneb9c1b512016-09-06 20:57:50 +00001440class CommandObjectCommandsScriptImport : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001441public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001442 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1443 : CommandObjectParsed(interpreter, "command script import",
1444 "Import a scripting module in LLDB.", nullptr),
1445 m_options() {
1446 CommandArgumentEntry arg1;
1447 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001448
Kate Stoneb9c1b512016-09-06 20:57:50 +00001449 // Define the first (and only) variant of this arg.
1450 cmd_arg.arg_type = eArgTypeFilename;
1451 cmd_arg.arg_repetition = eArgRepeatPlus;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001452
Kate Stoneb9c1b512016-09-06 20:57:50 +00001453 // There is only one variant this argument could be; put it into the
1454 // argument entry.
1455 arg1.push_back(cmd_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +00001456
Kate Stoneb9c1b512016-09-06 20:57:50 +00001457 // Push the data for the first argument into the m_arguments vector.
1458 m_arguments.push_back(arg1);
1459 }
1460
1461 ~CommandObjectCommandsScriptImport() override = default;
1462
1463 int HandleArgumentCompletion(Args &input, int &cursor_index,
1464 int &cursor_char_position,
1465 OptionElementVector &opt_element_vector,
1466 int match_start_point, int max_return_elements,
1467 bool &word_complete,
1468 StringList &matches) override {
1469 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1470 completion_str.erase(cursor_char_position);
1471
1472 CommandCompletions::InvokeCommonCompletionCallbacks(
1473 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1474 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1475 word_complete, matches);
1476 return matches.GetSize();
1477 }
1478
1479 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +00001480
1481protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001482 class CommandOptions : public Options {
1483 public:
1484 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001485
Kate Stoneb9c1b512016-09-06 20:57:50 +00001486 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001487
Kate Stoneb9c1b512016-09-06 20:57:50 +00001488 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1489 ExecutionContext *execution_context) override {
1490 Error error;
1491 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001492
Kate Stoneb9c1b512016-09-06 20:57:50 +00001493 switch (short_option) {
1494 case 'r':
1495 m_allow_reload = true;
1496 break;
1497 default:
1498 error.SetErrorStringWithFormat("unrecognized option '%c'",
1499 short_option);
1500 break;
1501 }
1502
1503 return error;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001504 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001505
1506 void OptionParsingStarting(ExecutionContext *execution_context) override {
1507 m_allow_reload = true;
1508 }
1509
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001510 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1511 return g_script_import_options;
1512 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001513
1514 // Instance variables to hold the values for command options.
1515
1516 bool m_allow_reload;
1517 };
1518
1519 bool DoExecute(Args &command, CommandReturnObject &result) override {
1520 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1521 lldb::eScriptLanguagePython) {
1522 result.AppendError("only scripting language supported for module "
1523 "importing is currently Python");
1524 result.SetStatus(eReturnStatusFailed);
1525 return false;
1526 }
1527
1528 size_t argc = command.GetArgumentCount();
1529 if (0 == argc) {
1530 result.AppendError("command script import needs one or more arguments");
1531 result.SetStatus(eReturnStatusFailed);
1532 return false;
1533 }
1534
1535 for (size_t i = 0; i < argc; i++) {
1536 std::string path = command.GetArgumentAtIndex(i);
1537 Error error;
1538
1539 const bool init_session = true;
1540 // FIXME: this is necessary because CommandObject::CheckRequirements()
1541 // assumes that
1542 // commands won't ever be recursively invoked, but it's actually possible
1543 // to craft
1544 // a Python script that does other "command script imports" in
1545 // __lldb_init_module
1546 // the real fix is to have recursive commands possible with a
1547 // CommandInvocation object
1548 // separate from the CommandObject itself, so that recursive command
1549 // invocations
1550 // won't stomp on each other (wrt to execution contents, options, and
1551 // more)
1552 m_exe_ctx.Clear();
1553 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1554 path.c_str(), m_options.m_allow_reload, init_session, error)) {
1555 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1556 } else {
1557 result.AppendErrorWithFormat("module importing failed: %s",
1558 error.AsCString());
1559 result.SetStatus(eReturnStatusFailed);
1560 }
1561 }
1562
1563 return result.Succeeded();
1564 }
1565
1566 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001567};
Enrico Granata223383e2011-08-16 23:24:13 +00001568
1569//-------------------------------------------------------------------------
1570// CommandObjectCommandsScriptAdd
1571//-------------------------------------------------------------------------
1572
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001573static OptionEnumValueElement g_script_synchro_type[] = {
1574 {eScriptedCommandSynchronicitySynchronous, "synchronous",
1575 "Run synchronous"},
1576 {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1577 "Run asynchronous"},
1578 {eScriptedCommandSynchronicityCurrentValue, "current",
1579 "Do not alter current setting"},
1580 {0, nullptr, nullptr}};
1581
1582static OptionDefinition g_script_add_options[] = {
1583 // clang-format off
1584 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
1585 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
1586 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." },
1587 { 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." },
1588 // clang-format on
1589};
1590
Kate Stoneb9c1b512016-09-06 20:57:50 +00001591class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1592 public IOHandlerDelegateMultiline {
Jim Ingham5a988412012-06-08 21:56:10 +00001593public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001594 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1595 : CommandObjectParsed(interpreter, "command script add",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001596 "Add a scripted function as an LLDB command.",
1597 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001598 IOHandlerDelegateMultiline("DONE"), m_options() {
1599 CommandArgumentEntry arg1;
1600 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001601
Kate Stoneb9c1b512016-09-06 20:57:50 +00001602 // Define the first (and only) variant of this arg.
1603 cmd_arg.arg_type = eArgTypeCommandName;
1604 cmd_arg.arg_repetition = eArgRepeatPlain;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001605
Kate Stoneb9c1b512016-09-06 20:57:50 +00001606 // There is only one variant this argument could be; put it into the
1607 // argument entry.
1608 arg1.push_back(cmd_arg);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001609
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610 // Push the data for the first argument into the m_arguments vector.
1611 m_arguments.push_back(arg1);
1612 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001613
Kate Stoneb9c1b512016-09-06 20:57:50 +00001614 ~CommandObjectCommandsScriptAdd() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001615
Kate Stoneb9c1b512016-09-06 20:57:50 +00001616 Options *GetOptions() override { return &m_options; }
Greg Clayton44d93782014-01-27 23:43:24 +00001617
Jim Ingham5a988412012-06-08 21:56:10 +00001618protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001619 class CommandOptions : public Options {
1620 public:
1621 CommandOptions()
1622 : Options(), m_class_name(), m_funct_name(), m_short_help(),
1623 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
Enrico Granata223383e2011-08-16 23:24:13 +00001624
Kate Stoneb9c1b512016-09-06 20:57:50 +00001625 ~CommandOptions() override = default;
1626
1627 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1628 ExecutionContext *execution_context) override {
1629 Error error;
1630 const int short_option = m_getopt_table[option_idx].val;
1631
1632 switch (short_option) {
1633 case 'f':
1634 if (option_arg)
1635 m_funct_name.assign(option_arg);
1636 break;
1637 case 'c':
1638 if (option_arg)
1639 m_class_name.assign(option_arg);
1640 break;
1641 case 'h':
1642 if (option_arg)
1643 m_short_help.assign(option_arg);
1644 break;
1645 case 's':
1646 m_synchronicity =
1647 (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001648 option_arg, GetDefinitions()[option_idx].enum_values, 0, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001649 if (!error.Success())
1650 error.SetErrorStringWithFormat(
1651 "unrecognized value for synchronicity '%s'", option_arg);
1652 break;
1653 default:
1654 error.SetErrorStringWithFormat("unrecognized option '%c'",
1655 short_option);
1656 break;
1657 }
1658
1659 return error;
Enrico Granata223383e2011-08-16 23:24:13 +00001660 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001661
1662 void OptionParsingStarting(ExecutionContext *execution_context) override {
1663 m_class_name.clear();
1664 m_funct_name.clear();
1665 m_short_help.clear();
1666 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1667 }
1668
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001669 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1670 return g_script_add_options;
1671 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001672
1673 // Instance variables to hold the values for command options.
1674
1675 std::string m_class_name;
1676 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001677 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001678 ScriptedCommandSynchronicity m_synchronicity;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001679 };
1680
1681 void IOHandlerActivated(IOHandler &io_handler) override {
1682 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1683 if (output_sp) {
1684 output_sp->PutCString(g_python_command_instructions);
1685 output_sp->Flush();
1686 }
1687 }
1688
1689 void IOHandlerInputComplete(IOHandler &io_handler,
1690 std::string &data) override {
1691 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1692
1693 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1694 if (interpreter) {
1695
1696 StringList lines;
1697 lines.SplitIntoLines(data);
1698 if (lines.GetSize() > 0) {
1699 std::string funct_name_str;
1700 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1701 if (funct_name_str.empty()) {
1702 error_sp->Printf("error: unable to obtain a function name, didn't "
1703 "add python command.\n");
1704 error_sp->Flush();
1705 } else {
1706 // everything should be fine now, let's add this alias
1707
1708 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1709 m_interpreter, m_cmd_name, funct_name_str.c_str(), m_short_help,
1710 m_synchronicity));
1711
1712 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1713 true)) {
1714 error_sp->Printf("error: unable to add selected command, didn't "
1715 "add python command.\n");
1716 error_sp->Flush();
1717 }
1718 }
1719 } else {
1720 error_sp->Printf(
1721 "error: unable to create function, didn't add python command.\n");
1722 error_sp->Flush();
1723 }
1724 } else {
1725 error_sp->Printf("error: empty function, didn't add python command.\n");
1726 error_sp->Flush();
1727 }
1728 } else {
1729 error_sp->Printf(
1730 "error: script interpreter missing, didn't add python command.\n");
1731 error_sp->Flush();
1732 }
1733
1734 io_handler.SetIsDone(true);
1735 }
1736
1737protected:
1738 bool DoExecute(Args &command, CommandReturnObject &result) override {
1739 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1740 lldb::eScriptLanguagePython) {
1741 result.AppendError("only scripting language supported for scripted "
1742 "commands is currently Python");
1743 result.SetStatus(eReturnStatusFailed);
1744 return false;
1745 }
1746
1747 size_t argc = command.GetArgumentCount();
1748
1749 if (argc != 1) {
1750 result.AppendError("'command script add' requires one argument");
1751 result.SetStatus(eReturnStatusFailed);
1752 return false;
1753 }
1754
1755 // Store the options in case we get multi-line input
1756 m_cmd_name = command.GetArgumentAtIndex(0);
1757 m_short_help.assign(m_options.m_short_help);
1758 m_synchronicity = m_options.m_synchronicity;
1759
1760 if (m_options.m_class_name.empty()) {
1761 if (m_options.m_funct_name.empty()) {
1762 m_interpreter.GetPythonCommandsFromIOHandler(
1763 " ", // Prompt
1764 *this, // IOHandlerDelegate
1765 true, // Run IOHandler in async mode
1766 nullptr); // Baton for the "io_handler" that will be passed back
1767 // into our IOHandlerDelegate functions
1768 } else {
1769 CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1770 m_interpreter, m_cmd_name, m_options.m_funct_name,
1771 m_options.m_short_help, m_synchronicity));
1772 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1773 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1774 } else {
1775 result.AppendError("cannot add command");
1776 result.SetStatus(eReturnStatusFailed);
1777 }
1778 }
1779 } else {
1780 ScriptInterpreter *interpreter =
1781 GetCommandInterpreter().GetScriptInterpreter();
1782 if (!interpreter) {
1783 result.AppendError("cannot find ScriptInterpreter");
1784 result.SetStatus(eReturnStatusFailed);
1785 return false;
1786 }
1787
1788 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1789 m_options.m_class_name.c_str());
1790 if (!cmd_obj_sp) {
1791 result.AppendError("cannot create helper object");
1792 result.SetStatus(eReturnStatusFailed);
1793 return false;
1794 }
1795
1796 CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1797 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1798 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1799 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1800 } else {
1801 result.AppendError("cannot add command");
1802 result.SetStatus(eReturnStatusFailed);
1803 }
1804 }
1805
1806 return result.Succeeded();
1807 }
1808
1809 CommandOptions m_options;
1810 std::string m_cmd_name;
1811 std::string m_short_help;
1812 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001813};
1814
Enrico Granata223383e2011-08-16 23:24:13 +00001815//-------------------------------------------------------------------------
1816// CommandObjectCommandsScriptList
1817//-------------------------------------------------------------------------
1818
Kate Stoneb9c1b512016-09-06 20:57:50 +00001819class CommandObjectCommandsScriptList : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001820public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001821 CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1822 : CommandObjectParsed(interpreter, "command script list",
1823 "List defined scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001824
Kate Stoneb9c1b512016-09-06 20:57:50 +00001825 ~CommandObjectCommandsScriptList() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001826
Kate Stoneb9c1b512016-09-06 20:57:50 +00001827 bool DoExecute(Args &command, CommandReturnObject &result) override {
1828 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1829
1830 result.SetStatus(eReturnStatusSuccessFinishResult);
1831
1832 return true;
1833 }
Enrico Granata223383e2011-08-16 23:24:13 +00001834};
1835
1836//-------------------------------------------------------------------------
1837// CommandObjectCommandsScriptClear
1838//-------------------------------------------------------------------------
1839
Kate Stoneb9c1b512016-09-06 20:57:50 +00001840class CommandObjectCommandsScriptClear : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001841public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001842 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1843 : CommandObjectParsed(interpreter, "command script clear",
1844 "Delete all scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001845
Kate Stoneb9c1b512016-09-06 20:57:50 +00001846 ~CommandObjectCommandsScriptClear() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001847
Jim Ingham5a988412012-06-08 21:56:10 +00001848protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001849 bool DoExecute(Args &command, CommandReturnObject &result) override {
1850 m_interpreter.RemoveAllUser();
1851
1852 result.SetStatus(eReturnStatusSuccessFinishResult);
1853
1854 return true;
1855 }
Enrico Granata223383e2011-08-16 23:24:13 +00001856};
1857
1858//-------------------------------------------------------------------------
1859// CommandObjectCommandsScriptDelete
1860//-------------------------------------------------------------------------
1861
Kate Stoneb9c1b512016-09-06 20:57:50 +00001862class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001863public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001864 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1865 : CommandObjectParsed(interpreter, "command script delete",
1866 "Delete a scripted command.", nullptr) {
1867 CommandArgumentEntry arg1;
1868 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001869
Kate Stoneb9c1b512016-09-06 20:57:50 +00001870 // Define the first (and only) variant of this arg.
1871 cmd_arg.arg_type = eArgTypeCommandName;
1872 cmd_arg.arg_repetition = eArgRepeatPlain;
1873
1874 // There is only one variant this argument could be; put it into the
1875 // argument entry.
1876 arg1.push_back(cmd_arg);
1877
1878 // Push the data for the first argument into the m_arguments vector.
1879 m_arguments.push_back(arg1);
1880 }
1881
1882 ~CommandObjectCommandsScriptDelete() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001883
Jim Ingham5a988412012-06-08 21:56:10 +00001884protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001885 bool DoExecute(Args &command, CommandReturnObject &result) override {
1886
1887 size_t argc = command.GetArgumentCount();
1888
1889 if (argc != 1) {
1890 result.AppendError("'command script delete' requires one argument");
1891 result.SetStatus(eReturnStatusFailed);
1892 return false;
Enrico Granata223383e2011-08-16 23:24:13 +00001893 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001894
1895 const char *cmd_name = command.GetArgumentAtIndex(0);
1896
1897 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() &&
1898 m_interpreter.UserCommandExists(cmd_name)) {
1899 m_interpreter.RemoveUser(cmd_name);
1900 result.SetStatus(eReturnStatusSuccessFinishResult);
1901 } else {
1902 result.AppendErrorWithFormat("command %s not found", cmd_name);
1903 result.SetStatus(eReturnStatusFailed);
1904 }
1905
1906 return result.Succeeded();
1907 }
Enrico Granata223383e2011-08-16 23:24:13 +00001908};
1909
1910#pragma mark CommandObjectMultiwordCommandsScript
1911
1912//-------------------------------------------------------------------------
1913// CommandObjectMultiwordCommandsScript
1914//-------------------------------------------------------------------------
1915
Kate Stoneb9c1b512016-09-06 20:57:50 +00001916class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
Enrico Granata223383e2011-08-16 23:24:13 +00001917public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001918 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1919 : CommandObjectMultiword(
1920 interpreter, "command script", "Commands for managing custom "
1921 "commands implemented by "
1922 "interpreter scripts.",
1923 "command script <subcommand> [<subcommand-options>]") {
1924 LoadSubCommand("add", CommandObjectSP(
1925 new CommandObjectCommandsScriptAdd(interpreter)));
1926 LoadSubCommand(
1927 "delete",
1928 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1929 LoadSubCommand(
1930 "clear",
1931 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1932 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1933 interpreter)));
1934 LoadSubCommand(
1935 "import",
1936 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1937 }
Enrico Granata223383e2011-08-16 23:24:13 +00001938
Kate Stoneb9c1b512016-09-06 20:57:50 +00001939 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00001940};
1941
Jim Inghamebc09c32010-07-07 03:36:20 +00001942#pragma mark CommandObjectMultiwordCommands
1943
1944//-------------------------------------------------------------------------
1945// CommandObjectMultiwordCommands
1946//-------------------------------------------------------------------------
1947
Kate Stoneb9c1b512016-09-06 20:57:50 +00001948CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1949 CommandInterpreter &interpreter)
1950 : CommandObjectMultiword(interpreter, "command",
1951 "Commands for managing custom LLDB commands.",
1952 "command <subcommand> [<subcommand-options>]") {
1953 LoadSubCommand("source",
1954 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1955 LoadSubCommand("alias",
1956 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1957 LoadSubCommand("unalias", CommandObjectSP(
1958 new CommandObjectCommandsUnalias(interpreter)));
1959 LoadSubCommand("delete",
1960 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1961 LoadSubCommand(
1962 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1963 LoadSubCommand("history", CommandObjectSP(
1964 new CommandObjectCommandsHistory(interpreter)));
1965 LoadSubCommand(
1966 "script",
1967 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00001968}
1969
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001970CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;