blob: f4f3afb32ba37467d283ef3687a0518b9b69fdf5 [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
Kate Stoneb9c1b512016-09-06 20:57:50 +000039class CommandObjectCommandsHistory : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +000040public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 CommandObjectCommandsHistory(CommandInterpreter &interpreter)
42 : CommandObjectParsed(interpreter, "command history",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000043 "Dump the history of commands in this session.",
44 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 m_options() {}
Jim Ingham5a988412012-06-08 21:56:10 +000046
Kate Stoneb9c1b512016-09-06 20:57:50 +000047 ~CommandObjectCommandsHistory() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +000048
Kate Stoneb9c1b512016-09-06 20:57:50 +000049 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +000050
51protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 class CommandOptions : public Options {
53 public:
54 CommandOptions()
55 : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) {
Jim Inghama5a97eb2011-07-12 03:12:18 +000056 }
Jim Ingham5a988412012-06-08 21:56:10 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 ~CommandOptions() override = default;
59
60 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
61 ExecutionContext *execution_context) override {
62 Error error;
63 const int short_option = m_getopt_table[option_idx].val;
64
65 switch (short_option) {
66 case 'c':
67 error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign);
68 break;
69 case 's':
70 if (option_arg && strcmp("end", option_arg) == 0) {
71 m_start_idx.SetCurrentValue(UINT64_MAX);
72 m_start_idx.SetOptionWasSet();
73 } else
74 error = m_start_idx.SetValueFromString(option_arg,
75 eVarSetOperationAssign);
76 break;
77 case 'e':
78 error =
79 m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign);
80 break;
81 case 'C':
82 m_clear.SetCurrentValue(true);
83 m_clear.SetOptionWasSet();
84 break;
85 default:
86 error.SetErrorStringWithFormat("unrecognized option '%c'",
87 short_option);
88 break;
89 }
90
91 return error;
92 }
93
94 void OptionParsingStarting(ExecutionContext *execution_context) override {
95 m_start_idx.Clear();
96 m_stop_idx.Clear();
97 m_count.Clear();
98 m_clear.Clear();
99 }
100
101 const OptionDefinition *GetDefinitions() override { return g_option_table; }
102
103 // Options table: Required for subclasses of Options.
104
105 static OptionDefinition g_option_table[];
106
107 // Instance variables to hold the values for command options.
108
109 OptionValueUInt64 m_start_idx;
110 OptionValueUInt64 m_stop_idx;
111 OptionValueUInt64 m_count;
112 OptionValueBoolean m_clear;
113 };
114
115 bool DoExecute(Args &command, CommandReturnObject &result) override {
116 if (m_options.m_clear.GetCurrentValue() &&
117 m_options.m_clear.OptionWasSet()) {
118 m_interpreter.GetCommandHistory().Clear();
119 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
120 } else {
121 if (m_options.m_start_idx.OptionWasSet() &&
122 m_options.m_stop_idx.OptionWasSet() &&
123 m_options.m_count.OptionWasSet()) {
124 result.AppendError("--count, --start-index and --end-index cannot be "
125 "all specified in the same invocation");
126 result.SetStatus(lldb::eReturnStatusFailed);
127 } else {
128 std::pair<bool, uint64_t> start_idx(
129 m_options.m_start_idx.OptionWasSet(),
130 m_options.m_start_idx.GetCurrentValue());
131 std::pair<bool, uint64_t> stop_idx(
132 m_options.m_stop_idx.OptionWasSet(),
133 m_options.m_stop_idx.GetCurrentValue());
134 std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(),
135 m_options.m_count.GetCurrentValue());
136
137 const CommandHistory &history(m_interpreter.GetCommandHistory());
138
139 if (start_idx.first && start_idx.second == UINT64_MAX) {
140 if (count.first) {
141 start_idx.second = history.GetSize() - count.second;
142 stop_idx.second = history.GetSize() - 1;
143 } else if (stop_idx.first) {
144 start_idx.second = stop_idx.second;
145 stop_idx.second = history.GetSize() - 1;
146 } else {
147 start_idx.second = 0;
148 stop_idx.second = history.GetSize() - 1;
149 }
150 } else {
151 if (!start_idx.first && !stop_idx.first && !count.first) {
152 start_idx.second = 0;
153 stop_idx.second = history.GetSize() - 1;
154 } else if (start_idx.first) {
155 if (count.first) {
156 stop_idx.second = start_idx.second + count.second - 1;
157 } else if (!stop_idx.first) {
158 stop_idx.second = history.GetSize() - 1;
159 }
160 } else if (stop_idx.first) {
161 if (count.first) {
162 if (stop_idx.second >= count.second)
163 start_idx.second = stop_idx.second - count.second + 1;
164 else
165 start_idx.second = 0;
166 }
167 } else /* if (count.first) */
168 {
169 start_idx.second = 0;
170 stop_idx.second = count.second - 1;
171 }
172 }
173 history.Dump(result.GetOutputStream(), start_idx.second,
174 stop_idx.second);
175 }
176 }
177 return result.Succeeded();
178 }
179
180 CommandOptions m_options;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000181};
182
183OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 CommandObjectCommandsHistory::CommandOptions::g_option_table[] = {
185 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +0000186 {LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
187 {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)."},
188 {LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
189 {LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."},
190 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000191 // clang-format on
Jim Inghama5a97eb2011-07-12 03:12:18 +0000192};
193
Jim Inghama5a97eb2011-07-12 03:12:18 +0000194//-------------------------------------------------------------------------
195// CommandObjectCommandsSource
196//-------------------------------------------------------------------------
197
Kate Stoneb9c1b512016-09-06 20:57:50 +0000198class CommandObjectCommandsSource : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000199public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200 CommandObjectCommandsSource(CommandInterpreter &interpreter)
201 : CommandObjectParsed(
202 interpreter, "command source",
203 "Read and execute LLDB commands from the file <filename>.",
204 nullptr),
205 m_options() {
206 CommandArgumentEntry arg;
207 CommandArgumentData file_arg;
Jim Ingham5a988412012-06-08 21:56:10 +0000208
Kate Stoneb9c1b512016-09-06 20:57:50 +0000209 // Define the first (and only) variant of this arg.
210 file_arg.arg_type = eArgTypeFilename;
211 file_arg.arg_repetition = eArgRepeatPlain;
Jim Ingham5a988412012-06-08 21:56:10 +0000212
Kate Stoneb9c1b512016-09-06 20:57:50 +0000213 // There is only one variant this argument could be; put it into the
214 // argument entry.
215 arg.push_back(file_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +0000216
Kate Stoneb9c1b512016-09-06 20:57:50 +0000217 // Push the data for the first argument into the m_arguments vector.
218 m_arguments.push_back(arg);
219 }
Jim Ingham5a988412012-06-08 21:56:10 +0000220
Kate Stoneb9c1b512016-09-06 20:57:50 +0000221 ~CommandObjectCommandsSource() override = default;
222
223 const char *GetRepeatCommand(Args &current_command_args,
224 uint32_t index) override {
225 return "";
226 }
227
228 int HandleArgumentCompletion(Args &input, int &cursor_index,
229 int &cursor_char_position,
230 OptionElementVector &opt_element_vector,
231 int match_start_point, int max_return_elements,
232 bool &word_complete,
233 StringList &matches) override {
234 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
235 completion_str.erase(cursor_char_position);
236
237 CommandCompletions::InvokeCommonCompletionCallbacks(
238 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
239 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
240 word_complete, matches);
241 return matches.GetSize();
242 }
243
244 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +0000245
246protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 class CommandOptions : public Options {
248 public:
249 CommandOptions()
250 : Options(), m_stop_on_error(true), m_silent_run(false),
251 m_stop_on_continue(true) {}
Jim Inghame16c50a2011-02-18 00:54:25 +0000252
Kate Stoneb9c1b512016-09-06 20:57:50 +0000253 ~CommandOptions() override = default;
Jim Inghame16c50a2011-02-18 00:54:25 +0000254
Kate Stoneb9c1b512016-09-06 20:57:50 +0000255 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
256 ExecutionContext *execution_context) override {
257 Error error;
258 const int short_option = m_getopt_table[option_idx].val;
Greg Clayton340b0302014-02-05 17:57:57 +0000259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260 switch (short_option) {
261 case 'e':
262 error = m_stop_on_error.SetValueFromString(option_arg);
263 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000264
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265 case 'c':
266 error = m_stop_on_continue.SetValueFromString(option_arg);
267 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000268
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 case 's':
270 error = m_silent_run.SetValueFromString(option_arg);
271 break;
Jim Inghame16c50a2011-02-18 00:54:25 +0000272
Kate Stoneb9c1b512016-09-06 20:57:50 +0000273 default:
274 error.SetErrorStringWithFormat("unrecognized option '%c'",
275 short_option);
276 break;
277 }
Jim Inghame16c50a2011-02-18 00:54:25 +0000278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 return error;
Jim Inghamebc09c32010-07-07 03:36:20 +0000280 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000281
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 void OptionParsingStarting(ExecutionContext *execution_context) override {
283 m_stop_on_error.Clear();
284 m_silent_run.Clear();
285 m_stop_on_continue.Clear();
286 }
287
288 const OptionDefinition *GetDefinitions() override { return g_option_table; }
289
290 // Options table: Required for subclasses of Options.
291
292 static OptionDefinition g_option_table[];
293
294 // Instance variables to hold the values for command options.
295
296 OptionValueBoolean m_stop_on_error;
297 OptionValueBoolean m_silent_run;
298 OptionValueBoolean m_stop_on_continue;
299 };
300
301 bool DoExecute(Args &command, CommandReturnObject &result) override {
302 const size_t argc = command.GetArgumentCount();
303 if (argc == 1) {
304 const char *filename = command.GetArgumentAtIndex(0);
305
306 FileSpec cmd_file(filename, true);
307 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
308
309 // If any options were set, then use them
310 if (m_options.m_stop_on_error.OptionWasSet() ||
311 m_options.m_silent_run.OptionWasSet() ||
312 m_options.m_stop_on_continue.OptionWasSet()) {
313 // Use user set settings
314 CommandInterpreterRunOptions options;
315 options.SetStopOnContinue(
316 m_options.m_stop_on_continue.GetCurrentValue());
317 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
318 options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
319 options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
320
321 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
322 result);
323 } else {
324 // No options were set, inherit any settings from nested "command
325 // source" commands,
326 // or set to sane default settings...
327 CommandInterpreterRunOptions options;
328 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options,
329 result);
330 }
331 } else {
332 result.AppendErrorWithFormat(
333 "'%s' takes exactly one executable filename argument.\n",
334 GetCommandName());
335 result.SetStatus(eReturnStatusFailed);
336 }
337 return result.Succeeded();
338 }
339
340 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000341};
342
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343OptionDefinition CommandObjectCommandsSource::CommandOptions::g_option_table[] =
344 {
345 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +0000346 {LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
347 {LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
348 {LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
349 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350 // clang-format on
Jim Inghame16c50a2011-02-18 00:54:25 +0000351};
352
Jim Inghamebc09c32010-07-07 03:36:20 +0000353#pragma mark CommandObjectCommandsAlias
354//-------------------------------------------------------------------------
355// CommandObjectCommandsAlias
356//-------------------------------------------------------------------------
357
Kate Stoneb9c1b512016-09-06 20:57:50 +0000358static const char *g_python_command_instructions =
359 "Enter your Python command(s). Type 'DONE' to end.\n"
360 "You must define a Python function with this signature:\n"
361 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000362
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363class CommandObjectCommandsAlias : public CommandObjectRaw {
Enrico Granata45d0e232016-03-31 01:10:54 +0000364protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 class CommandOptions : public OptionGroup {
366 public:
367 CommandOptions() : OptionGroup(), m_help(), m_long_help() {}
Enrico Granata45d0e232016-03-31 01:10:54 +0000368
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 ~CommandOptions() override = default;
370
371 uint32_t GetNumDefinitions() override { return 3; }
372
373 const OptionDefinition *GetDefinitions() override { return g_option_table; }
374
375 Error SetOptionValue(uint32_t option_idx, const char *option_value,
376 ExecutionContext *execution_context) override {
377 Error error;
378
379 const int short_option = g_option_table[option_idx].short_option;
380
381 switch (short_option) {
382 case 'h':
383 m_help.SetCurrentValue(option_value);
384 m_help.SetOptionWasSet();
385 break;
386
387 case 'H':
388 m_long_help.SetCurrentValue(option_value);
389 m_long_help.SetOptionWasSet();
390 break;
391
392 default:
393 error.SetErrorStringWithFormat("invalid short option character '%c'",
394 short_option);
395 break;
396 }
397
398 return error;
Enrico Granata45d0e232016-03-31 01:10:54 +0000399 }
400
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 void OptionParsingStarting(ExecutionContext *execution_context) override {
402 m_help.Clear();
403 m_long_help.Clear();
404 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000405
Kate Stoneb9c1b512016-09-06 20:57:50 +0000406 // Options table: Required for subclasses of Options.
407
408 static OptionDefinition g_option_table[];
409 OptionValueString m_help;
410 OptionValueString m_long_help;
411 };
412
413 OptionGroupOptions m_option_group;
414 CommandOptions m_command_options;
415
416public:
417 Options *GetOptions() override { return &m_option_group; }
418
419 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
420 : CommandObjectRaw(
421 interpreter, "command alias",
422 "Define a custom command in terms of an existing command.",
423 nullptr),
424 m_option_group(), m_command_options() {
425 m_option_group.Append(&m_command_options);
426 m_option_group.Finalize();
427
428 SetHelpLong(
429 "'alias' allows the user to create a short-cut or abbreviation for long \
Kate Stoneea671fb2015-07-14 05:48:36 +0000430commands, multi-word commands, and commands that take particular options. \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431Below are some simple examples of how one might use the 'alias' command:"
432 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000433
434(lldb) command alias sc script
435
436 Creates the abbreviation 'sc' for the 'script' command.
437
438(lldb) command alias bp breakpoint
439
Kate Stoneb9c1b512016-09-06 20:57:50 +0000440)"
441 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
Kate Stoneea671fb2015-07-14 05:48:36 +0000442breakpoint commands are two-word commands, the user would still need to \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000443enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'."
444 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000445
446(lldb) command alias bpl breakpoint list
447
448 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
449
Kate Stoneb9c1b512016-09-06 20:57:50 +0000450)"
451 "An alias can include some options for the command, with the values either \
Kate Stoneea671fb2015-07-14 05:48:36 +0000452filled in at the time the alias is created, or specified as positional \
453arguments, to be filled in when the alias is invoked. The following example \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454shows how to create aliases with options:"
455 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000456
457(lldb) command alias bfl breakpoint set -f %1 -l %2
458
Kate Stoneb9c1b512016-09-06 20:57:50 +0000459)"
460 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
Kate Stoneea671fb2015-07-14 05:48:36 +0000461options already part of the alias. So if the user wants to set a breakpoint \
462by file and line without explicitly having to use the -f and -l options, the \
463user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
464for the actual arguments that will be passed when the alias command is used. \
465The number in the placeholder refers to the position/order the actual value \
466occupies when the alias is used. All the occurrences of '%1' in the alias \
467will be replaced with the first argument, all the occurrences of '%2' in the \
468alias will be replaced with the second argument, and so on. This also allows \
469actual arguments to be used multiple times within an alias (see 'process \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470launch' example below)."
471 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000472
Kate Stoneb9c1b512016-09-06 20:57:50 +0000473)"
474 "Note: the positional arguments must substitute as whole words in the resultant \
Kate Stoneea671fb2015-07-14 05:48:36 +0000475command, so you can't at present do something like this to append the file extension \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000476\".cpp\":"
477 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000478
479(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
480
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481)"
482 "For more complex aliasing, use the \"command regex\" command instead. In the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000483'bfl' case above, the actual file value will be filled in with the first argument \
484following 'bfl' and the actual line number value will be filled in with the second \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485argument. The user would use this alias as follows:"
486 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000487
488(lldb) command alias bfl breakpoint set -f %1 -l %2
489(lldb) bfl my-file.c 137
490
491This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
492
493Another example:
494
495(lldb) command alias pltty process launch -s -o %1 -e %1
496(lldb) pltty /dev/tty0
497
498 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
499
Kate Stoneb9c1b512016-09-06 20:57:50 +0000500)"
501 "If the user always wanted to pass the same value to a particular option, the \
Kate Stoneea671fb2015-07-14 05:48:36 +0000502alias could be defined with that value directly in the alias as a constant, \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000503rather than using a positional placeholder:"
504 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000505
506(lldb) command alias bl3 breakpoint set -f %1 -l 3
507
Kate Stoneb9c1b512016-09-06 20:57:50 +0000508 Always sets a breakpoint on line 3 of whatever file is indicated.)");
Jim Inghamebc09c32010-07-07 03:36:20 +0000509
Kate Stoneb9c1b512016-09-06 20:57:50 +0000510 CommandArgumentEntry arg1;
511 CommandArgumentEntry arg2;
512 CommandArgumentEntry arg3;
513 CommandArgumentData alias_arg;
514 CommandArgumentData cmd_arg;
515 CommandArgumentData options_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000516
Kate Stoneb9c1b512016-09-06 20:57:50 +0000517 // Define the first (and only) variant of this arg.
518 alias_arg.arg_type = eArgTypeAliasName;
519 alias_arg.arg_repetition = eArgRepeatPlain;
520
521 // There is only one variant this argument could be; put it into the
522 // argument entry.
523 arg1.push_back(alias_arg);
524
525 // Define the first (and only) variant of this arg.
526 cmd_arg.arg_type = eArgTypeCommandName;
527 cmd_arg.arg_repetition = eArgRepeatPlain;
528
529 // There is only one variant this argument could be; put it into the
530 // argument entry.
531 arg2.push_back(cmd_arg);
532
533 // Define the first (and only) variant of this arg.
534 options_arg.arg_type = eArgTypeAliasOptions;
535 options_arg.arg_repetition = eArgRepeatOptional;
536
537 // There is only one variant this argument could be; put it into the
538 // argument entry.
539 arg3.push_back(options_arg);
540
541 // Push the data for the first argument into the m_arguments vector.
542 m_arguments.push_back(arg1);
543 m_arguments.push_back(arg2);
544 m_arguments.push_back(arg3);
545 }
546
547 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000548
Jim Ingham5a988412012-06-08 21:56:10 +0000549protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550 bool DoExecute(const char *raw_command_line,
551 CommandReturnObject &result) override {
552 if (!raw_command_line || !raw_command_line[0]) {
553 result.AppendError("'command alias' requires at least two arguments");
554 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000555 }
556
Kate Stoneb9c1b512016-09-06 20:57:50 +0000557 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
558 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
Caroline Ticeca90c472011-05-06 21:37:15 +0000559
Kate Stoneb9c1b512016-09-06 20:57:50 +0000560 const char *remainder = nullptr;
Enrico Granata212130a2016-03-08 05:37:15 +0000561
Kate Stoneb9c1b512016-09-06 20:57:50 +0000562 if (raw_command_line[0] == '-') {
563 // We have some options and these options MUST end with --.
564 const char *end_options = nullptr;
565 const char *s = raw_command_line;
566 while (s && s[0]) {
567 end_options = ::strstr(s, "--");
568 if (end_options) {
569 end_options += 2; // Get past the "--"
570 if (::isspace(end_options[0])) {
571 remainder = end_options;
572 while (::isspace(*remainder))
573 ++remainder;
574 break;
575 }
576 }
577 s = end_options;
578 }
579
580 if (end_options) {
581 Args args(
582 llvm::StringRef(raw_command_line, end_options - raw_command_line));
583 if (!ParseOptions(args, result))
584 return false;
585
586 Error error(m_option_group.NotifyOptionParsingFinished(&exe_ctx));
587 if (error.Fail()) {
588 result.AppendError(error.AsCString());
589 result.SetStatus(eReturnStatusFailed);
590 return false;
591 }
592 }
Caroline Tice844d2302010-12-09 22:52:49 +0000593 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000594 if (nullptr == remainder)
595 remainder = raw_command_line;
Jim Inghamebc09c32010-07-07 03:36:20 +0000596
Kate Stoneb9c1b512016-09-06 20:57:50 +0000597 std::string raw_command_string(remainder);
598 Args args(raw_command_string.c_str());
Jim Inghamebc09c32010-07-07 03:36:20 +0000599
Kate Stoneb9c1b512016-09-06 20:57:50 +0000600 size_t argc = args.GetArgumentCount();
Jim Inghamebc09c32010-07-07 03:36:20 +0000601
Kate Stoneb9c1b512016-09-06 20:57:50 +0000602 if (argc < 2) {
603 result.AppendError("'command alias' requires at least two arguments");
604 result.SetStatus(eReturnStatusFailed);
605 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000606 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000607
608 // Get the alias command.
609
610 const std::string alias_command = args.GetArgumentAtIndex(0);
611 if (alias_command.size() > 1 && alias_command[0] == '-') {
612 result.AppendError("aliases starting with a dash are not supported");
613 if (alias_command == "--help" || alias_command == "--long-help") {
614 result.AppendWarning("if trying to pass options to 'command alias' add "
615 "a -- at the end of the options");
616 }
617 result.SetStatus(eReturnStatusFailed);
618 return false;
619 }
620
621 // Strip the new alias name off 'raw_command_string' (leave it on args,
622 // which gets passed to 'Execute', which
623 // does the stripping itself.
624 size_t pos = raw_command_string.find(alias_command);
625 if (pos == 0) {
626 raw_command_string = raw_command_string.substr(alias_command.size());
627 pos = raw_command_string.find_first_not_of(' ');
628 if ((pos != std::string::npos) && (pos > 0))
629 raw_command_string = raw_command_string.substr(pos);
630 } else {
631 result.AppendError("Error parsing command string. No alias created.");
632 result.SetStatus(eReturnStatusFailed);
633 return false;
634 }
635
636 // Verify that the command is alias-able.
637 if (m_interpreter.CommandExists(alias_command.c_str())) {
638 result.AppendErrorWithFormat(
639 "'%s' is a permanent debugger command and cannot be redefined.\n",
640 alias_command.c_str());
641 result.SetStatus(eReturnStatusFailed);
642 return false;
643 }
644
645 // Get CommandObject that is being aliased. The command name is read from
646 // the front of raw_command_string.
647 // raw_command_string is returned with the name of the command object
648 // stripped off the front.
649 std::string original_raw_command_string(raw_command_string);
650 CommandObject *cmd_obj =
651 m_interpreter.GetCommandObjectForCommand(raw_command_string);
652
653 if (!cmd_obj) {
654 result.AppendErrorWithFormat("invalid command given to 'command alias'. "
655 "'%s' does not begin with a valid command."
656 " No alias created.",
657 original_raw_command_string.c_str());
658 result.SetStatus(eReturnStatusFailed);
659 return false;
660 } else if (!cmd_obj->WantsRawCommandString()) {
661 // Note that args was initialized with the original command, and has not
662 // been updated to this point.
663 // Therefore can we pass it to the version of Execute that does not
664 // need/expect raw input in the alias.
665 return HandleAliasingNormalCommand(args, result);
666 } else {
667 return HandleAliasingRawCommand(alias_command, raw_command_string,
668 *cmd_obj, result);
669 }
670 return result.Succeeded();
671 }
672
673 bool HandleAliasingRawCommand(const std::string &alias_command,
674 std::string &raw_command_string,
675 CommandObject &cmd_obj,
676 CommandReturnObject &result) {
677 // Verify & handle any options/arguments passed to the alias command
678
679 OptionArgVectorSP option_arg_vector_sp =
680 OptionArgVectorSP(new OptionArgVector);
681
682 if (CommandObjectSP cmd_obj_sp =
683 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) {
684 if (m_interpreter.AliasExists(alias_command.c_str()) ||
685 m_interpreter.UserCommandExists(alias_command.c_str())) {
686 result.AppendWarningWithFormat(
687 "Overwriting existing definition for '%s'.\n",
688 alias_command.c_str());
689 }
690 if (CommandAlias *alias = m_interpreter.AddAlias(
691 alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str())) {
692 if (m_command_options.m_help.OptionWasSet())
693 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
694 if (m_command_options.m_long_help.OptionWasSet())
695 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
696 result.SetStatus(eReturnStatusSuccessFinishNoResult);
697 } else {
698 result.AppendError("Unable to create requested alias.\n");
699 result.SetStatus(eReturnStatusFailed);
700 }
701
702 } else {
703 result.AppendError("Unable to create requested alias.\n");
704 result.SetStatus(eReturnStatusFailed);
705 }
706
707 return result.Succeeded();
708 }
709
710 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) {
711 size_t argc = args.GetArgumentCount();
712
713 if (argc < 2) {
714 result.AppendError("'command alias' requires at least two arguments");
715 result.SetStatus(eReturnStatusFailed);
716 return false;
717 }
718
719 const std::string alias_command = args.GetArgumentAtIndex(0);
720 const std::string actual_command = args.GetArgumentAtIndex(1);
721
722 args.Shift(); // Shift the alias command word off the argument vector.
723 args.Shift(); // Shift the old command word off the argument vector.
724
725 // Verify that the command is alias'able, and get the appropriate command
726 // object.
727
728 if (m_interpreter.CommandExists(alias_command.c_str())) {
729 result.AppendErrorWithFormat(
730 "'%s' is a permanent debugger command and cannot be redefined.\n",
731 alias_command.c_str());
732 result.SetStatus(eReturnStatusFailed);
733 } else {
734 CommandObjectSP command_obj_sp(
735 m_interpreter.GetCommandSPExact(actual_command.c_str(), true));
736 CommandObjectSP subcommand_obj_sp;
737 bool use_subcommand = false;
738 if (command_obj_sp) {
739 CommandObject *cmd_obj = command_obj_sp.get();
740 CommandObject *sub_cmd_obj = nullptr;
741 OptionArgVectorSP option_arg_vector_sp =
742 OptionArgVectorSP(new OptionArgVector);
743
744 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0) {
745 if (argc >= 3) {
746 const std::string sub_command = args.GetArgumentAtIndex(0);
747 assert(sub_command.length() != 0);
748 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command.c_str());
749 if (subcommand_obj_sp) {
750 sub_cmd_obj = subcommand_obj_sp.get();
751 use_subcommand = true;
752 args.Shift(); // Shift the sub_command word off the argument
753 // vector.
754 cmd_obj = sub_cmd_obj;
755 } else {
756 result.AppendErrorWithFormat(
757 "'%s' is not a valid sub-command of '%s'. "
758 "Unable to create alias.\n",
759 sub_command.c_str(), actual_command.c_str());
760 result.SetStatus(eReturnStatusFailed);
761 return false;
762 }
763 }
764 }
765
766 // Verify & handle any options/arguments passed to the alias command
767
768 std::string args_string;
769
770 if (args.GetArgumentCount() > 0) {
771 CommandObjectSP tmp_sp =
772 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false);
773 if (use_subcommand)
774 tmp_sp = m_interpreter.GetCommandSPExact(
775 sub_cmd_obj->GetCommandName(), false);
776
777 args.GetCommandString(args_string);
778 }
779
780 if (m_interpreter.AliasExists(alias_command.c_str()) ||
781 m_interpreter.UserCommandExists(alias_command.c_str())) {
782 result.AppendWarningWithFormat(
783 "Overwriting existing definition for '%s'.\n",
784 alias_command.c_str());
785 }
786
787 if (CommandAlias *alias = m_interpreter.AddAlias(
788 alias_command.c_str(),
789 use_subcommand ? subcommand_obj_sp : command_obj_sp,
790 args_string.c_str())) {
791 if (m_command_options.m_help.OptionWasSet())
792 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
793 if (m_command_options.m_long_help.OptionWasSet())
794 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
795 result.SetStatus(eReturnStatusSuccessFinishNoResult);
796 } else {
797 result.AppendError("Unable to create requested alias.\n");
798 result.SetStatus(eReturnStatusFailed);
799 return false;
800 }
801 } else {
802 result.AppendErrorWithFormat("'%s' is not an existing command.\n",
803 actual_command.c_str());
804 result.SetStatus(eReturnStatusFailed);
805 return false;
806 }
807 }
808
809 return result.Succeeded();
810 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000811};
812
Kate Stoneb9c1b512016-09-06 20:57:50 +0000813OptionDefinition CommandObjectCommandsAlias::CommandOptions::g_option_table[] =
814 {
815 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +0000816 {LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"},
817 {LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"},
818 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +0000819 // clang-format on
Enrico Granata45d0e232016-03-31 01:10:54 +0000820};
821
Jim Inghamebc09c32010-07-07 03:36:20 +0000822#pragma mark CommandObjectCommandsUnalias
823//-------------------------------------------------------------------------
824// CommandObjectCommandsUnalias
825//-------------------------------------------------------------------------
826
Kate Stoneb9c1b512016-09-06 20:57:50 +0000827class CommandObjectCommandsUnalias : public CommandObjectParsed {
Jim Inghamebc09c32010-07-07 03:36:20 +0000828public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000829 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
830 : CommandObjectParsed(
831 interpreter, "command unalias",
832 "Delete one or more custom commands defined by 'command alias'.",
833 nullptr) {
834 CommandArgumentEntry arg;
835 CommandArgumentData alias_arg;
Jim Inghamebc09c32010-07-07 03:36:20 +0000836
Kate Stoneb9c1b512016-09-06 20:57:50 +0000837 // Define the first (and only) variant of this arg.
838 alias_arg.arg_type = eArgTypeAliasName;
839 alias_arg.arg_repetition = eArgRepeatPlain;
840
841 // There is only one variant this argument could be; put it into the
842 // argument entry.
843 arg.push_back(alias_arg);
844
845 // Push the data for the first argument into the m_arguments vector.
846 m_arguments.push_back(arg);
847 }
848
849 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000850
Jim Ingham5a988412012-06-08 21:56:10 +0000851protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000852 bool DoExecute(Args &args, CommandReturnObject &result) override {
853 CommandObject::CommandMap::iterator pos;
854 CommandObject *cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000855
Kate Stoneb9c1b512016-09-06 20:57:50 +0000856 if (args.GetArgumentCount() != 0) {
857 const char *command_name = args.GetArgumentAtIndex(0);
858 cmd_obj = m_interpreter.GetCommandObject(command_name);
859 if (cmd_obj) {
860 if (m_interpreter.CommandExists(command_name)) {
861 if (cmd_obj->IsRemovable()) {
862 result.AppendErrorWithFormat(
863 "'%s' is not an alias, it is a debugger command which can be "
864 "removed using the 'command delete' command.\n",
865 command_name);
866 } else {
867 result.AppendErrorWithFormat(
868 "'%s' is a permanent debugger command and cannot be removed.\n",
869 command_name);
870 }
871 result.SetStatus(eReturnStatusFailed);
872 } else {
873 if (!m_interpreter.RemoveAlias(command_name)) {
874 if (m_interpreter.AliasExists(command_name))
875 result.AppendErrorWithFormat(
876 "Error occurred while attempting to unalias '%s'.\n",
877 command_name);
Jim Inghamebc09c32010-07-07 03:36:20 +0000878 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000879 result.AppendErrorWithFormat("'%s' is not an existing alias.\n",
880 command_name);
881 result.SetStatus(eReturnStatusFailed);
882 } else
883 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Jim Inghamebc09c32010-07-07 03:36:20 +0000884 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000885 } else {
886 result.AppendErrorWithFormat(
887 "'%s' is not a known command.\nTry 'help' to see a "
888 "current list of commands.\n",
889 command_name);
890 result.SetStatus(eReturnStatusFailed);
891 }
892 } else {
893 result.AppendError("must call 'unalias' with a valid alias");
894 result.SetStatus(eReturnStatusFailed);
Jim Inghamebc09c32010-07-07 03:36:20 +0000895 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000896
897 return result.Succeeded();
898 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000899};
900
Greg Claytonb5472782015-01-09 19:08:20 +0000901#pragma mark CommandObjectCommandsDelete
902//-------------------------------------------------------------------------
903// CommandObjectCommandsDelete
904//-------------------------------------------------------------------------
905
Kate Stoneb9c1b512016-09-06 20:57:50 +0000906class CommandObjectCommandsDelete : public CommandObjectParsed {
Greg Claytonb5472782015-01-09 19:08:20 +0000907public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000908 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
909 : CommandObjectParsed(
910 interpreter, "command delete",
911 "Delete one or more custom commands defined by 'command regex'.",
912 nullptr) {
913 CommandArgumentEntry arg;
914 CommandArgumentData alias_arg;
Greg Claytonb5472782015-01-09 19:08:20 +0000915
Kate Stoneb9c1b512016-09-06 20:57:50 +0000916 // Define the first (and only) variant of this arg.
917 alias_arg.arg_type = eArgTypeCommandName;
918 alias_arg.arg_repetition = eArgRepeatPlain;
Greg Claytonb5472782015-01-09 19:08:20 +0000919
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 // There is only one variant this argument could be; put it into the
921 // argument entry.
922 arg.push_back(alias_arg);
Greg Claytonb5472782015-01-09 19:08:20 +0000923
Kate Stoneb9c1b512016-09-06 20:57:50 +0000924 // Push the data for the first argument into the m_arguments vector.
925 m_arguments.push_back(arg);
926 }
Greg Claytonb5472782015-01-09 19:08:20 +0000927
Kate Stoneb9c1b512016-09-06 20:57:50 +0000928 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +0000929
930protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000931 bool DoExecute(Args &args, CommandReturnObject &result) override {
932 CommandObject::CommandMap::iterator pos;
Greg Claytonb5472782015-01-09 19:08:20 +0000933
Kate Stoneb9c1b512016-09-06 20:57:50 +0000934 if (args.GetArgumentCount() != 0) {
935 const char *command_name = args.GetArgumentAtIndex(0);
936 if (m_interpreter.CommandExists(command_name)) {
937 if (m_interpreter.RemoveCommand(command_name)) {
938 result.SetStatus(eReturnStatusSuccessFinishNoResult);
939 } else {
940 result.AppendErrorWithFormat(
941 "'%s' is a permanent debugger command and cannot be removed.\n",
942 command_name);
943 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000944 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000945 } else {
946 StreamString error_msg_stream;
947 const bool generate_apropos = true;
948 const bool generate_type_lookup = false;
949 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(
950 &error_msg_stream, command_name, nullptr, nullptr, generate_apropos,
951 generate_type_lookup);
952 result.AppendErrorWithFormat("%s", error_msg_stream.GetData());
953 result.SetStatus(eReturnStatusFailed);
954 }
955 } else {
956 result.AppendErrorWithFormat("must call '%s' with one or more valid user "
957 "defined regular expression command names",
958 GetCommandName());
959 result.SetStatus(eReturnStatusFailed);
Greg Claytonb5472782015-01-09 19:08:20 +0000960 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000961
962 return result.Succeeded();
963 }
Greg Claytonb5472782015-01-09 19:08:20 +0000964};
965
Greg Claytonde164aa2011-04-20 16:37:46 +0000966//-------------------------------------------------------------------------
967// CommandObjectCommandsAddRegex
968//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000969#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +0000970
Kate Stoneb9c1b512016-09-06 20:57:50 +0000971class CommandObjectCommandsAddRegex : public CommandObjectParsed,
972 public IOHandlerDelegateMultiline {
Greg Claytonde164aa2011-04-20 16:37:46 +0000973public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000974 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
975 : CommandObjectParsed(
976 interpreter, "command regex", "Define a custom command in terms of "
977 "existing commands by matching "
978 "regular expressions.",
979 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
980 IOHandlerDelegateMultiline("",
981 IOHandlerDelegate::Completion::LLDBCommand),
982 m_options() {
983 SetHelpLong(
984 R"(
985)"
986 "This command allows the user to create powerful regular expression commands \
Kate Stoneea671fb2015-07-14 05:48:36 +0000987with substitutions. The regular expressions and substitutions are specified \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000988using the regular expression substitution format of:"
989 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000990
991 s/<regex>/<subst>/
992
Kate Stoneb9c1b512016-09-06 20:57:50 +0000993)"
994 "<regex> is a regular expression that can use parenthesis to capture regular \
Kate Stoneea671fb2015-07-14 05:48:36 +0000995expression input and substitute the captured matches in the output using %1 \
Kate Stoneb9c1b512016-09-06 20:57:50 +0000996for the first match, %2 for the second, and so on."
997 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +0000998
Kate Stoneb9c1b512016-09-06 20:57:50 +0000999)"
1000 "The regular expressions can all be specified on the command line if more than \
Kate Stoneea671fb2015-07-14 05:48:36 +00001001one argument is provided. If just the command name is provided on the command \
1002line, then the regular expressions and substitutions can be entered on separate \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001003lines, followed by an empty line to terminate the command definition."
1004 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001005
1006EXAMPLES
1007
Kate Stoneb9c1b512016-09-06 20:57:50 +00001008)"
1009 "The following example will define a regular expression command named 'f' that \
Kate Stoneea671fb2015-07-14 05:48:36 +00001010will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011a number follows 'f':"
1012 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001013
Kate Stoneb9c1b512016-09-06 20:57:50 +00001014 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')");
1015 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001016
Kate Stoneb9c1b512016-09-06 20:57:50 +00001017 ~CommandObjectCommandsAddRegex() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001018
Jim Ingham5a988412012-06-08 21:56:10 +00001019protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001020 void IOHandlerActivated(IOHandler &io_handler) override {
1021 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1022 if (output_sp) {
1023 output_sp->PutCString("Enter one of more sed substitution commands in "
1024 "the form: 's/<regex>/<subst>/'.\nTerminate the "
1025 "substitution list with an empty line.\n");
1026 output_sp->Flush();
1027 }
1028 }
1029
1030 void IOHandlerInputComplete(IOHandler &io_handler,
1031 std::string &data) override {
1032 io_handler.SetIsDone(true);
1033 if (m_regex_cmd_ap) {
1034 StringList lines;
1035 if (lines.SplitIntoLines(data)) {
1036 const size_t num_lines = lines.GetSize();
1037 bool check_only = false;
1038 for (size_t i = 0; i < num_lines; ++i) {
1039 llvm::StringRef bytes_strref(lines[i]);
1040 Error error = AppendRegexSubstitution(bytes_strref, check_only);
1041 if (error.Fail()) {
1042 if (!m_interpreter.GetDebugger()
1043 .GetCommandInterpreter()
1044 .GetBatchCommandMode()) {
1045 StreamSP out_stream =
1046 m_interpreter.GetDebugger().GetAsyncOutputStream();
1047 out_stream->Printf("error: %s\n", error.AsCString());
1048 }
1049 }
Greg Clayton44d93782014-01-27 23:43:24 +00001050 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001051 }
1052 if (m_regex_cmd_ap->HasRegexEntries()) {
1053 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1054 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1055 }
1056 }
1057 }
1058
1059 bool DoExecute(Args &command, CommandReturnObject &result) override {
1060 const size_t argc = command.GetArgumentCount();
1061 if (argc == 0) {
1062 result.AppendError("usage: 'command regex <command-name> "
1063 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1064 result.SetStatus(eReturnStatusFailed);
1065 } else {
1066 Error error;
1067 const char *name = command.GetArgumentAtIndex(0);
1068 m_regex_cmd_ap.reset(new CommandObjectRegexCommand(
1069 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10,
1070 0, true));
1071
1072 if (argc == 1) {
1073 Debugger &debugger = m_interpreter.GetDebugger();
1074 bool color_prompt = debugger.GetUseColor();
1075 const bool multiple_lines = true; // Get multiple lines
1076 IOHandlerSP io_handler_sp(new IOHandlerEditline(
1077 debugger, IOHandler::Type::Other,
1078 "lldb-regex", // Name of input reader for history
1079 "> ", // Prompt
1080 nullptr, // Continuation prompt
1081 multiple_lines, color_prompt,
1082 0, // Don't show line numbers
1083 *this));
1084
1085 if (io_handler_sp) {
1086 debugger.PushIOHandler(io_handler_sp);
1087 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1088 }
1089 } else {
1090 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx) {
1091 llvm::StringRef arg_strref(command.GetArgumentAtIndex(arg_idx));
1092 bool check_only = false;
1093 error = AppendRegexSubstitution(arg_strref, check_only);
1094 if (error.Fail())
1095 break;
1096 }
1097
1098 if (error.Success()) {
1099 AddRegexCommandToInterpreter();
1100 }
1101 }
1102 if (error.Fail()) {
1103 result.AppendError(error.AsCString());
1104 result.SetStatus(eReturnStatusFailed);
1105 }
Greg Clayton44d93782014-01-27 23:43:24 +00001106 }
1107
Kate Stoneb9c1b512016-09-06 20:57:50 +00001108 return result.Succeeded();
1109 }
1110
1111 Error AppendRegexSubstitution(const llvm::StringRef &regex_sed,
1112 bool check_only) {
1113 Error error;
1114
1115 if (!m_regex_cmd_ap) {
1116 error.SetErrorStringWithFormat(
1117 "invalid regular expression command object for: '%.*s'",
1118 (int)regex_sed.size(), regex_sed.data());
1119 return error;
Greg Clayton44d93782014-01-27 23:43:24 +00001120 }
Greg Clayton44d93782014-01-27 23:43:24 +00001121
Kate Stoneb9c1b512016-09-06 20:57:50 +00001122 size_t regex_sed_size = regex_sed.size();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001123
Kate Stoneb9c1b512016-09-06 20:57:50 +00001124 if (regex_sed_size <= 1) {
1125 error.SetErrorStringWithFormat(
1126 "regular expression substitution string is too short: '%.*s'",
1127 (int)regex_sed.size(), regex_sed.data());
1128 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001129 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001130
Kate Stoneb9c1b512016-09-06 20:57:50 +00001131 if (regex_sed[0] != 's') {
1132 error.SetErrorStringWithFormat("regular expression substitution string "
1133 "doesn't start with 's': '%.*s'",
1134 (int)regex_sed.size(), regex_sed.data());
1135 return error;
1136 }
1137 const size_t first_separator_char_pos = 1;
1138 // use the char that follows 's' as the regex separator character
1139 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1140 const char separator_char = regex_sed[first_separator_char_pos];
1141 const size_t second_separator_char_pos =
1142 regex_sed.find(separator_char, first_separator_char_pos + 1);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001143
Kate Stoneb9c1b512016-09-06 20:57:50 +00001144 if (second_separator_char_pos == std::string::npos) {
1145 error.SetErrorStringWithFormat(
1146 "missing second '%c' separator char after '%.*s' in '%.*s'",
1147 separator_char,
1148 (int)(regex_sed.size() - first_separator_char_pos - 1),
1149 regex_sed.data() + (first_separator_char_pos + 1),
1150 (int)regex_sed.size(), regex_sed.data());
1151 return error;
1152 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001153
Kate Stoneb9c1b512016-09-06 20:57:50 +00001154 const size_t third_separator_char_pos =
1155 regex_sed.find(separator_char, second_separator_char_pos + 1);
Greg Clayton44d93782014-01-27 23:43:24 +00001156
Kate Stoneb9c1b512016-09-06 20:57:50 +00001157 if (third_separator_char_pos == std::string::npos) {
1158 error.SetErrorStringWithFormat(
1159 "missing third '%c' separator char after '%.*s' in '%.*s'",
1160 separator_char,
1161 (int)(regex_sed.size() - second_separator_char_pos - 1),
1162 regex_sed.data() + (second_separator_char_pos + 1),
1163 (int)regex_sed.size(), regex_sed.data());
1164 return error;
1165 }
1166
1167 if (third_separator_char_pos != regex_sed_size - 1) {
1168 // Make sure that everything that follows the last regex
1169 // separator char
1170 if (regex_sed.find_first_not_of("\t\n\v\f\r ",
1171 third_separator_char_pos + 1) !=
1172 std::string::npos) {
1173 error.SetErrorStringWithFormat(
1174 "extra data found after the '%.*s' regular expression substitution "
1175 "string: '%.*s'",
1176 (int)third_separator_char_pos + 1, regex_sed.data(),
1177 (int)(regex_sed.size() - third_separator_char_pos - 1),
1178 regex_sed.data() + (third_separator_char_pos + 1));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001179 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001180 }
1181 } else if (first_separator_char_pos + 1 == second_separator_char_pos) {
1182 error.SetErrorStringWithFormat(
1183 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1184 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1185 regex_sed.data());
1186 return error;
1187 } else if (second_separator_char_pos + 1 == third_separator_char_pos) {
1188 error.SetErrorStringWithFormat(
1189 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1190 separator_char, separator_char, separator_char, (int)regex_sed.size(),
1191 regex_sed.data());
1192 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001193 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194
1195 if (!check_only) {
1196 std::string regex(regex_sed.substr(first_separator_char_pos + 1,
1197 second_separator_char_pos -
1198 first_separator_char_pos - 1));
1199 std::string subst(regex_sed.substr(second_separator_char_pos + 1,
1200 third_separator_char_pos -
1201 second_separator_char_pos - 1));
1202 m_regex_cmd_ap->AddRegexCommand(regex.c_str(), subst.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001203 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001204 return error;
1205 }
1206
1207 void AddRegexCommandToInterpreter() {
1208 if (m_regex_cmd_ap) {
1209 if (m_regex_cmd_ap->HasRegexEntries()) {
1210 CommandObjectSP cmd_sp(m_regex_cmd_ap.release());
1211 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1212 }
1213 }
1214 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001215
Greg Claytonde164aa2011-04-20 16:37:46 +00001216private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001217 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001218
Kate Stoneb9c1b512016-09-06 20:57:50 +00001219 class CommandOptions : public Options {
1220 public:
1221 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001222
Kate Stoneb9c1b512016-09-06 20:57:50 +00001223 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001224
Kate Stoneb9c1b512016-09-06 20:57:50 +00001225 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1226 ExecutionContext *execution_context) override {
1227 Error error;
1228 const int short_option = m_getopt_table[option_idx].val;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001229
Kate Stoneb9c1b512016-09-06 20:57:50 +00001230 switch (short_option) {
1231 case 'h':
1232 m_help.assign(option_arg);
1233 break;
1234 case 's':
1235 m_syntax.assign(option_arg);
1236 break;
1237 default:
1238 error.SetErrorStringWithFormat("unrecognized option '%c'",
1239 short_option);
1240 break;
1241 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001242
Kate Stoneb9c1b512016-09-06 20:57:50 +00001243 return error;
1244 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001245
Kate Stoneb9c1b512016-09-06 20:57:50 +00001246 void OptionParsingStarting(ExecutionContext *execution_context) override {
1247 m_help.clear();
1248 m_syntax.clear();
1249 }
1250
1251 const OptionDefinition *GetDefinitions() override { return g_option_table; }
1252
1253 // Options table: Required for subclasses of Options.
1254
1255 static OptionDefinition g_option_table[];
1256
1257 const char *GetHelp() {
1258 return (m_help.empty() ? nullptr : m_help.c_str());
1259 }
1260
1261 const char *GetSyntax() {
1262 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1263 }
1264
1265 protected:
1266 // Instance variables to hold the values for command options.
1267
1268 std::string m_help;
1269 std::string m_syntax;
1270 };
1271
1272 Options *GetOptions() override { return &m_options; }
1273
1274 CommandOptions m_options;
Greg Claytonde164aa2011-04-20 16:37:46 +00001275};
1276
Greg Claytonde164aa2011-04-20 16:37:46 +00001277OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001278 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] = {
1279 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001280 {LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."},
1281 {LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1282 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001283 // clang-format on
Greg Claytonde164aa2011-04-20 16:37:46 +00001284};
1285
Kate Stoneb9c1b512016-09-06 20:57:50 +00001286class CommandObjectPythonFunction : public CommandObjectRaw {
Enrico Granata223383e2011-08-16 23:24:13 +00001287public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001288 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name,
1289 std::string funct, std::string help,
1290 ScriptedCommandSynchronicity synch)
1291 : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1292 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) {
1293 if (!help.empty())
1294 SetHelp(help.c_str());
1295 else {
1296 StreamString stream;
1297 stream.Printf("For more information run 'help %s'", name.c_str());
1298 SetHelp(stream.GetData());
Enrico Granata223383e2011-08-16 23:24:13 +00001299 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001300 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001301
Kate Stoneb9c1b512016-09-06 20:57:50 +00001302 ~CommandObjectPythonFunction() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001303
Kate Stoneb9c1b512016-09-06 20:57:50 +00001304 bool IsRemovable() const override { return true; }
Jim Ingham5a988412012-06-08 21:56:10 +00001305
Kate Stoneb9c1b512016-09-06 20:57:50 +00001306 const std::string &GetFunctionName() { return m_function_name; }
Jim Ingham5a988412012-06-08 21:56:10 +00001307
Kate Stoneb9c1b512016-09-06 20:57:50 +00001308 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1309
1310 const char *GetHelpLong() override {
1311 if (!m_fetched_help_long) {
1312 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1313 if (scripter) {
1314 std::string docstring;
1315 m_fetched_help_long = scripter->GetDocumentationForItem(
1316 m_function_name.c_str(), docstring);
1317 if (!docstring.empty())
1318 SetHelpLong(docstring.c_str());
1319 }
Jim Ingham5a988412012-06-08 21:56:10 +00001320 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001321 return CommandObjectRaw::GetHelpLong();
1322 }
1323
Jim Ingham5a988412012-06-08 21:56:10 +00001324protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001325 bool DoExecute(const char *raw_command_line,
1326 CommandReturnObject &result) override {
1327 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1328
1329 Error error;
1330
1331 result.SetStatus(eReturnStatusInvalid);
1332
1333 if (!scripter ||
1334 !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1335 raw_command_line, m_synchro, result,
1336 error, m_exe_ctx)) {
1337 result.AppendError(error.AsCString());
1338 result.SetStatus(eReturnStatusFailed);
1339 } else {
1340 // Don't change the status if the command already set it...
1341 if (result.GetStatus() == eReturnStatusInvalid) {
1342 if (result.GetOutputData() == nullptr ||
1343 result.GetOutputData()[0] == '\0')
1344 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata223383e2011-08-16 23:24:13 +00001345 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001346 result.SetStatus(eReturnStatusSuccessFinishResult);
1347 }
Enrico Granata223383e2011-08-16 23:24:13 +00001348 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001349
Kate Stoneb9c1b512016-09-06 20:57:50 +00001350 return result.Succeeded();
1351 }
1352
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001353private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001354 std::string m_function_name;
1355 ScriptedCommandSynchronicity m_synchro;
1356 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001357};
1358
Kate Stoneb9c1b512016-09-06 20:57:50 +00001359class CommandObjectScriptingObject : public CommandObjectRaw {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001360public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001361 CommandObjectScriptingObject(CommandInterpreter &interpreter,
1362 std::string name,
1363 StructuredData::GenericSP cmd_obj_sp,
1364 ScriptedCommandSynchronicity synch)
1365 : CommandObjectRaw(interpreter, name.c_str(), nullptr, nullptr),
1366 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false),
1367 m_fetched_help_long(false) {
1368 StreamString stream;
1369 stream.Printf("For more information run 'help %s'", name.c_str());
1370 SetHelp(stream.GetData());
1371 if (ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter())
1372 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1373 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001374
Kate Stoneb9c1b512016-09-06 20:57:50 +00001375 ~CommandObjectScriptingObject() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001376
Kate Stoneb9c1b512016-09-06 20:57:50 +00001377 bool IsRemovable() const override { return true; }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001378
Kate Stoneb9c1b512016-09-06 20:57:50 +00001379 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; }
1380
1381 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; }
1382
1383 const char *GetHelp() override {
1384 if (!m_fetched_help_short) {
1385 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1386 if (scripter) {
1387 std::string docstring;
1388 m_fetched_help_short =
1389 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring);
1390 if (!docstring.empty())
1391 SetHelp(docstring.c_str());
1392 }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001393 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001394 return CommandObjectRaw::GetHelp();
1395 }
1396
1397 const char *GetHelpLong() override {
1398 if (!m_fetched_help_long) {
1399 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1400 if (scripter) {
1401 std::string docstring;
1402 m_fetched_help_long =
1403 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring);
1404 if (!docstring.empty())
1405 SetHelpLong(docstring.c_str());
1406 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001407 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001408 return CommandObjectRaw::GetHelpLong();
1409 }
1410
Enrico Granata9fe00e52015-03-13 02:20:41 +00001411protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001412 bool DoExecute(const char *raw_command_line,
1413 CommandReturnObject &result) override {
1414 ScriptInterpreter *scripter = m_interpreter.GetScriptInterpreter();
1415
1416 Error error;
1417
1418 result.SetStatus(eReturnStatusInvalid);
1419
1420 if (!scripter ||
1421 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line,
1422 m_synchro, result, error, m_exe_ctx)) {
1423 result.AppendError(error.AsCString());
1424 result.SetStatus(eReturnStatusFailed);
1425 } else {
1426 // Don't change the status if the command already set it...
1427 if (result.GetStatus() == eReturnStatusInvalid) {
1428 if (result.GetOutputData() == nullptr ||
1429 result.GetOutputData()[0] == '\0')
1430 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Enrico Granata9fe00e52015-03-13 02:20:41 +00001431 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001432 result.SetStatus(eReturnStatusSuccessFinishResult);
1433 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001434 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001435
Kate Stoneb9c1b512016-09-06 20:57:50 +00001436 return result.Succeeded();
1437 }
1438
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001439private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001440 StructuredData::GenericSP m_cmd_obj_sp;
1441 ScriptedCommandSynchronicity m_synchro;
1442 bool m_fetched_help_short : 1;
1443 bool m_fetched_help_long : 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001444};
1445
Enrico Granataa9dbf432011-10-17 21:45:27 +00001446//-------------------------------------------------------------------------
1447// CommandObjectCommandsScriptImport
1448//-------------------------------------------------------------------------
1449
Kate Stoneb9c1b512016-09-06 20:57:50 +00001450class CommandObjectCommandsScriptImport : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001451public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001452 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter)
1453 : CommandObjectParsed(interpreter, "command script import",
1454 "Import a scripting module in LLDB.", nullptr),
1455 m_options() {
1456 CommandArgumentEntry arg1;
1457 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001458
Kate Stoneb9c1b512016-09-06 20:57:50 +00001459 // Define the first (and only) variant of this arg.
1460 cmd_arg.arg_type = eArgTypeFilename;
1461 cmd_arg.arg_repetition = eArgRepeatPlus;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001462
Kate Stoneb9c1b512016-09-06 20:57:50 +00001463 // There is only one variant this argument could be; put it into the
1464 // argument entry.
1465 arg1.push_back(cmd_arg);
Todd Fialae1cfbc72016-08-11 23:51:28 +00001466
Kate Stoneb9c1b512016-09-06 20:57:50 +00001467 // Push the data for the first argument into the m_arguments vector.
1468 m_arguments.push_back(arg1);
1469 }
1470
1471 ~CommandObjectCommandsScriptImport() override = default;
1472
1473 int HandleArgumentCompletion(Args &input, int &cursor_index,
1474 int &cursor_char_position,
1475 OptionElementVector &opt_element_vector,
1476 int match_start_point, int max_return_elements,
1477 bool &word_complete,
1478 StringList &matches) override {
1479 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
1480 completion_str.erase(cursor_char_position);
1481
1482 CommandCompletions::InvokeCommonCompletionCallbacks(
1483 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1484 completion_str.c_str(), match_start_point, max_return_elements, nullptr,
1485 word_complete, matches);
1486 return matches.GetSize();
1487 }
1488
1489 Options *GetOptions() override { return &m_options; }
Jim Ingham5a988412012-06-08 21:56:10 +00001490
1491protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001492 class CommandOptions : public Options {
1493 public:
1494 CommandOptions() : Options() {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001495
Kate Stoneb9c1b512016-09-06 20:57:50 +00001496 ~CommandOptions() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001497
Kate Stoneb9c1b512016-09-06 20:57:50 +00001498 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1499 ExecutionContext *execution_context) override {
1500 Error error;
1501 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001502
Kate Stoneb9c1b512016-09-06 20:57:50 +00001503 switch (short_option) {
1504 case 'r':
1505 m_allow_reload = true;
1506 break;
1507 default:
1508 error.SetErrorStringWithFormat("unrecognized option '%c'",
1509 short_option);
1510 break;
1511 }
1512
1513 return error;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001514 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001515
1516 void OptionParsingStarting(ExecutionContext *execution_context) override {
1517 m_allow_reload = true;
1518 }
1519
1520 const OptionDefinition *GetDefinitions() override { return g_option_table; }
1521
1522 // Options table: Required for subclasses of Options.
1523
1524 static OptionDefinition g_option_table[];
1525
1526 // Instance variables to hold the values for command options.
1527
1528 bool m_allow_reload;
1529 };
1530
1531 bool DoExecute(Args &command, CommandReturnObject &result) override {
1532 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1533 lldb::eScriptLanguagePython) {
1534 result.AppendError("only scripting language supported for module "
1535 "importing is currently Python");
1536 result.SetStatus(eReturnStatusFailed);
1537 return false;
1538 }
1539
1540 size_t argc = command.GetArgumentCount();
1541 if (0 == argc) {
1542 result.AppendError("command script import needs one or more arguments");
1543 result.SetStatus(eReturnStatusFailed);
1544 return false;
1545 }
1546
1547 for (size_t i = 0; i < argc; i++) {
1548 std::string path = command.GetArgumentAtIndex(i);
1549 Error error;
1550
1551 const bool init_session = true;
1552 // FIXME: this is necessary because CommandObject::CheckRequirements()
1553 // assumes that
1554 // commands won't ever be recursively invoked, but it's actually possible
1555 // to craft
1556 // a Python script that does other "command script imports" in
1557 // __lldb_init_module
1558 // the real fix is to have recursive commands possible with a
1559 // CommandInvocation object
1560 // separate from the CommandObject itself, so that recursive command
1561 // invocations
1562 // won't stomp on each other (wrt to execution contents, options, and
1563 // more)
1564 m_exe_ctx.Clear();
1565 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(
1566 path.c_str(), m_options.m_allow_reload, init_session, error)) {
1567 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1568 } else {
1569 result.AppendErrorWithFormat("module importing failed: %s",
1570 error.AsCString());
1571 result.SetStatus(eReturnStatusFailed);
1572 }
1573 }
1574
1575 return result.Succeeded();
1576 }
1577
1578 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001579};
Enrico Granata223383e2011-08-16 23:24:13 +00001580
Enrico Granata0a305db2011-11-07 22:57:04 +00001581OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001582 CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] = {
1583 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001584 {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."},
1585 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001586 // clang-format on
Enrico Granata0a305db2011-11-07 22:57:04 +00001587};
1588
Enrico Granata223383e2011-08-16 23:24:13 +00001589//-------------------------------------------------------------------------
1590// CommandObjectCommandsScriptAdd
1591//-------------------------------------------------------------------------
1592
Kate Stoneb9c1b512016-09-06 20:57:50 +00001593class CommandObjectCommandsScriptAdd : public CommandObjectParsed,
1594 public IOHandlerDelegateMultiline {
Jim Ingham5a988412012-06-08 21:56:10 +00001595public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001596 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter)
1597 : CommandObjectParsed(interpreter, "command script add",
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001598 "Add a scripted function as an LLDB command.",
1599 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001600 IOHandlerDelegateMultiline("DONE"), m_options() {
1601 CommandArgumentEntry arg1;
1602 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001603
Kate Stoneb9c1b512016-09-06 20:57:50 +00001604 // Define the first (and only) variant of this arg.
1605 cmd_arg.arg_type = eArgTypeCommandName;
1606 cmd_arg.arg_repetition = eArgRepeatPlain;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001607
Kate Stoneb9c1b512016-09-06 20:57:50 +00001608 // There is only one variant this argument could be; put it into the
1609 // argument entry.
1610 arg1.push_back(cmd_arg);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001611
Kate Stoneb9c1b512016-09-06 20:57:50 +00001612 // Push the data for the first argument into the m_arguments vector.
1613 m_arguments.push_back(arg1);
1614 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001615
Kate Stoneb9c1b512016-09-06 20:57:50 +00001616 ~CommandObjectCommandsScriptAdd() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001617
Kate Stoneb9c1b512016-09-06 20:57:50 +00001618 Options *GetOptions() override { return &m_options; }
Greg Clayton44d93782014-01-27 23:43:24 +00001619
Jim Ingham5a988412012-06-08 21:56:10 +00001620protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001621 class CommandOptions : public Options {
1622 public:
1623 CommandOptions()
1624 : Options(), m_class_name(), m_funct_name(), m_short_help(),
1625 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {}
Enrico Granata223383e2011-08-16 23:24:13 +00001626
Kate Stoneb9c1b512016-09-06 20:57:50 +00001627 ~CommandOptions() override = default;
1628
1629 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1630 ExecutionContext *execution_context) override {
1631 Error error;
1632 const int short_option = m_getopt_table[option_idx].val;
1633
1634 switch (short_option) {
1635 case 'f':
1636 if (option_arg)
1637 m_funct_name.assign(option_arg);
1638 break;
1639 case 'c':
1640 if (option_arg)
1641 m_class_name.assign(option_arg);
1642 break;
1643 case 'h':
1644 if (option_arg)
1645 m_short_help.assign(option_arg);
1646 break;
1647 case 's':
1648 m_synchronicity =
1649 (ScriptedCommandSynchronicity)Args::StringToOptionEnum(
1650 option_arg, g_option_table[option_idx].enum_values, 0, error);
1651 if (!error.Success())
1652 error.SetErrorStringWithFormat(
1653 "unrecognized value for synchronicity '%s'", option_arg);
1654 break;
1655 default:
1656 error.SetErrorStringWithFormat("unrecognized option '%c'",
1657 short_option);
1658 break;
1659 }
1660
1661 return error;
Enrico Granata223383e2011-08-16 23:24:13 +00001662 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001663
1664 void OptionParsingStarting(ExecutionContext *execution_context) override {
1665 m_class_name.clear();
1666 m_funct_name.clear();
1667 m_short_help.clear();
1668 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1669 }
1670
1671 const OptionDefinition *GetDefinitions() override { return g_option_table; }
1672
1673 // Options table: Required for subclasses of Options.
1674
1675 static OptionDefinition g_option_table[];
1676
1677 // Instance variables to hold the values for command options.
1678
1679 std::string m_class_name;
1680 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001681 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001682 ScriptedCommandSynchronicity m_synchronicity;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001683 };
1684
1685 void IOHandlerActivated(IOHandler &io_handler) override {
1686 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1687 if (output_sp) {
1688 output_sp->PutCString(g_python_command_instructions);
1689 output_sp->Flush();
1690 }
1691 }
1692
1693 void IOHandlerInputComplete(IOHandler &io_handler,
1694 std::string &data) override {
1695 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1696
1697 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1698 if (interpreter) {
1699
1700 StringList lines;
1701 lines.SplitIntoLines(data);
1702 if (lines.GetSize() > 0) {
1703 std::string funct_name_str;
1704 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) {
1705 if (funct_name_str.empty()) {
1706 error_sp->Printf("error: unable to obtain a function name, didn't "
1707 "add python command.\n");
1708 error_sp->Flush();
1709 } else {
1710 // everything should be fine now, let's add this alias
1711
1712 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(
1713 m_interpreter, m_cmd_name, funct_name_str.c_str(), m_short_help,
1714 m_synchronicity));
1715
1716 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp,
1717 true)) {
1718 error_sp->Printf("error: unable to add selected command, didn't "
1719 "add python command.\n");
1720 error_sp->Flush();
1721 }
1722 }
1723 } else {
1724 error_sp->Printf(
1725 "error: unable to create function, didn't add python command.\n");
1726 error_sp->Flush();
1727 }
1728 } else {
1729 error_sp->Printf("error: empty function, didn't add python command.\n");
1730 error_sp->Flush();
1731 }
1732 } else {
1733 error_sp->Printf(
1734 "error: script interpreter missing, didn't add python command.\n");
1735 error_sp->Flush();
1736 }
1737
1738 io_handler.SetIsDone(true);
1739 }
1740
1741protected:
1742 bool DoExecute(Args &command, CommandReturnObject &result) override {
1743 if (m_interpreter.GetDebugger().GetScriptLanguage() !=
1744 lldb::eScriptLanguagePython) {
1745 result.AppendError("only scripting language supported for scripted "
1746 "commands is currently Python");
1747 result.SetStatus(eReturnStatusFailed);
1748 return false;
1749 }
1750
1751 size_t argc = command.GetArgumentCount();
1752
1753 if (argc != 1) {
1754 result.AppendError("'command script add' requires one argument");
1755 result.SetStatus(eReturnStatusFailed);
1756 return false;
1757 }
1758
1759 // Store the options in case we get multi-line input
1760 m_cmd_name = command.GetArgumentAtIndex(0);
1761 m_short_help.assign(m_options.m_short_help);
1762 m_synchronicity = m_options.m_synchronicity;
1763
1764 if (m_options.m_class_name.empty()) {
1765 if (m_options.m_funct_name.empty()) {
1766 m_interpreter.GetPythonCommandsFromIOHandler(
1767 " ", // Prompt
1768 *this, // IOHandlerDelegate
1769 true, // Run IOHandler in async mode
1770 nullptr); // Baton for the "io_handler" that will be passed back
1771 // into our IOHandlerDelegate functions
1772 } else {
1773 CommandObjectSP new_cmd(new CommandObjectPythonFunction(
1774 m_interpreter, m_cmd_name, m_options.m_funct_name,
1775 m_options.m_short_help, m_synchronicity));
1776 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1777 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1778 } else {
1779 result.AppendError("cannot add command");
1780 result.SetStatus(eReturnStatusFailed);
1781 }
1782 }
1783 } else {
1784 ScriptInterpreter *interpreter =
1785 GetCommandInterpreter().GetScriptInterpreter();
1786 if (!interpreter) {
1787 result.AppendError("cannot find ScriptInterpreter");
1788 result.SetStatus(eReturnStatusFailed);
1789 return false;
1790 }
1791
1792 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(
1793 m_options.m_class_name.c_str());
1794 if (!cmd_obj_sp) {
1795 result.AppendError("cannot create helper object");
1796 result.SetStatus(eReturnStatusFailed);
1797 return false;
1798 }
1799
1800 CommandObjectSP new_cmd(new CommandObjectScriptingObject(
1801 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity));
1802 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) {
1803 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1804 } else {
1805 result.AppendError("cannot add command");
1806 result.SetStatus(eReturnStatusFailed);
1807 }
1808 }
1809
1810 return result.Succeeded();
1811 }
1812
1813 CommandOptions m_options;
1814 std::string m_cmd_name;
1815 std::string m_short_help;
1816 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001817};
1818
Kate Stoneb9c1b512016-09-06 20:57:50 +00001819static OptionEnumValueElement g_script_synchro_type[] = {
1820 {eScriptedCommandSynchronicitySynchronous, "synchronous",
1821 "Run synchronous"},
1822 {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
1823 "Run asynchronous"},
1824 {eScriptedCommandSynchronicityCurrentValue, "current",
1825 "Do not alter current setting"},
1826 {0, nullptr, nullptr}};
Enrico Granata0a305db2011-11-07 22:57:04 +00001827
Enrico Granata223383e2011-08-16 23:24:13 +00001828OptionDefinition
Kate Stoneb9c1b512016-09-06 20:57:50 +00001829 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] = {
1830 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001831 {LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
1832 {LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."},
1833 {LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."},
1834 {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."},
1835 {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
Kate Stoneb9c1b512016-09-06 20:57:50 +00001836 // clang-format on
Enrico Granata223383e2011-08-16 23:24:13 +00001837};
1838
1839//-------------------------------------------------------------------------
1840// CommandObjectCommandsScriptList
1841//-------------------------------------------------------------------------
1842
Kate Stoneb9c1b512016-09-06 20:57:50 +00001843class CommandObjectCommandsScriptList : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001844public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001845 CommandObjectCommandsScriptList(CommandInterpreter &interpreter)
1846 : CommandObjectParsed(interpreter, "command script list",
1847 "List defined scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001848
Kate Stoneb9c1b512016-09-06 20:57:50 +00001849 ~CommandObjectCommandsScriptList() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001850
Kate Stoneb9c1b512016-09-06 20:57:50 +00001851 bool DoExecute(Args &command, CommandReturnObject &result) override {
1852 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef);
1853
1854 result.SetStatus(eReturnStatusSuccessFinishResult);
1855
1856 return true;
1857 }
Enrico Granata223383e2011-08-16 23:24:13 +00001858};
1859
1860//-------------------------------------------------------------------------
1861// CommandObjectCommandsScriptClear
1862//-------------------------------------------------------------------------
1863
Kate Stoneb9c1b512016-09-06 20:57:50 +00001864class CommandObjectCommandsScriptClear : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001865public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001866 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter)
1867 : CommandObjectParsed(interpreter, "command script clear",
1868 "Delete all scripted commands.", nullptr) {}
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001869
Kate Stoneb9c1b512016-09-06 20:57:50 +00001870 ~CommandObjectCommandsScriptClear() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001871
Jim Ingham5a988412012-06-08 21:56:10 +00001872protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001873 bool DoExecute(Args &command, CommandReturnObject &result) override {
1874 m_interpreter.RemoveAllUser();
1875
1876 result.SetStatus(eReturnStatusSuccessFinishResult);
1877
1878 return true;
1879 }
Enrico Granata223383e2011-08-16 23:24:13 +00001880};
1881
1882//-------------------------------------------------------------------------
1883// CommandObjectCommandsScriptDelete
1884//-------------------------------------------------------------------------
1885
Kate Stoneb9c1b512016-09-06 20:57:50 +00001886class CommandObjectCommandsScriptDelete : public CommandObjectParsed {
Enrico Granata223383e2011-08-16 23:24:13 +00001887public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001888 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter)
1889 : CommandObjectParsed(interpreter, "command script delete",
1890 "Delete a scripted command.", nullptr) {
1891 CommandArgumentEntry arg1;
1892 CommandArgumentData cmd_arg;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001893
Kate Stoneb9c1b512016-09-06 20:57:50 +00001894 // Define the first (and only) variant of this arg.
1895 cmd_arg.arg_type = eArgTypeCommandName;
1896 cmd_arg.arg_repetition = eArgRepeatPlain;
1897
1898 // There is only one variant this argument could be; put it into the
1899 // argument entry.
1900 arg1.push_back(cmd_arg);
1901
1902 // Push the data for the first argument into the m_arguments vector.
1903 m_arguments.push_back(arg1);
1904 }
1905
1906 ~CommandObjectCommandsScriptDelete() override = default;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001907
Jim Ingham5a988412012-06-08 21:56:10 +00001908protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001909 bool DoExecute(Args &command, CommandReturnObject &result) override {
1910
1911 size_t argc = command.GetArgumentCount();
1912
1913 if (argc != 1) {
1914 result.AppendError("'command script delete' requires one argument");
1915 result.SetStatus(eReturnStatusFailed);
1916 return false;
Enrico Granata223383e2011-08-16 23:24:13 +00001917 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001918
1919 const char *cmd_name = command.GetArgumentAtIndex(0);
1920
1921 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() &&
1922 m_interpreter.UserCommandExists(cmd_name)) {
1923 m_interpreter.RemoveUser(cmd_name);
1924 result.SetStatus(eReturnStatusSuccessFinishResult);
1925 } else {
1926 result.AppendErrorWithFormat("command %s not found", cmd_name);
1927 result.SetStatus(eReturnStatusFailed);
1928 }
1929
1930 return result.Succeeded();
1931 }
Enrico Granata223383e2011-08-16 23:24:13 +00001932};
1933
1934#pragma mark CommandObjectMultiwordCommandsScript
1935
1936//-------------------------------------------------------------------------
1937// CommandObjectMultiwordCommandsScript
1938//-------------------------------------------------------------------------
1939
Kate Stoneb9c1b512016-09-06 20:57:50 +00001940class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword {
Enrico Granata223383e2011-08-16 23:24:13 +00001941public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001942 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
1943 : CommandObjectMultiword(
1944 interpreter, "command script", "Commands for managing custom "
1945 "commands implemented by "
1946 "interpreter scripts.",
1947 "command script <subcommand> [<subcommand-options>]") {
1948 LoadSubCommand("add", CommandObjectSP(
1949 new CommandObjectCommandsScriptAdd(interpreter)));
1950 LoadSubCommand(
1951 "delete",
1952 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter)));
1953 LoadSubCommand(
1954 "clear",
1955 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter)));
1956 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList(
1957 interpreter)));
1958 LoadSubCommand(
1959 "import",
1960 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter)));
1961 }
Enrico Granata223383e2011-08-16 23:24:13 +00001962
Kate Stoneb9c1b512016-09-06 20:57:50 +00001963 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00001964};
1965
Jim Inghamebc09c32010-07-07 03:36:20 +00001966#pragma mark CommandObjectMultiwordCommands
1967
1968//-------------------------------------------------------------------------
1969// CommandObjectMultiwordCommands
1970//-------------------------------------------------------------------------
1971
Kate Stoneb9c1b512016-09-06 20:57:50 +00001972CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(
1973 CommandInterpreter &interpreter)
1974 : CommandObjectMultiword(interpreter, "command",
1975 "Commands for managing custom LLDB commands.",
1976 "command <subcommand> [<subcommand-options>]") {
1977 LoadSubCommand("source",
1978 CommandObjectSP(new CommandObjectCommandsSource(interpreter)));
1979 LoadSubCommand("alias",
1980 CommandObjectSP(new CommandObjectCommandsAlias(interpreter)));
1981 LoadSubCommand("unalias", CommandObjectSP(
1982 new CommandObjectCommandsUnalias(interpreter)));
1983 LoadSubCommand("delete",
1984 CommandObjectSP(new CommandObjectCommandsDelete(interpreter)));
1985 LoadSubCommand(
1986 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter)));
1987 LoadSubCommand("history", CommandObjectSP(
1988 new CommandObjectCommandsHistory(interpreter)));
1989 LoadSubCommand(
1990 "script",
1991 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00001992}
1993
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001994CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;