blob: dd2fd9a0efc8940c2aea06f7f30de7b2aed44e91 [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
Jim Ingham5a988412012-06-08 21:56:10 +000039class CommandObjectCommandsHistory : public CommandObjectParsed
Jim Inghama5a97eb2011-07-12 03:12:18 +000040{
Jim Ingham5a988412012-06-08 21:56:10 +000041public:
42 CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000043 CommandObjectParsed(interpreter,
44 "command history",
45 "Dump the history of commands in this session.",
46 nullptr),
Jim Ingham5a988412012-06-08 21:56:10 +000047 m_options (interpreter)
48 {
49 }
50
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000051 ~CommandObjectCommandsHistory() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +000052
Bruce Mitchener13d21e92015-10-07 16:56:17 +000053 Options *
54 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +000055 {
56 return &m_options;
57 }
58
59protected:
Jim Inghama5a97eb2011-07-12 03:12:18 +000060 class CommandOptions : public Options
61 {
62 public:
Jim Inghama5a97eb2011-07-12 03:12:18 +000063 CommandOptions (CommandInterpreter &interpreter) :
Enrico Granata7594f142013-06-17 22:51:50 +000064 Options (interpreter),
65 m_start_idx(0),
66 m_stop_idx(0),
67 m_count(0),
Enrico Granata63123b62013-06-17 23:28:27 +000068 m_clear(false)
Jim Inghama5a97eb2011-07-12 03:12:18 +000069 {
70 }
71
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +000072 ~CommandOptions() override = default;
Jim Inghama5a97eb2011-07-12 03:12:18 +000073
Bruce Mitchener13d21e92015-10-07 16:56:17 +000074 Error
75 SetOptionValue (uint32_t option_idx, const char *option_arg) override
Jim Inghama5a97eb2011-07-12 03:12:18 +000076 {
77 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000078 const int short_option = m_getopt_table[option_idx].val;
Jim Inghama5a97eb2011-07-12 03:12:18 +000079
80 switch (short_option)
81 {
82 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +000083 error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign);
Jim Inghama5a97eb2011-07-12 03:12:18 +000084 break;
85 case 's':
Enrico Granata7594f142013-06-17 22:51:50 +000086 if (option_arg && strcmp("end", option_arg) == 0)
87 {
88 m_start_idx.SetCurrentValue(UINT64_MAX);
89 m_start_idx.SetOptionWasSet();
90 }
91 else
Pavel Labathc95f7e22015-02-20 11:14:59 +000092 error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
Enrico Granata7594f142013-06-17 22:51:50 +000093 break;
94 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +000095 error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
Enrico Granata7594f142013-06-17 22:51:50 +000096 break;
Enrico Granata63123b62013-06-17 23:28:27 +000097 case 'C':
98 m_clear.SetCurrentValue(true);
99 m_clear.SetOptionWasSet();
Jim Inghama5a97eb2011-07-12 03:12:18 +0000100 break;
101 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000102 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Jim Inghama5a97eb2011-07-12 03:12:18 +0000103 break;
104 }
105
106 return error;
107 }
108
109 void
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000110 OptionParsingStarting () override
Jim Inghama5a97eb2011-07-12 03:12:18 +0000111 {
Enrico Granata7594f142013-06-17 22:51:50 +0000112 m_start_idx.Clear();
113 m_stop_idx.Clear();
114 m_count.Clear();
Enrico Granata63123b62013-06-17 23:28:27 +0000115 m_clear.Clear();
Jim Inghama5a97eb2011-07-12 03:12:18 +0000116 }
117
118 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000119 GetDefinitions () override
Jim Inghama5a97eb2011-07-12 03:12:18 +0000120 {
121 return g_option_table;
122 }
123
124 // Options table: Required for subclasses of Options.
125
126 static OptionDefinition g_option_table[];
127
128 // Instance variables to hold the values for command options.
129
Enrico Granata7594f142013-06-17 22:51:50 +0000130 OptionValueUInt64 m_start_idx;
131 OptionValueUInt64 m_stop_idx;
132 OptionValueUInt64 m_count;
Enrico Granata63123b62013-06-17 23:28:27 +0000133 OptionValueBoolean m_clear;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000134 };
135
Jim Inghama5a97eb2011-07-12 03:12:18 +0000136 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000137 DoExecute (Args& command, CommandReturnObject &result) override
Jim Inghama5a97eb2011-07-12 03:12:18 +0000138 {
Enrico Granata63123b62013-06-17 23:28:27 +0000139 if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet())
Enrico Granata7594f142013-06-17 22:51:50 +0000140 {
141 m_interpreter.GetCommandHistory().Clear();
142 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
143 }
144 else
145 {
146 if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet())
147 {
148 result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation");
149 result.SetStatus(lldb::eReturnStatusFailed);
150 }
151 else
152 {
Virgile Bello84400ec2013-08-27 16:22:29 +0000153 std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue());
154 std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue());
155 std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue());
Enrico Granata7594f142013-06-17 22:51:50 +0000156
157 const CommandHistory& history(m_interpreter.GetCommandHistory());
158
159 if (start_idx.first && start_idx.second == UINT64_MAX)
160 {
161 if (count.first)
162 {
163 start_idx.second = history.GetSize() - count.second;
164 stop_idx.second = history.GetSize() - 1;
165 }
166 else if (stop_idx.first)
167 {
168 start_idx.second = stop_idx.second;
169 stop_idx.second = history.GetSize() - 1;
170 }
171 else
172 {
173 start_idx.second = 0;
174 stop_idx.second = history.GetSize() - 1;
175 }
176 }
177 else
178 {
179 if (!start_idx.first && !stop_idx.first && !count.first)
180 {
181 start_idx.second = 0;
182 stop_idx.second = history.GetSize() - 1;
183 }
184 else if (start_idx.first)
185 {
186 if (count.first)
187 {
188 stop_idx.second = start_idx.second + count.second - 1;
189 }
190 else if (!stop_idx.first)
191 {
192 stop_idx.second = history.GetSize() - 1;
193 }
194 }
195 else if (stop_idx.first)
196 {
197 if (count.first)
198 {
199 if (stop_idx.second >= count.second)
200 start_idx.second = stop_idx.second - count.second + 1;
201 else
202 start_idx.second = 0;
203 }
204 }
205 else /* if (count.first) */
206 {
207 start_idx.second = 0;
208 stop_idx.second = count.second - 1;
209 }
210 }
211 history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second);
212 }
213 }
Jim Inghama5a97eb2011-07-12 03:12:18 +0000214 return result.Succeeded();
215
216 }
Jim Ingham5a988412012-06-08 21:56:10 +0000217
218 CommandOptions m_options;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000219};
220
221OptionDefinition
222CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
223{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000224{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
225{ 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)."},
226{ LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
227{ LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."},
228{ 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Jim Inghama5a97eb2011-07-12 03:12:18 +0000229};
230
Jim Inghama5a97eb2011-07-12 03:12:18 +0000231//-------------------------------------------------------------------------
232// CommandObjectCommandsSource
233//-------------------------------------------------------------------------
234
Jim Ingham5a988412012-06-08 21:56:10 +0000235class CommandObjectCommandsSource : public CommandObjectParsed
Jim Inghamebc09c32010-07-07 03:36:20 +0000236{
Jim Ingham5a988412012-06-08 21:56:10 +0000237public:
Kate Stone7428a182016-07-14 22:03:10 +0000238 CommandObjectCommandsSource(CommandInterpreter &interpreter)
239 : CommandObjectParsed(interpreter, "command source", "Read and execute LLDB commands from the file <filename>.",
240 nullptr),
241 m_options(interpreter)
Jim Ingham5a988412012-06-08 21:56:10 +0000242 {
243 CommandArgumentEntry arg;
244 CommandArgumentData file_arg;
245
246 // Define the first (and only) variant of this arg.
247 file_arg.arg_type = eArgTypeFilename;
248 file_arg.arg_repetition = eArgRepeatPlain;
249
250 // There is only one variant this argument could be; put it into the argument entry.
251 arg.push_back (file_arg);
252
253 // Push the data for the first argument into the m_arguments vector.
254 m_arguments.push_back (arg);
255 }
256
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000257 ~CommandObjectCommandsSource() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000258
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000259 const char*
260 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Jim Ingham5a988412012-06-08 21:56:10 +0000261 {
262 return "";
263 }
264
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000265 int
Jim Ingham5a988412012-06-08 21:56:10 +0000266 HandleArgumentCompletion (Args &input,
267 int &cursor_index,
268 int &cursor_char_position,
269 OptionElementVector &opt_element_vector,
270 int match_start_point,
271 int max_return_elements,
272 bool &word_complete,
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000273 StringList &matches) override
Jim Ingham5a988412012-06-08 21:56:10 +0000274 {
275 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
276 completion_str.erase (cursor_char_position);
277
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000278 CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
279 CommandCompletions::eDiskFileCompletion,
280 completion_str.c_str(),
281 match_start_point,
282 max_return_elements,
283 nullptr,
284 word_complete,
285 matches);
Jim Ingham5a988412012-06-08 21:56:10 +0000286 return matches.GetSize();
287 }
288
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000289 Options *
290 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +0000291 {
292 return &m_options;
293 }
294
295protected:
Jim Inghame16c50a2011-02-18 00:54:25 +0000296 class CommandOptions : public Options
297 {
298 public:
Greg Claytoneb0103f2011-04-07 22:46:35 +0000299 CommandOptions (CommandInterpreter &interpreter) :
Enrico Granata012d4fc2013-06-11 01:26:35 +0000300 Options (interpreter),
Greg Clayton340b0302014-02-05 17:57:57 +0000301 m_stop_on_error (true),
302 m_silent_run (false),
303 m_stop_on_continue (true)
Greg Claytoneb0103f2011-04-07 22:46:35 +0000304 {
305 }
Jim Inghame16c50a2011-02-18 00:54:25 +0000306
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000307 ~CommandOptions() override = default;
Jim Inghame16c50a2011-02-18 00:54:25 +0000308
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000309 Error
310 SetOptionValue (uint32_t option_idx, const char *option_arg) override
Jim Inghame16c50a2011-02-18 00:54:25 +0000311 {
312 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000313 const int short_option = m_getopt_table[option_idx].val;
Jim Inghame16c50a2011-02-18 00:54:25 +0000314
315 switch (short_option)
316 {
317 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000318 error = m_stop_on_error.SetValueFromString(option_arg);
Jim Inghame16c50a2011-02-18 00:54:25 +0000319 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000320
Jim Inghame16c50a2011-02-18 00:54:25 +0000321 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000322 error = m_stop_on_continue.SetValueFromString(option_arg);
Jim Inghame16c50a2011-02-18 00:54:25 +0000323 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000324
Michael Sartain60986172013-07-09 23:22:53 +0000325 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000326 error = m_silent_run.SetValueFromString(option_arg);
Michael Sartain60986172013-07-09 23:22:53 +0000327 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000328
Jim Inghame16c50a2011-02-18 00:54:25 +0000329 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000330 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Jim Inghame16c50a2011-02-18 00:54:25 +0000331 break;
332 }
333
334 return error;
335 }
336
337 void
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000338 OptionParsingStarting () override
Jim Inghame16c50a2011-02-18 00:54:25 +0000339 {
Enrico Granata012d4fc2013-06-11 01:26:35 +0000340 m_stop_on_error.Clear();
Greg Clayton340b0302014-02-05 17:57:57 +0000341 m_silent_run.Clear();
342 m_stop_on_continue.Clear();
Jim Inghame16c50a2011-02-18 00:54:25 +0000343 }
344
Greg Claytone0d378b2011-03-24 21:19:54 +0000345 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000346 GetDefinitions () override
Jim Inghame16c50a2011-02-18 00:54:25 +0000347 {
348 return g_option_table;
349 }
350
351 // Options table: Required for subclasses of Options.
352
Greg Claytone0d378b2011-03-24 21:19:54 +0000353 static OptionDefinition g_option_table[];
Jim Inghame16c50a2011-02-18 00:54:25 +0000354
355 // Instance variables to hold the values for command options.
356
Enrico Granata012d4fc2013-06-11 01:26:35 +0000357 OptionValueBoolean m_stop_on_error;
Jim Ingham7d8555c2014-11-18 19:12:13 +0000358 OptionValueBoolean m_silent_run;
Greg Clayton340b0302014-02-05 17:57:57 +0000359 OptionValueBoolean m_stop_on_continue;
Jim Inghame16c50a2011-02-18 00:54:25 +0000360 };
361
Jim Inghamebc09c32010-07-07 03:36:20 +0000362 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000363 DoExecute(Args& command, CommandReturnObject &result) override
Jim Inghamebc09c32010-07-07 03:36:20 +0000364 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000365 const size_t argc = command.GetArgumentCount();
Jim Inghamebc09c32010-07-07 03:36:20 +0000366 if (argc == 1)
367 {
Jim Ingham5a988412012-06-08 21:56:10 +0000368 const char *filename = command.GetArgumentAtIndex(0);
Jim Inghamebc09c32010-07-07 03:36:20 +0000369
Johnny Chen1ee38532010-10-20 21:40:50 +0000370 FileSpec cmd_file (filename, true);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000371 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
Greg Clayton340b0302014-02-05 17:57:57 +0000372
373 // If any options were set, then use them
374 if (m_options.m_stop_on_error.OptionWasSet() ||
375 m_options.m_silent_run.OptionWasSet() ||
376 m_options.m_stop_on_continue.OptionWasSet())
377 {
378 // Use user set settings
Jim Ingham26c7bf92014-10-11 00:38:27 +0000379 CommandInterpreterRunOptions options;
380 options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
381 options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue());
Jim Ingham7d8555c2014-11-18 19:12:13 +0000382 options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue());
383 options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue());
Jim Ingham26c7bf92014-10-11 00:38:27 +0000384
Greg Clayton340b0302014-02-05 17:57:57 +0000385 m_interpreter.HandleCommandsFromFile (cmd_file,
386 exe_ctx,
Jim Ingham26c7bf92014-10-11 00:38:27 +0000387 options,
Greg Clayton340b0302014-02-05 17:57:57 +0000388 result);
Greg Clayton340b0302014-02-05 17:57:57 +0000389 }
390 else
391 {
392 // No options were set, inherit any settings from nested "command source" commands,
393 // or set to sane default settings...
Jim Ingham26c7bf92014-10-11 00:38:27 +0000394 CommandInterpreterRunOptions options;
Greg Clayton340b0302014-02-05 17:57:57 +0000395 m_interpreter.HandleCommandsFromFile (cmd_file,
396 exe_ctx,
Jim Ingham26c7bf92014-10-11 00:38:27 +0000397 options,
Greg Clayton340b0302014-02-05 17:57:57 +0000398 result);
Greg Clayton340b0302014-02-05 17:57:57 +0000399 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000400 }
401 else
402 {
403 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
404 result.SetStatus (eReturnStatusFailed);
405 }
406 return result.Succeeded();
Jim Inghamebc09c32010-07-07 03:36:20 +0000407 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000408
Jim Ingham5a988412012-06-08 21:56:10 +0000409 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000410};
411
Greg Claytone0d378b2011-03-24 21:19:54 +0000412OptionDefinition
Jim Inghame16c50a2011-02-18 00:54:25 +0000413CommandObjectCommandsSource::CommandOptions::g_option_table[] =
414{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000415{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
416{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
417{ LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
418{ 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Jim Inghame16c50a2011-02-18 00:54:25 +0000419};
420
Jim Inghamebc09c32010-07-07 03:36:20 +0000421#pragma mark CommandObjectCommandsAlias
422//-------------------------------------------------------------------------
423// CommandObjectCommandsAlias
424//-------------------------------------------------------------------------
425
Enrico Granatabe93a352011-08-16 16:49:25 +0000426static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
427 "You must define a Python function with this signature:\n"
Greg Clayton44d93782014-01-27 23:43:24 +0000428 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000429
Jim Ingham5a988412012-06-08 21:56:10 +0000430class CommandObjectCommandsAlias : public CommandObjectRaw
Jim Inghamebc09c32010-07-07 03:36:20 +0000431{
Enrico Granata45d0e232016-03-31 01:10:54 +0000432protected:
433 class CommandOptions : public OptionGroup
434 {
435 public:
436 CommandOptions () :
437 OptionGroup(),
438 m_help(),
439 m_long_help()
440 {}
441
442 ~CommandOptions() override = default;
443
444 uint32_t
445 GetNumDefinitions () override
446 {
447 return 3;
448 }
449
450 const OptionDefinition*
451 GetDefinitions () override
452 {
453 return g_option_table;
454 }
455
456 Error
457 SetOptionValue (CommandInterpreter &interpreter,
458 uint32_t option_idx,
459 const char *option_value) override
460 {
461 Error error;
462
463 const int short_option = g_option_table[option_idx].short_option;
464
465 switch (short_option)
466 {
467 case 'h':
468 m_help.SetCurrentValue(option_value);
469 m_help.SetOptionWasSet();
470 break;
471
472 case 'H':
473 m_long_help.SetCurrentValue(option_value);
474 m_long_help.SetOptionWasSet();
475 break;
476
477 default:
478 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
479 break;
480 }
481
482 return error;
483 }
484
485 void
486 OptionParsingStarting (CommandInterpreter &interpreter) override
487 {
488 m_help.Clear();
489 m_long_help.Clear();
490 }
491
492 // Options table: Required for subclasses of Options.
493
494 static OptionDefinition g_option_table[];
495 OptionValueString m_help;
496 OptionValueString m_long_help;
497 };
498
499 OptionGroupOptions m_option_group;
500 CommandOptions m_command_options;
501
Jim Inghamebc09c32010-07-07 03:36:20 +0000502public:
Enrico Granata45d0e232016-03-31 01:10:54 +0000503 Options *
504 GetOptions () override
505 {
506 return &m_option_group;
507 }
508
Kate Stone7428a182016-07-14 22:03:10 +0000509 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
510 : CommandObjectRaw(interpreter, "command alias", "Define a custom command in terms of an existing command.",
511 nullptr),
512 m_option_group(interpreter),
513 m_command_options()
Jim Inghamebc09c32010-07-07 03:36:20 +0000514 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000515 m_option_group.Append(&m_command_options);
516 m_option_group.Finalize();
517
Jim Inghamebc09c32010-07-07 03:36:20 +0000518 SetHelpLong(
Kate Stoneea671fb2015-07-14 05:48:36 +0000519"'alias' allows the user to create a short-cut or abbreviation for long \
520commands, multi-word commands, and commands that take particular options. \
521Below are some simple examples of how one might use the 'alias' command:" R"(
522
523(lldb) command alias sc script
524
525 Creates the abbreviation 'sc' for the 'script' command.
526
527(lldb) command alias bp breakpoint
528
529)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
530breakpoint commands are two-word commands, the user would still need to \
531enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
532
533(lldb) command alias bpl breakpoint list
534
535 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
536
537)" "An alias can include some options for the command, with the values either \
538filled in at the time the alias is created, or specified as positional \
539arguments, to be filled in when the alias is invoked. The following example \
540shows how to create aliases with options:" R"(
541
542(lldb) command alias bfl breakpoint set -f %1 -l %2
543
544)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
545options already part of the alias. So if the user wants to set a breakpoint \
546by file and line without explicitly having to use the -f and -l options, the \
547user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
548for the actual arguments that will be passed when the alias command is used. \
549The number in the placeholder refers to the position/order the actual value \
550occupies when the alias is used. All the occurrences of '%1' in the alias \
551will be replaced with the first argument, all the occurrences of '%2' in the \
552alias will be replaced with the second argument, and so on. This also allows \
553actual arguments to be used multiple times within an alias (see 'process \
554launch' example below)." R"(
555
556)" "Note: the positional arguments must substitute as whole words in the resultant \
557command, so you can't at present do something like this to append the file extension \
558\".cpp\":" R"(
559
560(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
561
562)" "For more complex aliasing, use the \"command regex\" command instead. In the \
563'bfl' case above, the actual file value will be filled in with the first argument \
564following 'bfl' and the actual line number value will be filled in with the second \
565argument. The user would use this alias as follows:" R"(
566
567(lldb) command alias bfl breakpoint set -f %1 -l %2
568(lldb) bfl my-file.c 137
569
570This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
571
572Another example:
573
574(lldb) command alias pltty process launch -s -o %1 -e %1
575(lldb) pltty /dev/tty0
576
577 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
578
579)" "If the user always wanted to pass the same value to a particular option, the \
580alias could be defined with that value directly in the alias as a constant, \
581rather than using a positional placeholder:" R"(
582
583(lldb) command alias bl3 breakpoint set -f %1 -l 3
584
585 Always sets a breakpoint on line 3 of whatever file is indicated.)"
586 );
Jim Inghamebc09c32010-07-07 03:36:20 +0000587
Caroline Tice405fe672010-10-04 22:28:36 +0000588 CommandArgumentEntry arg1;
589 CommandArgumentEntry arg2;
590 CommandArgumentEntry arg3;
591 CommandArgumentData alias_arg;
592 CommandArgumentData cmd_arg;
593 CommandArgumentData options_arg;
594
595 // Define the first (and only) variant of this arg.
596 alias_arg.arg_type = eArgTypeAliasName;
597 alias_arg.arg_repetition = eArgRepeatPlain;
598
599 // There is only one variant this argument could be; put it into the argument entry.
600 arg1.push_back (alias_arg);
601
602 // Define the first (and only) variant of this arg.
603 cmd_arg.arg_type = eArgTypeCommandName;
604 cmd_arg.arg_repetition = eArgRepeatPlain;
605
606 // There is only one variant this argument could be; put it into the argument entry.
607 arg2.push_back (cmd_arg);
608
609 // Define the first (and only) variant of this arg.
610 options_arg.arg_type = eArgTypeAliasOptions;
611 options_arg.arg_repetition = eArgRepeatOptional;
612
613 // There is only one variant this argument could be; put it into the argument entry.
614 arg3.push_back (options_arg);
615
616 // Push the data for the first argument into the m_arguments vector.
617 m_arguments.push_back (arg1);
618 m_arguments.push_back (arg2);
619 m_arguments.push_back (arg3);
Jim Inghamebc09c32010-07-07 03:36:20 +0000620 }
621
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000622 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000623
Jim Ingham5a988412012-06-08 21:56:10 +0000624protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000625 bool
626 DoExecute (const char *raw_command_line, CommandReturnObject &result) override
Caroline Tice844d2302010-12-09 22:52:49 +0000627 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000628 if (!raw_command_line || !raw_command_line[0])
629 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000630 result.AppendError ("'command alias' requires at least two arguments");
Enrico Granata45d0e232016-03-31 01:10:54 +0000631 return false;
632 }
633
634 m_option_group.NotifyOptionParsingStarting();
635
636 const char * remainder = nullptr;
637
638 if (raw_command_line[0] == '-')
639 {
640 // We have some options and these options MUST end with --.
641 const char *end_options = nullptr;
642 const char *s = raw_command_line;
643 while (s && s[0])
644 {
645 end_options = ::strstr (s, "--");
646 if (end_options)
647 {
648 end_options += 2; // Get past the "--"
649 if (::isspace (end_options[0]))
650 {
651 remainder = end_options;
652 while (::isspace (*remainder))
653 ++remainder;
654 break;
655 }
656 }
657 s = end_options;
658 }
659
660 if (end_options)
661 {
662 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
663 if (!ParseOptions (args, result))
664 return false;
665
666 Error error (m_option_group.NotifyOptionParsingFinished());
667 if (error.Fail())
668 {
669 result.AppendError (error.AsCString());
670 result.SetStatus (eReturnStatusFailed);
671 return false;
672 }
673 }
674 }
675 if (nullptr == remainder)
676 remainder = raw_command_line;
677
678 std::string raw_command_string (remainder);
679 Args args (raw_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +0000680
681 size_t argc = args.GetArgumentCount();
682
683 if (argc < 2)
684 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000685 result.AppendError ("'command alias' requires at least two arguments");
Caroline Tice844d2302010-12-09 22:52:49 +0000686 result.SetStatus (eReturnStatusFailed);
687 return false;
688 }
689
690 // Get the alias command.
691
692 const std::string alias_command = args.GetArgumentAtIndex (0);
Enrico Granatad72e4122016-04-08 17:56:57 +0000693 if (alias_command.size() > 1 &&
694 alias_command[0] == '-')
695 {
696 result.AppendError("aliases starting with a dash are not supported");
697 if (alias_command == "--help" || alias_command == "--long-help")
698 {
699 result.AppendWarning("if trying to pass options to 'command alias' add a -- at the end of the options");
700 }
701 result.SetStatus (eReturnStatusFailed);
702 return false;
703 }
Enrico Granatabe93a352011-08-16 16:49:25 +0000704
Caroline Tice844d2302010-12-09 22:52:49 +0000705 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
706 // does the stripping itself.
707 size_t pos = raw_command_string.find (alias_command);
708 if (pos == 0)
709 {
710 raw_command_string = raw_command_string.substr (alias_command.size());
711 pos = raw_command_string.find_first_not_of (' ');
712 if ((pos != std::string::npos) && (pos > 0))
713 raw_command_string = raw_command_string.substr (pos);
714 }
715 else
716 {
717 result.AppendError ("Error parsing command string. No alias created.");
718 result.SetStatus (eReturnStatusFailed);
719 return false;
720 }
721
722
723 // Verify that the command is alias-able.
724 if (m_interpreter.CommandExists (alias_command.c_str()))
725 {
726 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
727 alias_command.c_str());
728 result.SetStatus (eReturnStatusFailed);
729 return false;
730 }
731
732 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
733 // raw_command_string is returned with the name of the command object stripped off the front.
Enrico Granatad72e4122016-04-08 17:56:57 +0000734 std::string original_raw_command_string(raw_command_string);
Caroline Tice844d2302010-12-09 22:52:49 +0000735 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
736
737 if (!cmd_obj)
738 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000739 result.AppendErrorWithFormat ("invalid command given to 'command alias'. '%s' does not begin with a valid command."
740 " No alias created.", original_raw_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +0000741 result.SetStatus (eReturnStatusFailed);
742 return false;
743 }
744 else if (!cmd_obj->WantsRawCommandString ())
745 {
746 // Note that args was initialized with the original command, and has not been updated to this point.
747 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
Jim Ingham5a988412012-06-08 21:56:10 +0000748 return HandleAliasingNormalCommand (args, result);
Caroline Tice844d2302010-12-09 22:52:49 +0000749 }
750 else
751 {
Jim Ingham5a988412012-06-08 21:56:10 +0000752 return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result);
753 }
754 return result.Succeeded();
755 }
756
757 bool
758 HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result)
759 {
Caroline Tice844d2302010-12-09 22:52:49 +0000760 // Verify & handle any options/arguments passed to the alias command
761
762 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
Enrico Granata5e550302016-03-08 03:00:27 +0000763
Enrico Granata212130a2016-03-08 05:37:15 +0000764 if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false))
765 {
766 if (m_interpreter.AliasExists (alias_command.c_str())
767 || m_interpreter.UserCommandExists (alias_command.c_str()))
768 {
769 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
770 alias_command.c_str());
771 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000772 if (CommandAlias *alias = m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp, raw_command_string.c_str()))
Enrico Granata212130a2016-03-08 05:37:15 +0000773 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000774 if (m_command_options.m_help.OptionWasSet())
775 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
776 if (m_command_options.m_long_help.OptionWasSet())
777 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
Enrico Granata212130a2016-03-08 05:37:15 +0000778 result.SetStatus (eReturnStatusSuccessFinishNoResult);
779 }
780 else
781 {
782 result.AppendError ("Unable to create requested alias.\n");
783 result.SetStatus (eReturnStatusFailed);
784 }
Caroline Ticeca90c472011-05-06 21:37:15 +0000785
Caroline Tice472362e2010-12-14 18:51:39 +0000786 }
787 else
788 {
789 result.AppendError ("Unable to create requested alias.\n");
790 result.SetStatus (eReturnStatusFailed);
791 }
Enrico Granata212130a2016-03-08 05:37:15 +0000792
Jim Ingham5a988412012-06-08 21:56:10 +0000793 return result.Succeeded ();
Caroline Tice844d2302010-12-09 22:52:49 +0000794 }
Jim Ingham5a988412012-06-08 21:56:10 +0000795
Jim Inghamebc09c32010-07-07 03:36:20 +0000796 bool
Jim Ingham5a988412012-06-08 21:56:10 +0000797 HandleAliasingNormalCommand (Args& args, CommandReturnObject &result)
Jim Inghamebc09c32010-07-07 03:36:20 +0000798 {
Caroline Tice867b185d2010-09-21 23:25:40 +0000799 size_t argc = args.GetArgumentCount();
Jim Inghamebc09c32010-07-07 03:36:20 +0000800
801 if (argc < 2)
Greg Claytonc982c762010-07-09 20:39:50 +0000802 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000803 result.AppendError ("'command alias' requires at least two arguments");
Jim Inghamebc09c32010-07-07 03:36:20 +0000804 result.SetStatus (eReturnStatusFailed);
805 return false;
Greg Claytonc982c762010-07-09 20:39:50 +0000806 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000807
808 const std::string alias_command = args.GetArgumentAtIndex(0);
809 const std::string actual_command = args.GetArgumentAtIndex(1);
810
811 args.Shift(); // Shift the alias command word off the argument vector.
812 args.Shift(); // Shift the old command word off the argument vector.
813
814 // Verify that the command is alias'able, and get the appropriate command object.
815
Greg Claytona7015092010-09-18 01:14:36 +0000816 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Inghamebc09c32010-07-07 03:36:20 +0000817 {
818 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
819 alias_command.c_str());
820 result.SetStatus (eReturnStatusFailed);
821 }
822 else
823 {
Greg Claytona7015092010-09-18 01:14:36 +0000824 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Inghamebc09c32010-07-07 03:36:20 +0000825 CommandObjectSP subcommand_obj_sp;
826 bool use_subcommand = false;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000827 if (command_obj_sp)
Jim Inghamebc09c32010-07-07 03:36:20 +0000828 {
829 CommandObject *cmd_obj = command_obj_sp.get();
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000830 CommandObject *sub_cmd_obj = nullptr;
Jim Inghamebc09c32010-07-07 03:36:20 +0000831 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
Jim Inghamebc09c32010-07-07 03:36:20 +0000832
Caroline Tice844d2302010-12-09 22:52:49 +0000833 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Inghamebc09c32010-07-07 03:36:20 +0000834 {
835 if (argc >= 3)
836 {
837 const std::string sub_command = args.GetArgumentAtIndex(0);
838 assert (sub_command.length() != 0);
Greg Clayton998255b2012-10-13 02:07:45 +0000839 subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str());
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000840 if (subcommand_obj_sp)
Jim Inghamebc09c32010-07-07 03:36:20 +0000841 {
842 sub_cmd_obj = subcommand_obj_sp.get();
843 use_subcommand = true;
844 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Tice844d2302010-12-09 22:52:49 +0000845 cmd_obj = sub_cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000846 }
847 else
848 {
Caroline Ticef415eeb2010-11-02 19:00:04 +0000849 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
850 "Unable to create alias.\n",
851 sub_command.c_str(), actual_command.c_str());
Jim Inghamebc09c32010-07-07 03:36:20 +0000852 result.SetStatus (eReturnStatusFailed);
853 return false;
854 }
855 }
856 }
857
858 // Verify & handle any options/arguments passed to the alias command
859
Enrico Granata212130a2016-03-08 05:37:15 +0000860 std::string args_string;
861
Jim Inghamebc09c32010-07-07 03:36:20 +0000862 if (args.GetArgumentCount () > 0)
863 {
Caroline Ticeca90c472011-05-06 21:37:15 +0000864 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
865 if (use_subcommand)
866 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
867
Caroline Ticeca90c472011-05-06 21:37:15 +0000868 args.GetCommandString (args_string);
Jim Inghamebc09c32010-07-07 03:36:20 +0000869 }
Enrico Granata212130a2016-03-08 05:37:15 +0000870
Greg Claytona7015092010-09-18 01:14:36 +0000871 if (m_interpreter.AliasExists (alias_command.c_str())
872 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Inghamebc09c32010-07-07 03:36:20 +0000873 {
Enrico Granata212130a2016-03-08 05:37:15 +0000874 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
Jim Inghamebc09c32010-07-07 03:36:20 +0000875 alias_command.c_str());
876 }
Enrico Granata212130a2016-03-08 05:37:15 +0000877
Enrico Granata45d0e232016-03-31 01:10:54 +0000878 if (CommandAlias *alias = m_interpreter.AddAlias(alias_command.c_str(),
879 use_subcommand ? subcommand_obj_sp : command_obj_sp,
880 args_string.c_str()))
Enrico Granata212130a2016-03-08 05:37:15 +0000881 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000882 if (m_command_options.m_help.OptionWasSet())
883 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
884 if (m_command_options.m_long_help.OptionWasSet())
885 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
Enrico Granata212130a2016-03-08 05:37:15 +0000886 result.SetStatus (eReturnStatusSuccessFinishNoResult);
887 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000888 else
Enrico Granata212130a2016-03-08 05:37:15 +0000889 {
890 result.AppendError ("Unable to create requested alias.\n");
891 result.SetStatus (eReturnStatusFailed);
892 return false;
893 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000894 }
895 else
896 {
897 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
898 result.SetStatus (eReturnStatusFailed);
Caroline Ticee7941792010-10-28 23:17:48 +0000899 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000900 }
901 }
902
903 return result.Succeeded();
904 }
905};
906
Enrico Granata45d0e232016-03-31 01:10:54 +0000907OptionDefinition
908CommandObjectCommandsAlias::CommandOptions::g_option_table[] =
909{
910 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"},
911 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"},
912 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
913};
914
Jim Inghamebc09c32010-07-07 03:36:20 +0000915#pragma mark CommandObjectCommandsUnalias
916//-------------------------------------------------------------------------
917// CommandObjectCommandsUnalias
918//-------------------------------------------------------------------------
919
Jim Ingham5a988412012-06-08 21:56:10 +0000920class CommandObjectCommandsUnalias : public CommandObjectParsed
Jim Inghamebc09c32010-07-07 03:36:20 +0000921{
922public:
Kate Stone7428a182016-07-14 22:03:10 +0000923 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
924 : CommandObjectParsed(interpreter, "command unalias",
925 "Delete one or more custom commands defined by 'command alias'.", nullptr)
Jim Inghamebc09c32010-07-07 03:36:20 +0000926 {
Caroline Tice405fe672010-10-04 22:28:36 +0000927 CommandArgumentEntry arg;
928 CommandArgumentData alias_arg;
929
930 // Define the first (and only) variant of this arg.
931 alias_arg.arg_type = eArgTypeAliasName;
932 alias_arg.arg_repetition = eArgRepeatPlain;
933
934 // There is only one variant this argument could be; put it into the argument entry.
935 arg.push_back (alias_arg);
936
937 // Push the data for the first argument into the m_arguments vector.
938 m_arguments.push_back (arg);
Jim Inghamebc09c32010-07-07 03:36:20 +0000939 }
940
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000941 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000942
Jim Ingham5a988412012-06-08 21:56:10 +0000943protected:
Jim Inghamebc09c32010-07-07 03:36:20 +0000944 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000945 DoExecute (Args& args, CommandReturnObject &result) override
Jim Inghamebc09c32010-07-07 03:36:20 +0000946 {
947 CommandObject::CommandMap::iterator pos;
948 CommandObject *cmd_obj;
949
950 if (args.GetArgumentCount() != 0)
951 {
952 const char *command_name = args.GetArgumentAtIndex(0);
Greg Claytona7015092010-09-18 01:14:36 +0000953 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Inghamebc09c32010-07-07 03:36:20 +0000954 if (cmd_obj)
955 {
Greg Claytona7015092010-09-18 01:14:36 +0000956 if (m_interpreter.CommandExists (command_name))
Jim Inghamebc09c32010-07-07 03:36:20 +0000957 {
Greg Claytonb5472782015-01-09 19:08:20 +0000958 if (cmd_obj->IsRemovable())
959 {
960 result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n",
961 command_name);
962 }
963 else
964 {
965 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
966 command_name);
967 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000968 result.SetStatus (eReturnStatusFailed);
969 }
970 else
971 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000972 if (!m_interpreter.RemoveAlias(command_name))
Jim Inghamebc09c32010-07-07 03:36:20 +0000973 {
Greg Claytona7015092010-09-18 01:14:36 +0000974 if (m_interpreter.AliasExists (command_name))
Jim Inghamebc09c32010-07-07 03:36:20 +0000975 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
976 command_name);
977 else
978 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
979 result.SetStatus (eReturnStatusFailed);
980 }
981 else
982 result.SetStatus (eReturnStatusSuccessFinishNoResult);
983 }
984 }
985 else
986 {
987 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
988 "current list of commands.\n",
989 command_name);
990 result.SetStatus (eReturnStatusFailed);
991 }
992 }
993 else
994 {
995 result.AppendError ("must call 'unalias' with a valid alias");
996 result.SetStatus (eReturnStatusFailed);
997 }
998
999 return result.Succeeded();
1000 }
1001};
1002
Greg Claytonb5472782015-01-09 19:08:20 +00001003#pragma mark CommandObjectCommandsDelete
1004//-------------------------------------------------------------------------
1005// CommandObjectCommandsDelete
1006//-------------------------------------------------------------------------
1007
1008class CommandObjectCommandsDelete : public CommandObjectParsed
1009{
1010public:
Kate Stone7428a182016-07-14 22:03:10 +00001011 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
1012 : CommandObjectParsed(interpreter, "command delete",
1013 "Delete one or more custom commands defined by 'command regex'.", nullptr)
Greg Claytonb5472782015-01-09 19:08:20 +00001014 {
1015 CommandArgumentEntry arg;
1016 CommandArgumentData alias_arg;
1017
1018 // Define the first (and only) variant of this arg.
1019 alias_arg.arg_type = eArgTypeCommandName;
1020 alias_arg.arg_repetition = eArgRepeatPlain;
1021
1022 // There is only one variant this argument could be; put it into the argument entry.
1023 arg.push_back (alias_arg);
1024
1025 // Push the data for the first argument into the m_arguments vector.
1026 m_arguments.push_back (arg);
1027 }
1028
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001029 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +00001030
1031protected:
1032 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001033 DoExecute (Args& args, CommandReturnObject &result) override
Greg Claytonb5472782015-01-09 19:08:20 +00001034 {
1035 CommandObject::CommandMap::iterator pos;
1036
1037 if (args.GetArgumentCount() != 0)
1038 {
1039 const char *command_name = args.GetArgumentAtIndex(0);
1040 if (m_interpreter.CommandExists (command_name))
1041 {
1042 if (m_interpreter.RemoveCommand (command_name))
1043 {
1044 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1045 }
1046 else
1047 {
1048 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
1049 command_name);
1050 result.SetStatus (eReturnStatusFailed);
1051 }
1052 }
1053 else
1054 {
Enrico Granata46d4aa22016-02-29 23:22:53 +00001055 StreamString error_msg_stream;
1056 const bool generate_apropos = true;
1057 const bool generate_type_lookup = false;
1058 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
1059 command_name,
1060 nullptr,
1061 nullptr,
1062 generate_apropos,
1063 generate_type_lookup);
1064 result.AppendErrorWithFormat ("%s", error_msg_stream.GetData());
Greg Claytonb5472782015-01-09 19:08:20 +00001065 result.SetStatus (eReturnStatusFailed);
1066 }
1067 }
1068 else
1069 {
Kate Stone7428a182016-07-14 22:03:10 +00001070 result.AppendErrorWithFormat(
1071 "must call '%s' with one or more valid user defined regular expression command names",
1072 GetCommandName());
Greg Claytonb5472782015-01-09 19:08:20 +00001073 result.SetStatus (eReturnStatusFailed);
1074 }
1075
1076 return result.Succeeded();
1077 }
1078};
1079
Greg Claytonde164aa2011-04-20 16:37:46 +00001080//-------------------------------------------------------------------------
1081// CommandObjectCommandsAddRegex
1082//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001083#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +00001084
Greg Clayton44d93782014-01-27 23:43:24 +00001085class CommandObjectCommandsAddRegex :
1086 public CommandObjectParsed,
Greg Claytonea508632014-11-18 00:43:17 +00001087 public IOHandlerDelegateMultiline
Greg Claytonde164aa2011-04-20 16:37:46 +00001088{
1089public:
Kate Stone7428a182016-07-14 22:03:10 +00001090 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
1091 : CommandObjectParsed(interpreter, "command regex",
1092 "Define a custom command in terms of existing commands by matching regular expressions.",
1093 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
1094 IOHandlerDelegateMultiline("", IOHandlerDelegate::Completion::LLDBCommand),
1095 m_options(interpreter)
Greg Claytonde164aa2011-04-20 16:37:46 +00001096 {
Kate Stoneea671fb2015-07-14 05:48:36 +00001097 SetHelpLong(R"(
1098)" "This command allows the user to create powerful regular expression commands \
1099with substitutions. The regular expressions and substitutions are specified \
1100using the regular expression substitution format of:" R"(
1101
1102 s/<regex>/<subst>/
1103
1104)" "<regex> is a regular expression that can use parenthesis to capture regular \
1105expression input and substitute the captured matches in the output using %1 \
1106for the first match, %2 for the second, and so on." R"(
1107
1108)" "The regular expressions can all be specified on the command line if more than \
1109one argument is provided. If just the command name is provided on the command \
1110line, then the regular expressions and substitutions can be entered on separate \
1111lines, followed by an empty line to terminate the command definition." R"(
1112
1113EXAMPLES
1114
1115)" "The following example will define a regular expression command named 'f' that \
1116will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
1117a number follows 'f':" R"(
1118
1119 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
1120 );
Greg Claytonde164aa2011-04-20 16:37:46 +00001121 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001122
1123 ~CommandObjectCommandsAddRegex() override = default;
1124
Jim Ingham5a988412012-06-08 21:56:10 +00001125protected:
Greg Claytonea508632014-11-18 00:43:17 +00001126 void
1127 IOHandlerActivated (IOHandler &io_handler) override
Greg Clayton44d93782014-01-27 23:43:24 +00001128 {
1129 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1130 if (output_sp)
1131 {
1132 output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n");
1133 output_sp->Flush();
1134 }
1135 }
1136
Greg Claytonea508632014-11-18 00:43:17 +00001137 void
1138 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
Greg Clayton44d93782014-01-27 23:43:24 +00001139 {
1140 io_handler.SetIsDone(true);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001141 if (m_regex_cmd_ap)
Greg Clayton44d93782014-01-27 23:43:24 +00001142 {
1143 StringList lines;
1144 if (lines.SplitIntoLines (data))
1145 {
1146 const size_t num_lines = lines.GetSize();
1147 bool check_only = false;
1148 for (size_t i=0; i<num_lines; ++i)
1149 {
Greg Clayton44d93782014-01-27 23:43:24 +00001150 llvm::StringRef bytes_strref (lines[i]);
1151 Error error = AppendRegexSubstitution (bytes_strref, check_only);
1152 if (error.Fail())
1153 {
1154 if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
1155 {
1156 StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream();
1157 out_stream->Printf("error: %s\n", error.AsCString());
1158 }
1159 }
1160 }
1161 }
1162 if (m_regex_cmd_ap->HasRegexEntries())
1163 {
1164 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1165 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1166 }
1167 }
1168 }
Greg Clayton44d93782014-01-27 23:43:24 +00001169
Greg Claytonde164aa2011-04-20 16:37:46 +00001170 bool
Eric Christopherb0a18142014-11-18 22:40:27 +00001171 DoExecute (Args& command, CommandReturnObject &result) override
Greg Claytonde164aa2011-04-20 16:37:46 +00001172 {
Jim Ingham5a988412012-06-08 21:56:10 +00001173 const size_t argc = command.GetArgumentCount();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001174 if (argc == 0)
Greg Claytonde164aa2011-04-20 16:37:46 +00001175 {
Jason Molenda69c12cc2011-11-10 22:43:35 +00001176 result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001177 result.SetStatus (eReturnStatusFailed);
1178 }
1179 else
1180 {
1181 Error error;
Jim Ingham5a988412012-06-08 21:56:10 +00001182 const char *name = command.GetArgumentAtIndex(0);
Greg Claytonde164aa2011-04-20 16:37:46 +00001183 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
1184 name,
1185 m_options.GetHelp (),
1186 m_options.GetSyntax (),
Greg Claytonb5472782015-01-09 19:08:20 +00001187 10,
1188 0,
1189 true));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001190
1191 if (argc == 1)
Greg Claytonde164aa2011-04-20 16:37:46 +00001192 {
Greg Clayton44d93782014-01-27 23:43:24 +00001193 Debugger &debugger = m_interpreter.GetDebugger();
Kate Stonee30f11d2014-11-17 19:06:59 +00001194 bool color_prompt = debugger.GetUseColor();
Greg Clayton44d93782014-01-27 23:43:24 +00001195 const bool multiple_lines = true; // Get multiple lines
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001196 IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
1197 IOHandler::Type::Other,
1198 "lldb-regex", // Name of input reader for history
1199 "> ", // Prompt
1200 nullptr, // Continuation prompt
1201 multiple_lines,
1202 color_prompt,
1203 0, // Don't show line numbers
1204 *this));
Greg Clayton44d93782014-01-27 23:43:24 +00001205
1206 if (io_handler_sp)
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001207 {
Greg Clayton44d93782014-01-27 23:43:24 +00001208 debugger.PushIOHandler(io_handler_sp);
1209 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Claytonde164aa2011-04-20 16:37:46 +00001210 }
1211 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001212 else
1213 {
1214 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
1215 {
Jim Ingham5a988412012-06-08 21:56:10 +00001216 llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
Greg Clayton44d93782014-01-27 23:43:24 +00001217 bool check_only = false;
1218 error = AppendRegexSubstitution (arg_strref, check_only);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001219 if (error.Fail())
1220 break;
1221 }
1222
1223 if (error.Success())
1224 {
1225 AddRegexCommandToInterpreter();
1226 }
1227 }
1228 if (error.Fail())
1229 {
1230 result.AppendError (error.AsCString());
1231 result.SetStatus (eReturnStatusFailed);
1232 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001233 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001234
Greg Claytonde164aa2011-04-20 16:37:46 +00001235 return result.Succeeded();
1236 }
1237
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001238 Error
Greg Clayton44d93782014-01-27 23:43:24 +00001239 AppendRegexSubstitution (const llvm::StringRef &regex_sed, bool check_only)
Greg Claytonde164aa2011-04-20 16:37:46 +00001240 {
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001241 Error error;
1242
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001243 if (!m_regex_cmd_ap)
Greg Claytonde164aa2011-04-20 16:37:46 +00001244 {
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001245 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
1246 (int)regex_sed.size(),
1247 regex_sed.data());
1248 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001249 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001250
1251 size_t regex_sed_size = regex_sed.size();
1252
1253 if (regex_sed_size <= 1)
1254 {
1255 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
1256 (int)regex_sed.size(),
1257 regex_sed.data());
1258 return error;
1259 }
1260
1261 if (regex_sed[0] != 's')
1262 {
1263 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
1264 (int)regex_sed.size(),
1265 regex_sed.data());
1266 return error;
1267 }
1268 const size_t first_separator_char_pos = 1;
1269 // use the char that follows 's' as the regex separator character
1270 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1271 const char separator_char = regex_sed[first_separator_char_pos];
1272 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
1273
1274 if (second_separator_char_pos == std::string::npos)
1275 {
Greg Claytonea508632014-11-18 00:43:17 +00001276 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'",
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001277 separator_char,
1278 (int)(regex_sed.size() - first_separator_char_pos - 1),
Greg Claytonea508632014-11-18 00:43:17 +00001279 regex_sed.data() + (first_separator_char_pos + 1),
1280 (int)regex_sed.size(),
1281 regex_sed.data());
1282 return error;
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001283 }
1284
1285 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
1286
1287 if (third_separator_char_pos == std::string::npos)
1288 {
Greg Claytonea508632014-11-18 00:43:17 +00001289 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'",
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001290 separator_char,
1291 (int)(regex_sed.size() - second_separator_char_pos - 1),
Greg Claytonea508632014-11-18 00:43:17 +00001292 regex_sed.data() + (second_separator_char_pos + 1),
1293 (int)regex_sed.size(),
1294 regex_sed.data());
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001295 return error;
1296 }
1297
1298 if (third_separator_char_pos != regex_sed_size - 1)
1299 {
1300 // Make sure that everything that follows the last regex
1301 // separator char
1302 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
1303 {
1304 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
1305 (int)third_separator_char_pos + 1,
1306 regex_sed.data(),
1307 (int)(regex_sed.size() - third_separator_char_pos - 1),
1308 regex_sed.data() + (third_separator_char_pos + 1));
1309 return error;
1310 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001311 }
1312 else if (first_separator_char_pos + 1 == second_separator_char_pos)
1313 {
1314 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1315 separator_char,
1316 separator_char,
1317 separator_char,
1318 (int)regex_sed.size(),
1319 regex_sed.data());
1320 return error;
1321 }
1322 else if (second_separator_char_pos + 1 == third_separator_char_pos)
1323 {
1324 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1325 separator_char,
1326 separator_char,
1327 separator_char,
1328 (int)regex_sed.size(),
1329 regex_sed.data());
1330 return error;
1331 }
Greg Clayton44d93782014-01-27 23:43:24 +00001332
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001333 if (!check_only)
Greg Clayton44d93782014-01-27 23:43:24 +00001334 {
1335 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
1336 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
1337 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
1338 subst.c_str());
1339 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001340 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001341 }
1342
1343 void
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001344 AddRegexCommandToInterpreter()
Greg Claytonde164aa2011-04-20 16:37:46 +00001345 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001346 if (m_regex_cmd_ap)
Greg Claytonde164aa2011-04-20 16:37:46 +00001347 {
1348 if (m_regex_cmd_ap->HasRegexEntries())
1349 {
1350 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1351 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1352 }
1353 }
1354 }
1355
Greg Claytonde164aa2011-04-20 16:37:46 +00001356private:
Greg Clayton7b0992d2013-04-18 22:45:39 +00001357 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001358
1359 class CommandOptions : public Options
1360 {
1361 public:
Greg Claytonde164aa2011-04-20 16:37:46 +00001362 CommandOptions (CommandInterpreter &interpreter) :
1363 Options (interpreter)
1364 {
1365 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001366
1367 ~CommandOptions() override = default;
1368
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001369 Error
1370 SetOptionValue (uint32_t option_idx, const char *option_arg) override
Greg Claytonde164aa2011-04-20 16:37:46 +00001371 {
1372 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001373 const int short_option = m_getopt_table[option_idx].val;
Greg Claytonde164aa2011-04-20 16:37:46 +00001374
1375 switch (short_option)
1376 {
1377 case 'h':
1378 m_help.assign (option_arg);
1379 break;
1380 case 's':
1381 m_syntax.assign (option_arg);
1382 break;
Greg Claytonde164aa2011-04-20 16:37:46 +00001383 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001384 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Greg Claytonde164aa2011-04-20 16:37:46 +00001385 break;
1386 }
1387
1388 return error;
1389 }
1390
1391 void
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001392 OptionParsingStarting () override
Greg Claytonde164aa2011-04-20 16:37:46 +00001393 {
1394 m_help.clear();
1395 m_syntax.clear();
1396 }
1397
1398 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001399 GetDefinitions () override
Greg Claytonde164aa2011-04-20 16:37:46 +00001400 {
1401 return g_option_table;
1402 }
1403
1404 // Options table: Required for subclasses of Options.
1405
1406 static OptionDefinition g_option_table[];
1407
1408 const char *
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001409 GetHelp()
Greg Claytonde164aa2011-04-20 16:37:46 +00001410 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001411 return (m_help.empty() ? nullptr : m_help.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001412 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001413
Greg Claytonde164aa2011-04-20 16:37:46 +00001414 const char *
1415 GetSyntax ()
1416 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001417 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001418 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001419
Greg Claytonde164aa2011-04-20 16:37:46 +00001420 protected:
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001421 // Instance variables to hold the values for command options.
1422
Greg Claytonde164aa2011-04-20 16:37:46 +00001423 std::string m_help;
1424 std::string m_syntax;
1425 };
Jim Ingham5a988412012-06-08 21:56:10 +00001426
Eric Christopherb0a18142014-11-18 22:40:27 +00001427 Options *
1428 GetOptions () override
Greg Claytonde164aa2011-04-20 16:37:46 +00001429 {
1430 return &m_options;
1431 }
Jim Ingham5a988412012-06-08 21:56:10 +00001432
1433 CommandOptions m_options;
Greg Claytonde164aa2011-04-20 16:37:46 +00001434};
1435
Greg Claytonde164aa2011-04-20 16:37:46 +00001436OptionDefinition
1437CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1438{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001439{ LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."},
1440{ LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1441{ 0 , false, nullptr , 0 , 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr }
Greg Claytonde164aa2011-04-20 16:37:46 +00001442};
1443
Jim Ingham5a988412012-06-08 21:56:10 +00001444class CommandObjectPythonFunction : public CommandObjectRaw
Enrico Granata223383e2011-08-16 23:24:13 +00001445{
Enrico Granata223383e2011-08-16 23:24:13 +00001446public:
Enrico Granata223383e2011-08-16 23:24:13 +00001447 CommandObjectPythonFunction (CommandInterpreter &interpreter,
1448 std::string name,
Enrico Granata0a305db2011-11-07 22:57:04 +00001449 std::string funct,
Enrico Granata735152e2014-09-15 17:52:44 +00001450 std::string help,
Enrico Granata0a305db2011-11-07 22:57:04 +00001451 ScriptedCommandSynchronicity synch) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001452 CommandObjectRaw(interpreter,
1453 name.c_str(),
1454 nullptr,
1455 nullptr),
Jim Ingham5a988412012-06-08 21:56:10 +00001456 m_function_name(funct),
Enrico Granatafac939e2012-09-18 21:53:02 +00001457 m_synchro(synch),
1458 m_fetched_help_long(false)
Enrico Granata223383e2011-08-16 23:24:13 +00001459 {
Enrico Granata735152e2014-09-15 17:52:44 +00001460 if (!help.empty())
1461 SetHelp(help.c_str());
1462 else
1463 {
1464 StreamString stream;
1465 stream.Printf("For more information run 'help %s'",name.c_str());
1466 SetHelp(stream.GetData());
1467 }
Enrico Granata223383e2011-08-16 23:24:13 +00001468 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001469
1470 ~CommandObjectPythonFunction() override = default;
1471
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001472 bool
1473 IsRemovable () const override
Jim Ingham5a988412012-06-08 21:56:10 +00001474 {
1475 return true;
1476 }
1477
1478 const std::string&
1479 GetFunctionName ()
1480 {
1481 return m_function_name;
1482 }
1483
1484 ScriptedCommandSynchronicity
1485 GetSynchronicity ()
1486 {
1487 return m_synchro;
1488 }
1489
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001490 const char *
1491 GetHelpLong () override
Enrico Granatafac939e2012-09-18 21:53:02 +00001492 {
1493 if (!m_fetched_help_long)
1494 {
1495 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1496 if (scripter)
1497 {
1498 std::string docstring;
1499 m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring);
1500 if (!docstring.empty())
Enrico Granatabfb75e92016-03-22 22:12:59 +00001501 SetHelpLong(docstring.c_str());
Enrico Granatafac939e2012-09-18 21:53:02 +00001502 }
1503 }
1504 return CommandObjectRaw::GetHelpLong();
1505 }
1506
Jim Ingham5a988412012-06-08 21:56:10 +00001507protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001508 bool
1509 DoExecute (const char *raw_command_line, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00001510 {
1511 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1512
1513 Error error;
1514
Jim Ingham70f11f82012-06-27 17:25:36 +00001515 result.SetStatus(eReturnStatusInvalid);
1516
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001517 if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1518 raw_command_line,
1519 m_synchro,
1520 result,
1521 error,
1522 m_exe_ctx))
Enrico Granata223383e2011-08-16 23:24:13 +00001523 {
1524 result.AppendError(error.AsCString());
1525 result.SetStatus(eReturnStatusFailed);
1526 }
1527 else
Jim Ingham70f11f82012-06-27 17:25:36 +00001528 {
1529 // Don't change the status if the command already set it...
1530 if (result.GetStatus() == eReturnStatusInvalid)
1531 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001532 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0')
Jim Ingham70f11f82012-06-27 17:25:36 +00001533 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1534 else
1535 result.SetStatus(eReturnStatusSuccessFinishResult);
1536 }
1537 }
Enrico Granata223383e2011-08-16 23:24:13 +00001538
1539 return result.Succeeded();
1540 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001541
1542private:
1543 std::string m_function_name;
1544 ScriptedCommandSynchronicity m_synchro;
1545 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001546};
1547
Enrico Granata9fe00e52015-03-13 02:20:41 +00001548class CommandObjectScriptingObject : public CommandObjectRaw
1549{
Enrico Granata9fe00e52015-03-13 02:20:41 +00001550public:
Enrico Granata9fe00e52015-03-13 02:20:41 +00001551 CommandObjectScriptingObject (CommandInterpreter &interpreter,
1552 std::string name,
Zachary Turner0641ca12015-03-17 20:04:04 +00001553 StructuredData::GenericSP cmd_obj_sp,
Enrico Granata9fe00e52015-03-13 02:20:41 +00001554 ScriptedCommandSynchronicity synch) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001555 CommandObjectRaw(interpreter,
1556 name.c_str(),
1557 nullptr,
1558 nullptr),
1559 m_cmd_obj_sp(cmd_obj_sp),
1560 m_synchro(synch),
1561 m_fetched_help_short(false),
1562 m_fetched_help_long(false)
Enrico Granata9fe00e52015-03-13 02:20:41 +00001563 {
1564 StreamString stream;
1565 stream.Printf("For more information run 'help %s'",name.c_str());
1566 SetHelp(stream.GetData());
Enrico Granatae87764f2015-05-27 05:04:35 +00001567 if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter())
1568 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
Enrico Granata9fe00e52015-03-13 02:20:41 +00001569 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001570
1571 ~CommandObjectScriptingObject() override = default;
1572
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001573 bool
1574 IsRemovable () const override
Enrico Granata9fe00e52015-03-13 02:20:41 +00001575 {
1576 return true;
1577 }
1578
Zachary Turner0641ca12015-03-17 20:04:04 +00001579 StructuredData::GenericSP
Enrico Granata9fe00e52015-03-13 02:20:41 +00001580 GetImplementingObject ()
1581 {
1582 return m_cmd_obj_sp;
1583 }
1584
1585 ScriptedCommandSynchronicity
1586 GetSynchronicity ()
1587 {
1588 return m_synchro;
1589 }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001590
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001591 const char *
1592 GetHelp () override
Enrico Granata6f79bb22015-03-13 22:22:28 +00001593 {
1594 if (!m_fetched_help_short)
1595 {
1596 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1597 if (scripter)
1598 {
1599 std::string docstring;
1600 m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring);
1601 if (!docstring.empty())
Enrico Granatabfb75e92016-03-22 22:12:59 +00001602 SetHelp(docstring.c_str());
Enrico Granata6f79bb22015-03-13 22:22:28 +00001603 }
1604 }
1605 return CommandObjectRaw::GetHelp();
1606 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001607
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001608 const char *
1609 GetHelpLong () override
Enrico Granata9fe00e52015-03-13 02:20:41 +00001610 {
Enrico Granata6f79bb22015-03-13 22:22:28 +00001611 if (!m_fetched_help_long)
1612 {
1613 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1614 if (scripter)
1615 {
1616 std::string docstring;
1617 m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring);
1618 if (!docstring.empty())
Enrico Granatabfb75e92016-03-22 22:12:59 +00001619 SetHelpLong(docstring.c_str());
Enrico Granata6f79bb22015-03-13 22:22:28 +00001620 }
1621 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001622 return CommandObjectRaw::GetHelpLong();
1623 }
1624
1625protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001626 bool
1627 DoExecute (const char *raw_command_line, CommandReturnObject &result) override
Enrico Granata9fe00e52015-03-13 02:20:41 +00001628 {
1629 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1630
1631 Error error;
1632
1633 result.SetStatus(eReturnStatusInvalid);
1634
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001635 if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp,
1636 raw_command_line,
1637 m_synchro,
1638 result,
1639 error,
1640 m_exe_ctx))
Enrico Granata9fe00e52015-03-13 02:20:41 +00001641 {
1642 result.AppendError(error.AsCString());
1643 result.SetStatus(eReturnStatusFailed);
1644 }
1645 else
1646 {
1647 // Don't change the status if the command already set it...
1648 if (result.GetStatus() == eReturnStatusInvalid)
1649 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001650 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0')
Enrico Granata9fe00e52015-03-13 02:20:41 +00001651 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1652 else
1653 result.SetStatus(eReturnStatusSuccessFinishResult);
1654 }
1655 }
1656
1657 return result.Succeeded();
1658 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001659
1660private:
1661 StructuredData::GenericSP m_cmd_obj_sp;
1662 ScriptedCommandSynchronicity m_synchro;
1663 bool m_fetched_help_short: 1;
1664 bool m_fetched_help_long: 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001665};
1666
Enrico Granataa9dbf432011-10-17 21:45:27 +00001667//-------------------------------------------------------------------------
1668// CommandObjectCommandsScriptImport
1669//-------------------------------------------------------------------------
1670
Jim Ingham5a988412012-06-08 21:56:10 +00001671class CommandObjectCommandsScriptImport : public CommandObjectParsed
Enrico Granataa9dbf432011-10-17 21:45:27 +00001672{
Jim Ingham5a988412012-06-08 21:56:10 +00001673public:
1674 CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001675 CommandObjectParsed(interpreter,
1676 "command script import",
1677 "Import a scripting module in LLDB.",
1678 nullptr),
Jim Ingham5a988412012-06-08 21:56:10 +00001679 m_options(interpreter)
1680 {
1681 CommandArgumentEntry arg1;
1682 CommandArgumentData cmd_arg;
1683
1684 // Define the first (and only) variant of this arg.
1685 cmd_arg.arg_type = eArgTypeFilename;
Enrico Granata3b00e352015-06-16 18:31:04 +00001686 cmd_arg.arg_repetition = eArgRepeatPlus;
Jim Ingham5a988412012-06-08 21:56:10 +00001687
1688 // There is only one variant this argument could be; put it into the argument entry.
1689 arg1.push_back (cmd_arg);
1690
1691 // Push the data for the first argument into the m_arguments vector.
1692 m_arguments.push_back (arg1);
1693 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001694
1695 ~CommandObjectCommandsScriptImport() override = default;
1696
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001697 int
Jim Ingham5a988412012-06-08 21:56:10 +00001698 HandleArgumentCompletion (Args &input,
1699 int &cursor_index,
1700 int &cursor_char_position,
1701 OptionElementVector &opt_element_vector,
1702 int match_start_point,
1703 int max_return_elements,
1704 bool &word_complete,
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001705 StringList &matches) override
Jim Ingham5a988412012-06-08 21:56:10 +00001706 {
1707 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1708 completion_str.erase (cursor_char_position);
1709
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001710 CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
1711 CommandCompletions::eDiskFileCompletion,
1712 completion_str.c_str(),
1713 match_start_point,
1714 max_return_elements,
1715 nullptr,
1716 word_complete,
1717 matches);
Jim Ingham5a988412012-06-08 21:56:10 +00001718 return matches.GetSize();
1719 }
1720
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001721 Options *
1722 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +00001723 {
1724 return &m_options;
1725 }
1726
1727protected:
Enrico Granata0a305db2011-11-07 22:57:04 +00001728 class CommandOptions : public Options
1729 {
1730 public:
Enrico Granata0a305db2011-11-07 22:57:04 +00001731 CommandOptions (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001732 Options (interpreter)
Enrico Granata0a305db2011-11-07 22:57:04 +00001733 {
1734 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001735
1736 ~CommandOptions() override = default;
1737
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001738 Error
1739 SetOptionValue (uint32_t option_idx, const char *option_arg) override
Enrico Granata0a305db2011-11-07 22:57:04 +00001740 {
1741 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001742 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001743
1744 switch (short_option)
1745 {
1746 case 'r':
1747 m_allow_reload = true;
1748 break;
1749 default:
1750 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1751 break;
1752 }
1753
1754 return error;
1755 }
1756
1757 void
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001758 OptionParsingStarting () override
Enrico Granata0a305db2011-11-07 22:57:04 +00001759 {
Enrico Granatae0c70f12013-05-31 01:03:09 +00001760 m_allow_reload = true;
Enrico Granata0a305db2011-11-07 22:57:04 +00001761 }
1762
1763 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001764 GetDefinitions () override
Enrico Granata0a305db2011-11-07 22:57:04 +00001765 {
1766 return g_option_table;
1767 }
1768
1769 // Options table: Required for subclasses of Options.
1770
1771 static OptionDefinition g_option_table[];
1772
1773 // Instance variables to hold the values for command options.
1774
1775 bool m_allow_reload;
1776 };
Enrico Granata0a305db2011-11-07 22:57:04 +00001777
Enrico Granataa9dbf432011-10-17 21:45:27 +00001778 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001779 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granataa9dbf432011-10-17 21:45:27 +00001780 {
Enrico Granataa9dbf432011-10-17 21:45:27 +00001781 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1782 {
1783 result.AppendError ("only scripting language supported for module importing is currently Python");
1784 result.SetStatus (eReturnStatusFailed);
1785 return false;
1786 }
1787
Jim Ingham5a988412012-06-08 21:56:10 +00001788 size_t argc = command.GetArgumentCount();
Enrico Granata3b00e352015-06-16 18:31:04 +00001789 if (0 == argc)
Enrico Granataa9dbf432011-10-17 21:45:27 +00001790 {
Enrico Granata3b00e352015-06-16 18:31:04 +00001791 result.AppendError("command script import needs one or more arguments");
Enrico Granataa9dbf432011-10-17 21:45:27 +00001792 result.SetStatus (eReturnStatusFailed);
1793 return false;
1794 }
1795
Ed Maste0e978482015-06-17 17:29:56 +00001796 for (size_t i = 0;
Enrico Granata3b00e352015-06-16 18:31:04 +00001797 i < argc;
1798 i++)
Enrico Granataa9dbf432011-10-17 21:45:27 +00001799 {
Enrico Granata3b00e352015-06-16 18:31:04 +00001800 std::string path = command.GetArgumentAtIndex(i);
1801 Error error;
1802
1803 const bool init_session = true;
1804 // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
1805 // commands won't ever be recursively invoked, but it's actually possible to craft
1806 // a Python script that does other "command script imports" in __lldb_init_module
1807 // the real fix is to have recursive commands possible with a CommandInvocation object
1808 // separate from the CommandObject itself, so that recursive command invocations
1809 // won't stomp on each other (wrt to execution contents, options, and more)
1810 m_exe_ctx.Clear();
1811 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
1812 m_options.m_allow_reload,
1813 init_session,
1814 error))
1815 {
1816 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1817 }
1818 else
1819 {
1820 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
1821 result.SetStatus (eReturnStatusFailed);
1822 }
Enrico Granataa9dbf432011-10-17 21:45:27 +00001823 }
1824
1825 return result.Succeeded();
1826 }
Enrico Granata0a305db2011-11-07 22:57:04 +00001827
Jim Ingham5a988412012-06-08 21:56:10 +00001828 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001829};
Enrico Granata223383e2011-08-16 23:24:13 +00001830
Enrico Granata0a305db2011-11-07 22:57:04 +00001831OptionDefinition
1832CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
1833{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001834 { 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."},
1835 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata0a305db2011-11-07 22:57:04 +00001836};
1837
Enrico Granata223383e2011-08-16 23:24:13 +00001838//-------------------------------------------------------------------------
1839// CommandObjectCommandsScriptAdd
1840//-------------------------------------------------------------------------
1841
Greg Clayton44d93782014-01-27 23:43:24 +00001842class CommandObjectCommandsScriptAdd :
1843 public CommandObjectParsed,
1844 public IOHandlerDelegateMultiline
Enrico Granata223383e2011-08-16 23:24:13 +00001845{
Jim Ingham5a988412012-06-08 21:56:10 +00001846public:
1847 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001848 CommandObjectParsed(interpreter,
1849 "command script add",
1850 "Add a scripted function as an LLDB command.",
1851 nullptr),
Greg Claytonc3d874a2014-05-08 16:59:00 +00001852 IOHandlerDelegateMultiline ("DONE"),
Jim Ingham5a988412012-06-08 21:56:10 +00001853 m_options (interpreter)
1854 {
1855 CommandArgumentEntry arg1;
1856 CommandArgumentData cmd_arg;
1857
1858 // Define the first (and only) variant of this arg.
1859 cmd_arg.arg_type = eArgTypeCommandName;
1860 cmd_arg.arg_repetition = eArgRepeatPlain;
1861
1862 // There is only one variant this argument could be; put it into the argument entry.
1863 arg1.push_back (cmd_arg);
1864
1865 // Push the data for the first argument into the m_arguments vector.
1866 m_arguments.push_back (arg1);
1867 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001868
1869 ~CommandObjectCommandsScriptAdd() override = default;
1870
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001871 Options *
1872 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +00001873 {
1874 return &m_options;
1875 }
1876
1877protected:
Enrico Granata223383e2011-08-16 23:24:13 +00001878 class CommandOptions : public Options
1879 {
1880 public:
Enrico Granata223383e2011-08-16 23:24:13 +00001881 CommandOptions (CommandInterpreter &interpreter) :
Enrico Granata9fe00e52015-03-13 02:20:41 +00001882 Options (interpreter),
1883 m_class_name(),
1884 m_funct_name(),
1885 m_short_help(),
1886 m_synchronicity(eScriptedCommandSynchronicitySynchronous)
Enrico Granata223383e2011-08-16 23:24:13 +00001887 {
1888 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001889
1890 ~CommandOptions() override = default;
1891
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001892 Error
1893 SetOptionValue (uint32_t option_idx, const char *option_arg) override
Enrico Granata223383e2011-08-16 23:24:13 +00001894 {
1895 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001896 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata223383e2011-08-16 23:24:13 +00001897
1898 switch (short_option)
1899 {
1900 case 'f':
Enrico Granata735152e2014-09-15 17:52:44 +00001901 if (option_arg)
1902 m_funct_name.assign(option_arg);
1903 break;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001904 case 'c':
1905 if (option_arg)
1906 m_class_name.assign(option_arg);
1907 break;
Enrico Granata735152e2014-09-15 17:52:44 +00001908 case 'h':
1909 if (option_arg)
1910 m_short_help.assign(option_arg);
Enrico Granata223383e2011-08-16 23:24:13 +00001911 break;
Enrico Granata0a305db2011-11-07 22:57:04 +00001912 case 's':
Greg Clayton44d93782014-01-27 23:43:24 +00001913 m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
Enrico Granata0a305db2011-11-07 22:57:04 +00001914 if (!error.Success())
1915 error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
1916 break;
Enrico Granata223383e2011-08-16 23:24:13 +00001917 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001918 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Enrico Granata223383e2011-08-16 23:24:13 +00001919 break;
1920 }
1921
1922 return error;
1923 }
1924
1925 void
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001926 OptionParsingStarting () override
Enrico Granata223383e2011-08-16 23:24:13 +00001927 {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001928 m_class_name.clear();
Enrico Granata735152e2014-09-15 17:52:44 +00001929 m_funct_name.clear();
1930 m_short_help.clear();
Greg Clayton44d93782014-01-27 23:43:24 +00001931 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
Enrico Granata223383e2011-08-16 23:24:13 +00001932 }
1933
1934 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001935 GetDefinitions () override
Enrico Granata223383e2011-08-16 23:24:13 +00001936 {
1937 return g_option_table;
1938 }
1939
1940 // Options table: Required for subclasses of Options.
1941
1942 static OptionDefinition g_option_table[];
1943
1944 // Instance variables to hold the values for command options.
1945
Enrico Granata9fe00e52015-03-13 02:20:41 +00001946 std::string m_class_name;
Enrico Granata223383e2011-08-16 23:24:13 +00001947 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001948 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001949 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001950 };
Jim Ingham5a988412012-06-08 21:56:10 +00001951
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001952 void
1953 IOHandlerActivated (IOHandler &io_handler) override
Enrico Granata223383e2011-08-16 23:24:13 +00001954 {
Greg Clayton44d93782014-01-27 23:43:24 +00001955 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1956 if (output_sp)
Enrico Granata223383e2011-08-16 23:24:13 +00001957 {
Greg Clayton44d93782014-01-27 23:43:24 +00001958 output_sp->PutCString(g_python_command_instructions);
1959 output_sp->Flush();
Enrico Granata223383e2011-08-16 23:24:13 +00001960 }
Greg Clayton44d93782014-01-27 23:43:24 +00001961 }
Enrico Granata223383e2011-08-16 23:24:13 +00001962
Greg Clayton44d93782014-01-27 23:43:24 +00001963
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001964 void
1965 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
Greg Clayton44d93782014-01-27 23:43:24 +00001966 {
1967 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1968
1969 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1970 if (interpreter)
1971 {
1972
1973 StringList lines;
1974 lines.SplitIntoLines(data);
1975 if (lines.GetSize() > 0)
1976 {
1977 std::string funct_name_str;
1978 if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str))
1979 {
1980 if (funct_name_str.empty())
1981 {
1982 error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n");
1983 error_sp->Flush();
1984 }
1985 else
1986 {
1987 // everything should be fine now, let's add this alias
1988
1989 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
1990 m_cmd_name,
1991 funct_name_str.c_str(),
Enrico Granata735152e2014-09-15 17:52:44 +00001992 m_short_help,
Greg Clayton44d93782014-01-27 23:43:24 +00001993 m_synchronicity));
1994
1995 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
1996 {
1997 error_sp->Printf ("error: unable to add selected command, didn't add python command.\n");
1998 error_sp->Flush();
1999 }
2000 }
2001 }
2002 else
2003 {
2004 error_sp->Printf ("error: unable to create function, didn't add python command.\n");
2005 error_sp->Flush();
2006 }
2007 }
2008 else
2009 {
2010 error_sp->Printf ("error: empty function, didn't add python command.\n");
2011 error_sp->Flush();
2012 }
2013 }
2014 else
2015 {
2016 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
2017 error_sp->Flush();
2018 }
2019
2020 io_handler.SetIsDone(true);
Greg Clayton44d93782014-01-27 23:43:24 +00002021 }
2022
Jim Ingham5a988412012-06-08 21:56:10 +00002023protected:
Enrico Granata223383e2011-08-16 23:24:13 +00002024 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002025 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002026 {
Enrico Granata99f0b8f2011-08-17 01:30:04 +00002027 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
2028 {
2029 result.AppendError ("only scripting language supported for scripted commands is currently Python");
2030 result.SetStatus (eReturnStatusFailed);
2031 return false;
2032 }
2033
Jim Ingham5a988412012-06-08 21:56:10 +00002034 size_t argc = command.GetArgumentCount();
Enrico Granata223383e2011-08-16 23:24:13 +00002035
2036 if (argc != 1)
2037 {
2038 result.AppendError ("'command script add' requires one argument");
2039 result.SetStatus (eReturnStatusFailed);
2040 return false;
2041 }
2042
Enrico Granata735152e2014-09-15 17:52:44 +00002043 // Store the options in case we get multi-line input
Greg Clayton44d93782014-01-27 23:43:24 +00002044 m_cmd_name = command.GetArgumentAtIndex(0);
Enrico Granata735152e2014-09-15 17:52:44 +00002045 m_short_help.assign(m_options.m_short_help);
Greg Clayton44d93782014-01-27 23:43:24 +00002046 m_synchronicity = m_options.m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00002047
Enrico Granata9fe00e52015-03-13 02:20:41 +00002048 if (m_options.m_class_name.empty())
Enrico Granata223383e2011-08-16 23:24:13 +00002049 {
Enrico Granata9fe00e52015-03-13 02:20:41 +00002050 if (m_options.m_funct_name.empty())
2051 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002052 m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt
2053 *this, // IOHandlerDelegate
2054 true, // Run IOHandler in async mode
2055 nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
Enrico Granata9fe00e52015-03-13 02:20:41 +00002056 }
2057 else
2058 {
2059 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
2060 m_cmd_name,
2061 m_options.m_funct_name,
2062 m_options.m_short_help,
2063 m_synchronicity));
2064 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
2065 {
2066 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2067 }
2068 else
2069 {
2070 result.AppendError("cannot add command");
2071 result.SetStatus (eReturnStatusFailed);
2072 }
2073 }
Enrico Granata223383e2011-08-16 23:24:13 +00002074 }
2075 else
2076 {
Enrico Granata9fe00e52015-03-13 02:20:41 +00002077 ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter();
2078 if (!interpreter)
2079 {
2080 result.AppendError("cannot find ScriptInterpreter");
2081 result.SetStatus(eReturnStatusFailed);
2082 return false;
2083 }
2084
2085 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str());
2086 if (!cmd_obj_sp)
2087 {
2088 result.AppendError("cannot create helper object");
2089 result.SetStatus(eReturnStatusFailed);
2090 return false;
2091 }
2092
2093 CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter,
2094 m_cmd_name,
2095 cmd_obj_sp,
2096 m_synchronicity));
Greg Clayton44d93782014-01-27 23:43:24 +00002097 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
Enrico Granata223383e2011-08-16 23:24:13 +00002098 {
2099 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2100 }
2101 else
2102 {
2103 result.AppendError("cannot add command");
2104 result.SetStatus (eReturnStatusFailed);
2105 }
2106 }
2107
2108 return result.Succeeded();
Enrico Granata223383e2011-08-16 23:24:13 +00002109 }
Jim Ingham5a988412012-06-08 21:56:10 +00002110
2111 CommandOptions m_options;
Greg Clayton44d93782014-01-27 23:43:24 +00002112 std::string m_cmd_name;
Enrico Granata735152e2014-09-15 17:52:44 +00002113 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00002114 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00002115};
2116
Enrico Granata0a305db2011-11-07 22:57:04 +00002117static OptionEnumValueElement g_script_synchro_type[] =
2118{
2119 { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"},
2120 { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"},
2121 { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"},
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002122 { 0, nullptr, nullptr }
Enrico Granata0a305db2011-11-07 22:57:04 +00002123};
2124
Enrico Granata223383e2011-08-16 23:24:13 +00002125OptionDefinition
2126CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
2127{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002128 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
2129 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."},
2130 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."},
2131 { 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."},
2132 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata223383e2011-08-16 23:24:13 +00002133};
2134
2135//-------------------------------------------------------------------------
2136// CommandObjectCommandsScriptList
2137//-------------------------------------------------------------------------
2138
Jim Ingham5a988412012-06-08 21:56:10 +00002139class CommandObjectCommandsScriptList : public CommandObjectParsed
Enrico Granata223383e2011-08-16 23:24:13 +00002140{
Enrico Granata223383e2011-08-16 23:24:13 +00002141public:
2142 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002143 CommandObjectParsed(interpreter,
2144 "command script list",
2145 "List defined scripted commands.",
2146 nullptr)
Enrico Granata223383e2011-08-16 23:24:13 +00002147 {
2148 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002149
2150 ~CommandObjectCommandsScriptList() override = default;
2151
Enrico Granata223383e2011-08-16 23:24:13 +00002152 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002153 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002154 {
Enrico Granata223383e2011-08-16 23:24:13 +00002155 m_interpreter.GetHelp(result,
2156 CommandInterpreter::eCommandTypesUserDef);
2157
2158 result.SetStatus (eReturnStatusSuccessFinishResult);
2159
2160 return true;
Enrico Granata223383e2011-08-16 23:24:13 +00002161 }
2162};
2163
2164//-------------------------------------------------------------------------
2165// CommandObjectCommandsScriptClear
2166//-------------------------------------------------------------------------
2167
Jim Ingham5a988412012-06-08 21:56:10 +00002168class CommandObjectCommandsScriptClear : public CommandObjectParsed
Enrico Granata223383e2011-08-16 23:24:13 +00002169{
Enrico Granata223383e2011-08-16 23:24:13 +00002170public:
2171 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002172 CommandObjectParsed(interpreter,
2173 "command script clear",
2174 "Delete all scripted commands.",
2175 nullptr)
Enrico Granata223383e2011-08-16 23:24:13 +00002176 {
2177 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002178
2179 ~CommandObjectCommandsScriptClear() override = default;
2180
Jim Ingham5a988412012-06-08 21:56:10 +00002181protected:
Enrico Granata223383e2011-08-16 23:24:13 +00002182 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002183 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002184 {
Enrico Granata223383e2011-08-16 23:24:13 +00002185 m_interpreter.RemoveAllUser();
2186
2187 result.SetStatus (eReturnStatusSuccessFinishResult);
2188
2189 return true;
Enrico Granata223383e2011-08-16 23:24:13 +00002190 }
2191};
2192
2193//-------------------------------------------------------------------------
2194// CommandObjectCommandsScriptDelete
2195//-------------------------------------------------------------------------
2196
Jim Ingham5a988412012-06-08 21:56:10 +00002197class CommandObjectCommandsScriptDelete : public CommandObjectParsed
Enrico Granata223383e2011-08-16 23:24:13 +00002198{
Enrico Granata223383e2011-08-16 23:24:13 +00002199public:
2200 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002201 CommandObjectParsed(interpreter,
2202 "command script delete",
2203 "Delete a scripted command.",
2204 nullptr)
Enrico Granata223383e2011-08-16 23:24:13 +00002205 {
2206 CommandArgumentEntry arg1;
2207 CommandArgumentData cmd_arg;
2208
2209 // Define the first (and only) variant of this arg.
2210 cmd_arg.arg_type = eArgTypeCommandName;
2211 cmd_arg.arg_repetition = eArgRepeatPlain;
2212
2213 // There is only one variant this argument could be; put it into the argument entry.
2214 arg1.push_back (cmd_arg);
2215
2216 // Push the data for the first argument into the m_arguments vector.
2217 m_arguments.push_back (arg1);
2218 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002219
2220 ~CommandObjectCommandsScriptDelete() override = default;
2221
Jim Ingham5a988412012-06-08 21:56:10 +00002222protected:
Enrico Granata223383e2011-08-16 23:24:13 +00002223 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002224 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002225 {
2226
Jim Ingham5a988412012-06-08 21:56:10 +00002227 size_t argc = command.GetArgumentCount();
Enrico Granata223383e2011-08-16 23:24:13 +00002228
2229 if (argc != 1)
2230 {
2231 result.AppendError ("'command script delete' requires one argument");
2232 result.SetStatus (eReturnStatusFailed);
2233 return false;
2234 }
2235
Jim Ingham5a988412012-06-08 21:56:10 +00002236 const char* cmd_name = command.GetArgumentAtIndex(0);
Enrico Granata223383e2011-08-16 23:24:13 +00002237
2238 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
2239 {
2240 m_interpreter.RemoveUser(cmd_name);
2241 result.SetStatus (eReturnStatusSuccessFinishResult);
2242 }
2243 else
2244 {
2245 result.AppendErrorWithFormat ("command %s not found", cmd_name);
2246 result.SetStatus (eReturnStatusFailed);
2247 }
2248
2249 return result.Succeeded();
Enrico Granata223383e2011-08-16 23:24:13 +00002250 }
2251};
2252
2253#pragma mark CommandObjectMultiwordCommandsScript
2254
2255//-------------------------------------------------------------------------
2256// CommandObjectMultiwordCommandsScript
2257//-------------------------------------------------------------------------
2258
2259class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
2260{
2261public:
Kate Stone7428a182016-07-14 22:03:10 +00002262 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
2263 : CommandObjectMultiword(interpreter, "command script",
2264 "Commands for managing custom commands implemented by interpreter scripts.",
2265 "command script <subcommand> [<subcommand-options>]")
Enrico Granata223383e2011-08-16 23:24:13 +00002266 {
Greg Claytonb5472782015-01-09 19:08:20 +00002267 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
2268 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
2269 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
Enrico Granata223383e2011-08-16 23:24:13 +00002270 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
Greg Claytonb5472782015-01-09 19:08:20 +00002271 LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
Enrico Granata223383e2011-08-16 23:24:13 +00002272 }
2273
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002274 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00002275};
2276
Jim Inghamebc09c32010-07-07 03:36:20 +00002277#pragma mark CommandObjectMultiwordCommands
2278
2279//-------------------------------------------------------------------------
2280// CommandObjectMultiwordCommands
2281//-------------------------------------------------------------------------
2282
Kate Stone7428a182016-07-14 22:03:10 +00002283CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(CommandInterpreter &interpreter)
2284 : CommandObjectMultiword(interpreter, "command", "Commands for managing custom LLDB commands.",
2285 "command <subcommand> [<subcommand-options>]")
Jim Inghamebc09c32010-07-07 03:36:20 +00002286{
Greg Claytona7015092010-09-18 01:14:36 +00002287 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
2288 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
2289 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytonb5472782015-01-09 19:08:20 +00002290 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter)));
Greg Claytonde164aa2011-04-20 16:37:46 +00002291 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Greg Claytonb5472782015-01-09 19:08:20 +00002292 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
2293 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00002294}
2295
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002296CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;