blob: 0cba318a266d51172d3940a59b33ce9496c57780 [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),
Todd Fialae1cfbc72016-08-11 23:51:28 +000047 m_options()
Jim Ingham5a988412012-06-08 21:56:10 +000048 {
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:
Todd Fialae1cfbc72016-08-11 23:51:28 +000063 CommandOptions() :
64 Options(),
Enrico Granata7594f142013-06-17 22:51:50 +000065 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
Todd Fialae1cfbc72016-08-11 23:51:28 +000075 SetOptionValue (uint32_t option_idx, const char *option_arg,
76 ExecutionContext *execution_context) override
Jim Inghama5a97eb2011-07-12 03:12:18 +000077 {
78 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000079 const int short_option = m_getopt_table[option_idx].val;
Jim Inghama5a97eb2011-07-12 03:12:18 +000080
81 switch (short_option)
82 {
83 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +000084 error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign);
Jim Inghama5a97eb2011-07-12 03:12:18 +000085 break;
86 case 's':
Enrico Granata7594f142013-06-17 22:51:50 +000087 if (option_arg && strcmp("end", option_arg) == 0)
88 {
89 m_start_idx.SetCurrentValue(UINT64_MAX);
90 m_start_idx.SetOptionWasSet();
91 }
92 else
Pavel Labathc95f7e22015-02-20 11:14:59 +000093 error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
Enrico Granata7594f142013-06-17 22:51:50 +000094 break;
95 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +000096 error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
Enrico Granata7594f142013-06-17 22:51:50 +000097 break;
Enrico Granata63123b62013-06-17 23:28:27 +000098 case 'C':
99 m_clear.SetCurrentValue(true);
100 m_clear.SetOptionWasSet();
Jim Inghama5a97eb2011-07-12 03:12:18 +0000101 break;
102 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000103 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Jim Inghama5a97eb2011-07-12 03:12:18 +0000104 break;
105 }
106
107 return error;
108 }
109
110 void
Todd Fialae1cfbc72016-08-11 23:51:28 +0000111 OptionParsingStarting (ExecutionContext *execution_context) override
Jim Inghama5a97eb2011-07-12 03:12:18 +0000112 {
Enrico Granata7594f142013-06-17 22:51:50 +0000113 m_start_idx.Clear();
114 m_stop_idx.Clear();
115 m_count.Clear();
Enrico Granata63123b62013-06-17 23:28:27 +0000116 m_clear.Clear();
Jim Inghama5a97eb2011-07-12 03:12:18 +0000117 }
118
119 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000120 GetDefinitions () override
Jim Inghama5a97eb2011-07-12 03:12:18 +0000121 {
122 return g_option_table;
123 }
124
125 // Options table: Required for subclasses of Options.
126
127 static OptionDefinition g_option_table[];
128
129 // Instance variables to hold the values for command options.
130
Enrico Granata7594f142013-06-17 22:51:50 +0000131 OptionValueUInt64 m_start_idx;
132 OptionValueUInt64 m_stop_idx;
133 OptionValueUInt64 m_count;
Enrico Granata63123b62013-06-17 23:28:27 +0000134 OptionValueBoolean m_clear;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000135 };
136
Jim Inghama5a97eb2011-07-12 03:12:18 +0000137 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000138 DoExecute (Args& command, CommandReturnObject &result) override
Jim Inghama5a97eb2011-07-12 03:12:18 +0000139 {
Enrico Granata63123b62013-06-17 23:28:27 +0000140 if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet())
Enrico Granata7594f142013-06-17 22:51:50 +0000141 {
142 m_interpreter.GetCommandHistory().Clear();
143 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
144 }
145 else
146 {
147 if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet())
148 {
149 result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation");
150 result.SetStatus(lldb::eReturnStatusFailed);
151 }
152 else
153 {
Virgile Bello84400ec2013-08-27 16:22:29 +0000154 std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue());
155 std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue());
156 std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue());
Enrico Granata7594f142013-06-17 22:51:50 +0000157
158 const CommandHistory& history(m_interpreter.GetCommandHistory());
159
160 if (start_idx.first && start_idx.second == UINT64_MAX)
161 {
162 if (count.first)
163 {
164 start_idx.second = history.GetSize() - count.second;
165 stop_idx.second = history.GetSize() - 1;
166 }
167 else if (stop_idx.first)
168 {
169 start_idx.second = stop_idx.second;
170 stop_idx.second = history.GetSize() - 1;
171 }
172 else
173 {
174 start_idx.second = 0;
175 stop_idx.second = history.GetSize() - 1;
176 }
177 }
178 else
179 {
180 if (!start_idx.first && !stop_idx.first && !count.first)
181 {
182 start_idx.second = 0;
183 stop_idx.second = history.GetSize() - 1;
184 }
185 else if (start_idx.first)
186 {
187 if (count.first)
188 {
189 stop_idx.second = start_idx.second + count.second - 1;
190 }
191 else if (!stop_idx.first)
192 {
193 stop_idx.second = history.GetSize() - 1;
194 }
195 }
196 else if (stop_idx.first)
197 {
198 if (count.first)
199 {
200 if (stop_idx.second >= count.second)
201 start_idx.second = stop_idx.second - count.second + 1;
202 else
203 start_idx.second = 0;
204 }
205 }
206 else /* if (count.first) */
207 {
208 start_idx.second = 0;
209 stop_idx.second = count.second - 1;
210 }
211 }
212 history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second);
213 }
214 }
Jim Inghama5a97eb2011-07-12 03:12:18 +0000215 return result.Succeeded();
216
217 }
Jim Ingham5a988412012-06-08 21:56:10 +0000218
219 CommandOptions m_options;
Jim Inghama5a97eb2011-07-12 03:12:18 +0000220};
221
222OptionDefinition
223CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
224{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000225{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
226{ 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)."},
227{ LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
228{ LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history."},
229{ 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Jim Inghama5a97eb2011-07-12 03:12:18 +0000230};
231
Jim Inghama5a97eb2011-07-12 03:12:18 +0000232//-------------------------------------------------------------------------
233// CommandObjectCommandsSource
234//-------------------------------------------------------------------------
235
Jim Ingham5a988412012-06-08 21:56:10 +0000236class CommandObjectCommandsSource : public CommandObjectParsed
Jim Inghamebc09c32010-07-07 03:36:20 +0000237{
Jim Ingham5a988412012-06-08 21:56:10 +0000238public:
Kate Stone7428a182016-07-14 22:03:10 +0000239 CommandObjectCommandsSource(CommandInterpreter &interpreter)
240 : CommandObjectParsed(interpreter, "command source", "Read and execute LLDB commands from the file <filename>.",
241 nullptr),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000242 m_options()
Jim Ingham5a988412012-06-08 21:56:10 +0000243 {
244 CommandArgumentEntry arg;
245 CommandArgumentData file_arg;
246
247 // Define the first (and only) variant of this arg.
248 file_arg.arg_type = eArgTypeFilename;
249 file_arg.arg_repetition = eArgRepeatPlain;
250
251 // There is only one variant this argument could be; put it into the argument entry.
252 arg.push_back (file_arg);
253
254 // Push the data for the first argument into the m_arguments vector.
255 m_arguments.push_back (arg);
256 }
257
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000258 ~CommandObjectCommandsSource() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000259
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000260 const char*
261 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Jim Ingham5a988412012-06-08 21:56:10 +0000262 {
263 return "";
264 }
265
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000266 int
Jim Ingham5a988412012-06-08 21:56:10 +0000267 HandleArgumentCompletion (Args &input,
268 int &cursor_index,
269 int &cursor_char_position,
270 OptionElementVector &opt_element_vector,
271 int match_start_point,
272 int max_return_elements,
273 bool &word_complete,
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000274 StringList &matches) override
Jim Ingham5a988412012-06-08 21:56:10 +0000275 {
276 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
277 completion_str.erase (cursor_char_position);
Todd Fialae1cfbc72016-08-11 23:51:28 +0000278
279 CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000280 CommandCompletions::eDiskFileCompletion,
281 completion_str.c_str(),
282 match_start_point,
283 max_return_elements,
284 nullptr,
285 word_complete,
286 matches);
Jim Ingham5a988412012-06-08 21:56:10 +0000287 return matches.GetSize();
288 }
289
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000290 Options *
291 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +0000292 {
293 return &m_options;
294 }
295
296protected:
Jim Inghame16c50a2011-02-18 00:54:25 +0000297 class CommandOptions : public Options
298 {
299 public:
Todd Fialae1cfbc72016-08-11 23:51:28 +0000300 CommandOptions() :
301 Options(),
Greg Clayton340b0302014-02-05 17:57:57 +0000302 m_stop_on_error (true),
303 m_silent_run (false),
304 m_stop_on_continue (true)
Greg Claytoneb0103f2011-04-07 22:46:35 +0000305 {
306 }
Jim Inghame16c50a2011-02-18 00:54:25 +0000307
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000308 ~CommandOptions() override = default;
Jim Inghame16c50a2011-02-18 00:54:25 +0000309
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000310 Error
Todd Fialae1cfbc72016-08-11 23:51:28 +0000311 SetOptionValue (uint32_t option_idx, const char *option_arg,
312 ExecutionContext *execution_context) override
Jim Inghame16c50a2011-02-18 00:54:25 +0000313 {
314 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000315 const int short_option = m_getopt_table[option_idx].val;
Jim Inghame16c50a2011-02-18 00:54:25 +0000316
317 switch (short_option)
318 {
319 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000320 error = m_stop_on_error.SetValueFromString(option_arg);
Jim Inghame16c50a2011-02-18 00:54:25 +0000321 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000322
Jim Inghame16c50a2011-02-18 00:54:25 +0000323 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000324 error = m_stop_on_continue.SetValueFromString(option_arg);
Jim Inghame16c50a2011-02-18 00:54:25 +0000325 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000326
Michael Sartain60986172013-07-09 23:22:53 +0000327 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000328 error = m_silent_run.SetValueFromString(option_arg);
Michael Sartain60986172013-07-09 23:22:53 +0000329 break;
Greg Clayton340b0302014-02-05 17:57:57 +0000330
Jim Inghame16c50a2011-02-18 00:54:25 +0000331 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000332 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Jim Inghame16c50a2011-02-18 00:54:25 +0000333 break;
334 }
335
336 return error;
337 }
338
339 void
Todd Fialae1cfbc72016-08-11 23:51:28 +0000340 OptionParsingStarting (ExecutionContext *execution_context) override
Jim Inghame16c50a2011-02-18 00:54:25 +0000341 {
Enrico Granata012d4fc2013-06-11 01:26:35 +0000342 m_stop_on_error.Clear();
Greg Clayton340b0302014-02-05 17:57:57 +0000343 m_silent_run.Clear();
344 m_stop_on_continue.Clear();
Jim Inghame16c50a2011-02-18 00:54:25 +0000345 }
346
Greg Claytone0d378b2011-03-24 21:19:54 +0000347 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000348 GetDefinitions () override
Jim Inghame16c50a2011-02-18 00:54:25 +0000349 {
350 return g_option_table;
351 }
352
353 // Options table: Required for subclasses of Options.
354
Greg Claytone0d378b2011-03-24 21:19:54 +0000355 static OptionDefinition g_option_table[];
Jim Inghame16c50a2011-02-18 00:54:25 +0000356
357 // Instance variables to hold the values for command options.
358
Enrico Granata012d4fc2013-06-11 01:26:35 +0000359 OptionValueBoolean m_stop_on_error;
Jim Ingham7d8555c2014-11-18 19:12:13 +0000360 OptionValueBoolean m_silent_run;
Greg Clayton340b0302014-02-05 17:57:57 +0000361 OptionValueBoolean m_stop_on_continue;
Jim Inghame16c50a2011-02-18 00:54:25 +0000362 };
363
Jim Inghamebc09c32010-07-07 03:36:20 +0000364 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000365 DoExecute(Args& command, CommandReturnObject &result) override
Jim Inghamebc09c32010-07-07 03:36:20 +0000366 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000367 const size_t argc = command.GetArgumentCount();
Jim Inghamebc09c32010-07-07 03:36:20 +0000368 if (argc == 1)
369 {
Jim Ingham5a988412012-06-08 21:56:10 +0000370 const char *filename = command.GetArgumentAtIndex(0);
Jim Inghamebc09c32010-07-07 03:36:20 +0000371
Johnny Chen1ee38532010-10-20 21:40:50 +0000372 FileSpec cmd_file (filename, true);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000373 ExecutionContext *exe_ctx = nullptr; // Just use the default context.
Greg Clayton340b0302014-02-05 17:57:57 +0000374
375 // If any options were set, then use them
376 if (m_options.m_stop_on_error.OptionWasSet() ||
377 m_options.m_silent_run.OptionWasSet() ||
378 m_options.m_stop_on_continue.OptionWasSet())
379 {
380 // Use user set settings
Jim Ingham26c7bf92014-10-11 00:38:27 +0000381 CommandInterpreterRunOptions options;
382 options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
383 options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue());
Jim Ingham7d8555c2014-11-18 19:12:13 +0000384 options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue());
385 options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue());
Jim Ingham26c7bf92014-10-11 00:38:27 +0000386
Greg Clayton340b0302014-02-05 17:57:57 +0000387 m_interpreter.HandleCommandsFromFile (cmd_file,
388 exe_ctx,
Jim Ingham26c7bf92014-10-11 00:38:27 +0000389 options,
Greg Clayton340b0302014-02-05 17:57:57 +0000390 result);
Greg Clayton340b0302014-02-05 17:57:57 +0000391 }
392 else
393 {
394 // No options were set, inherit any settings from nested "command source" commands,
395 // or set to sane default settings...
Jim Ingham26c7bf92014-10-11 00:38:27 +0000396 CommandInterpreterRunOptions options;
Greg Clayton340b0302014-02-05 17:57:57 +0000397 m_interpreter.HandleCommandsFromFile (cmd_file,
398 exe_ctx,
Jim Ingham26c7bf92014-10-11 00:38:27 +0000399 options,
Greg Clayton340b0302014-02-05 17:57:57 +0000400 result);
Greg Clayton340b0302014-02-05 17:57:57 +0000401 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000402 }
403 else
404 {
405 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
406 result.SetStatus (eReturnStatusFailed);
407 }
408 return result.Succeeded();
Jim Inghamebc09c32010-07-07 03:36:20 +0000409 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000410
Jim Ingham5a988412012-06-08 21:56:10 +0000411 CommandOptions m_options;
Jim Inghamebc09c32010-07-07 03:36:20 +0000412};
413
Greg Claytone0d378b2011-03-24 21:19:54 +0000414OptionDefinition
Jim Inghame16c50a2011-02-18 00:54:25 +0000415CommandObjectCommandsSource::CommandOptions::g_option_table[] =
416{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000417{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
418{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
419{ LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
420{ 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Jim Inghame16c50a2011-02-18 00:54:25 +0000421};
422
Jim Inghamebc09c32010-07-07 03:36:20 +0000423#pragma mark CommandObjectCommandsAlias
424//-------------------------------------------------------------------------
425// CommandObjectCommandsAlias
426//-------------------------------------------------------------------------
427
Enrico Granatabe93a352011-08-16 16:49:25 +0000428static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
429 "You must define a Python function with this signature:\n"
Greg Clayton44d93782014-01-27 23:43:24 +0000430 "def my_command_impl(debugger, args, result, internal_dict):\n";
Enrico Granatabe93a352011-08-16 16:49:25 +0000431
Jim Ingham5a988412012-06-08 21:56:10 +0000432class CommandObjectCommandsAlias : public CommandObjectRaw
Jim Inghamebc09c32010-07-07 03:36:20 +0000433{
Enrico Granata45d0e232016-03-31 01:10:54 +0000434protected:
435 class CommandOptions : public OptionGroup
436 {
437 public:
438 CommandOptions () :
439 OptionGroup(),
440 m_help(),
441 m_long_help()
442 {}
443
444 ~CommandOptions() override = default;
445
446 uint32_t
447 GetNumDefinitions () override
448 {
449 return 3;
450 }
451
452 const OptionDefinition*
453 GetDefinitions () override
454 {
455 return g_option_table;
456 }
457
458 Error
Todd Fialae1cfbc72016-08-11 23:51:28 +0000459 SetOptionValue (uint32_t option_idx,
460 const char *option_value,
461 ExecutionContext *execution_context) override
Enrico Granata45d0e232016-03-31 01:10:54 +0000462 {
463 Error error;
464
465 const int short_option = g_option_table[option_idx].short_option;
466
467 switch (short_option)
468 {
469 case 'h':
470 m_help.SetCurrentValue(option_value);
471 m_help.SetOptionWasSet();
472 break;
473
474 case 'H':
475 m_long_help.SetCurrentValue(option_value);
476 m_long_help.SetOptionWasSet();
477 break;
478
479 default:
480 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
481 break;
482 }
483
484 return error;
485 }
486
487 void
Todd Fialae1cfbc72016-08-11 23:51:28 +0000488 OptionParsingStarting (ExecutionContext *execution_context) override
Enrico Granata45d0e232016-03-31 01:10:54 +0000489 {
490 m_help.Clear();
491 m_long_help.Clear();
492 }
493
494 // Options table: Required for subclasses of Options.
495
496 static OptionDefinition g_option_table[];
497 OptionValueString m_help;
498 OptionValueString m_long_help;
499 };
500
501 OptionGroupOptions m_option_group;
502 CommandOptions m_command_options;
503
Jim Inghamebc09c32010-07-07 03:36:20 +0000504public:
Enrico Granata45d0e232016-03-31 01:10:54 +0000505 Options *
506 GetOptions () override
507 {
508 return &m_option_group;
509 }
510
Kate Stone7428a182016-07-14 22:03:10 +0000511 CommandObjectCommandsAlias(CommandInterpreter &interpreter)
512 : CommandObjectRaw(interpreter, "command alias", "Define a custom command in terms of an existing command.",
513 nullptr),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000514 m_option_group(),
Kate Stone7428a182016-07-14 22:03:10 +0000515 m_command_options()
Jim Inghamebc09c32010-07-07 03:36:20 +0000516 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000517 m_option_group.Append(&m_command_options);
518 m_option_group.Finalize();
519
Jim Inghamebc09c32010-07-07 03:36:20 +0000520 SetHelpLong(
Kate Stoneea671fb2015-07-14 05:48:36 +0000521"'alias' allows the user to create a short-cut or abbreviation for long \
522commands, multi-word commands, and commands that take particular options. \
523Below are some simple examples of how one might use the 'alias' command:" R"(
524
525(lldb) command alias sc script
526
527 Creates the abbreviation 'sc' for the 'script' command.
528
529(lldb) command alias bp breakpoint
530
531)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
532breakpoint commands are two-word commands, the user would still need to \
533enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
534
535(lldb) command alias bpl breakpoint list
536
537 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
538
539)" "An alias can include some options for the command, with the values either \
540filled in at the time the alias is created, or specified as positional \
541arguments, to be filled in when the alias is invoked. The following example \
542shows how to create aliases with options:" R"(
543
544(lldb) command alias bfl breakpoint set -f %1 -l %2
545
546)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
547options already part of the alias. So if the user wants to set a breakpoint \
548by file and line without explicitly having to use the -f and -l options, the \
549user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
550for the actual arguments that will be passed when the alias command is used. \
551The number in the placeholder refers to the position/order the actual value \
552occupies when the alias is used. All the occurrences of '%1' in the alias \
553will be replaced with the first argument, all the occurrences of '%2' in the \
554alias will be replaced with the second argument, and so on. This also allows \
555actual arguments to be used multiple times within an alias (see 'process \
556launch' example below)." R"(
557
558)" "Note: the positional arguments must substitute as whole words in the resultant \
559command, so you can't at present do something like this to append the file extension \
560\".cpp\":" R"(
561
562(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
563
564)" "For more complex aliasing, use the \"command regex\" command instead. In the \
565'bfl' case above, the actual file value will be filled in with the first argument \
566following 'bfl' and the actual line number value will be filled in with the second \
567argument. The user would use this alias as follows:" R"(
568
569(lldb) command alias bfl breakpoint set -f %1 -l %2
570(lldb) bfl my-file.c 137
571
572This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
573
574Another example:
575
576(lldb) command alias pltty process launch -s -o %1 -e %1
577(lldb) pltty /dev/tty0
578
579 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
580
581)" "If the user always wanted to pass the same value to a particular option, the \
582alias could be defined with that value directly in the alias as a constant, \
583rather than using a positional placeholder:" R"(
584
585(lldb) command alias bl3 breakpoint set -f %1 -l 3
586
587 Always sets a breakpoint on line 3 of whatever file is indicated.)"
588 );
Jim Inghamebc09c32010-07-07 03:36:20 +0000589
Caroline Tice405fe672010-10-04 22:28:36 +0000590 CommandArgumentEntry arg1;
591 CommandArgumentEntry arg2;
592 CommandArgumentEntry arg3;
593 CommandArgumentData alias_arg;
594 CommandArgumentData cmd_arg;
595 CommandArgumentData options_arg;
596
597 // Define the first (and only) variant of this arg.
598 alias_arg.arg_type = eArgTypeAliasName;
599 alias_arg.arg_repetition = eArgRepeatPlain;
600
601 // There is only one variant this argument could be; put it into the argument entry.
602 arg1.push_back (alias_arg);
603
604 // Define the first (and only) variant of this arg.
605 cmd_arg.arg_type = eArgTypeCommandName;
606 cmd_arg.arg_repetition = eArgRepeatPlain;
607
608 // There is only one variant this argument could be; put it into the argument entry.
609 arg2.push_back (cmd_arg);
610
611 // Define the first (and only) variant of this arg.
612 options_arg.arg_type = eArgTypeAliasOptions;
613 options_arg.arg_repetition = eArgRepeatOptional;
614
615 // There is only one variant this argument could be; put it into the argument entry.
616 arg3.push_back (options_arg);
617
618 // Push the data for the first argument into the m_arguments vector.
619 m_arguments.push_back (arg1);
620 m_arguments.push_back (arg2);
621 m_arguments.push_back (arg3);
Jim Inghamebc09c32010-07-07 03:36:20 +0000622 }
623
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000624 ~CommandObjectCommandsAlias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000625
Jim Ingham5a988412012-06-08 21:56:10 +0000626protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000627 bool
628 DoExecute (const char *raw_command_line, CommandReturnObject &result) override
Caroline Tice844d2302010-12-09 22:52:49 +0000629 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000630 if (!raw_command_line || !raw_command_line[0])
631 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000632 result.AppendError ("'command alias' requires at least two arguments");
Enrico Granata45d0e232016-03-31 01:10:54 +0000633 return false;
634 }
Todd Fialae1cfbc72016-08-11 23:51:28 +0000635
636 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
637 m_option_group.NotifyOptionParsingStarting(&exe_ctx);
Enrico Granata45d0e232016-03-31 01:10:54 +0000638
639 const char * remainder = nullptr;
640
641 if (raw_command_line[0] == '-')
642 {
643 // We have some options and these options MUST end with --.
644 const char *end_options = nullptr;
645 const char *s = raw_command_line;
646 while (s && s[0])
647 {
648 end_options = ::strstr (s, "--");
649 if (end_options)
650 {
651 end_options += 2; // Get past the "--"
652 if (::isspace (end_options[0]))
653 {
654 remainder = end_options;
655 while (::isspace (*remainder))
656 ++remainder;
657 break;
658 }
659 }
660 s = end_options;
661 }
662
663 if (end_options)
664 {
665 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
666 if (!ParseOptions (args, result))
667 return false;
668
Todd Fialae1cfbc72016-08-11 23:51:28 +0000669 Error error (m_option_group.NotifyOptionParsingFinished(&exe_ctx));
Enrico Granata45d0e232016-03-31 01:10:54 +0000670 if (error.Fail())
671 {
672 result.AppendError (error.AsCString());
673 result.SetStatus (eReturnStatusFailed);
674 return false;
675 }
676 }
677 }
678 if (nullptr == remainder)
679 remainder = raw_command_line;
680
681 std::string raw_command_string (remainder);
682 Args args (raw_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +0000683
684 size_t argc = args.GetArgumentCount();
685
686 if (argc < 2)
687 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000688 result.AppendError ("'command alias' requires at least two arguments");
Caroline Tice844d2302010-12-09 22:52:49 +0000689 result.SetStatus (eReturnStatusFailed);
690 return false;
691 }
692
693 // Get the alias command.
694
695 const std::string alias_command = args.GetArgumentAtIndex (0);
Enrico Granatad72e4122016-04-08 17:56:57 +0000696 if (alias_command.size() > 1 &&
697 alias_command[0] == '-')
698 {
699 result.AppendError("aliases starting with a dash are not supported");
700 if (alias_command == "--help" || alias_command == "--long-help")
701 {
702 result.AppendWarning("if trying to pass options to 'command alias' add a -- at the end of the options");
703 }
704 result.SetStatus (eReturnStatusFailed);
705 return false;
706 }
Enrico Granatabe93a352011-08-16 16:49:25 +0000707
Caroline Tice844d2302010-12-09 22:52:49 +0000708 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
709 // does the stripping itself.
710 size_t pos = raw_command_string.find (alias_command);
711 if (pos == 0)
712 {
713 raw_command_string = raw_command_string.substr (alias_command.size());
714 pos = raw_command_string.find_first_not_of (' ');
715 if ((pos != std::string::npos) && (pos > 0))
716 raw_command_string = raw_command_string.substr (pos);
717 }
718 else
719 {
720 result.AppendError ("Error parsing command string. No alias created.");
721 result.SetStatus (eReturnStatusFailed);
722 return false;
723 }
724
725
726 // Verify that the command is alias-able.
727 if (m_interpreter.CommandExists (alias_command.c_str()))
728 {
729 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
730 alias_command.c_str());
731 result.SetStatus (eReturnStatusFailed);
732 return false;
733 }
734
735 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
736 // raw_command_string is returned with the name of the command object stripped off the front.
Enrico Granatad72e4122016-04-08 17:56:57 +0000737 std::string original_raw_command_string(raw_command_string);
Caroline Tice844d2302010-12-09 22:52:49 +0000738 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
739
740 if (!cmd_obj)
741 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000742 result.AppendErrorWithFormat ("invalid command given to 'command alias'. '%s' does not begin with a valid command."
743 " No alias created.", original_raw_command_string.c_str());
Caroline Tice844d2302010-12-09 22:52:49 +0000744 result.SetStatus (eReturnStatusFailed);
745 return false;
746 }
747 else if (!cmd_obj->WantsRawCommandString ())
748 {
749 // Note that args was initialized with the original command, and has not been updated to this point.
750 // 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 +0000751 return HandleAliasingNormalCommand (args, result);
Caroline Tice844d2302010-12-09 22:52:49 +0000752 }
753 else
754 {
Jim Ingham5a988412012-06-08 21:56:10 +0000755 return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result);
756 }
757 return result.Succeeded();
758 }
759
760 bool
761 HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result)
762 {
Caroline Tice844d2302010-12-09 22:52:49 +0000763 // Verify & handle any options/arguments passed to the alias command
764
765 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
Enrico Granata5e550302016-03-08 03:00:27 +0000766
Enrico Granata212130a2016-03-08 05:37:15 +0000767 if (CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false))
768 {
769 if (m_interpreter.AliasExists (alias_command.c_str())
770 || m_interpreter.UserCommandExists (alias_command.c_str()))
771 {
772 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
773 alias_command.c_str());
774 }
Enrico Granata45d0e232016-03-31 01:10:54 +0000775 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 +0000776 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000777 if (m_command_options.m_help.OptionWasSet())
778 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
779 if (m_command_options.m_long_help.OptionWasSet())
780 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
Enrico Granata212130a2016-03-08 05:37:15 +0000781 result.SetStatus (eReturnStatusSuccessFinishNoResult);
782 }
783 else
784 {
785 result.AppendError ("Unable to create requested alias.\n");
786 result.SetStatus (eReturnStatusFailed);
787 }
Caroline Ticeca90c472011-05-06 21:37:15 +0000788
Caroline Tice472362e2010-12-14 18:51:39 +0000789 }
790 else
791 {
792 result.AppendError ("Unable to create requested alias.\n");
793 result.SetStatus (eReturnStatusFailed);
794 }
Enrico Granata212130a2016-03-08 05:37:15 +0000795
Jim Ingham5a988412012-06-08 21:56:10 +0000796 return result.Succeeded ();
Caroline Tice844d2302010-12-09 22:52:49 +0000797 }
Jim Ingham5a988412012-06-08 21:56:10 +0000798
Jim Inghamebc09c32010-07-07 03:36:20 +0000799 bool
Jim Ingham5a988412012-06-08 21:56:10 +0000800 HandleAliasingNormalCommand (Args& args, CommandReturnObject &result)
Jim Inghamebc09c32010-07-07 03:36:20 +0000801 {
Caroline Tice867b185d2010-09-21 23:25:40 +0000802 size_t argc = args.GetArgumentCount();
Jim Inghamebc09c32010-07-07 03:36:20 +0000803
804 if (argc < 2)
Greg Claytonc982c762010-07-09 20:39:50 +0000805 {
Enrico Granatad72e4122016-04-08 17:56:57 +0000806 result.AppendError ("'command alias' requires at least two arguments");
Jim Inghamebc09c32010-07-07 03:36:20 +0000807 result.SetStatus (eReturnStatusFailed);
808 return false;
Greg Claytonc982c762010-07-09 20:39:50 +0000809 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000810
811 const std::string alias_command = args.GetArgumentAtIndex(0);
812 const std::string actual_command = args.GetArgumentAtIndex(1);
813
814 args.Shift(); // Shift the alias command word off the argument vector.
815 args.Shift(); // Shift the old command word off the argument vector.
816
817 // Verify that the command is alias'able, and get the appropriate command object.
818
Greg Claytona7015092010-09-18 01:14:36 +0000819 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Inghamebc09c32010-07-07 03:36:20 +0000820 {
821 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
822 alias_command.c_str());
823 result.SetStatus (eReturnStatusFailed);
824 }
825 else
826 {
Greg Claytona7015092010-09-18 01:14:36 +0000827 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Inghamebc09c32010-07-07 03:36:20 +0000828 CommandObjectSP subcommand_obj_sp;
829 bool use_subcommand = false;
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000830 if (command_obj_sp)
Jim Inghamebc09c32010-07-07 03:36:20 +0000831 {
832 CommandObject *cmd_obj = command_obj_sp.get();
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000833 CommandObject *sub_cmd_obj = nullptr;
Jim Inghamebc09c32010-07-07 03:36:20 +0000834 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
Jim Inghamebc09c32010-07-07 03:36:20 +0000835
Caroline Tice844d2302010-12-09 22:52:49 +0000836 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Inghamebc09c32010-07-07 03:36:20 +0000837 {
838 if (argc >= 3)
839 {
840 const std::string sub_command = args.GetArgumentAtIndex(0);
841 assert (sub_command.length() != 0);
Greg Clayton998255b2012-10-13 02:07:45 +0000842 subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str());
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000843 if (subcommand_obj_sp)
Jim Inghamebc09c32010-07-07 03:36:20 +0000844 {
845 sub_cmd_obj = subcommand_obj_sp.get();
846 use_subcommand = true;
847 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Tice844d2302010-12-09 22:52:49 +0000848 cmd_obj = sub_cmd_obj;
Jim Inghamebc09c32010-07-07 03:36:20 +0000849 }
850 else
851 {
Caroline Ticef415eeb2010-11-02 19:00:04 +0000852 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
853 "Unable to create alias.\n",
854 sub_command.c_str(), actual_command.c_str());
Jim Inghamebc09c32010-07-07 03:36:20 +0000855 result.SetStatus (eReturnStatusFailed);
856 return false;
857 }
858 }
859 }
860
861 // Verify & handle any options/arguments passed to the alias command
862
Enrico Granata212130a2016-03-08 05:37:15 +0000863 std::string args_string;
864
Jim Inghamebc09c32010-07-07 03:36:20 +0000865 if (args.GetArgumentCount () > 0)
866 {
Caroline Ticeca90c472011-05-06 21:37:15 +0000867 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
868 if (use_subcommand)
869 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
870
Caroline Ticeca90c472011-05-06 21:37:15 +0000871 args.GetCommandString (args_string);
Jim Inghamebc09c32010-07-07 03:36:20 +0000872 }
Enrico Granata212130a2016-03-08 05:37:15 +0000873
Greg Claytona7015092010-09-18 01:14:36 +0000874 if (m_interpreter.AliasExists (alias_command.c_str())
875 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Inghamebc09c32010-07-07 03:36:20 +0000876 {
Enrico Granata212130a2016-03-08 05:37:15 +0000877 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
Jim Inghamebc09c32010-07-07 03:36:20 +0000878 alias_command.c_str());
879 }
Enrico Granata212130a2016-03-08 05:37:15 +0000880
Enrico Granata45d0e232016-03-31 01:10:54 +0000881 if (CommandAlias *alias = m_interpreter.AddAlias(alias_command.c_str(),
882 use_subcommand ? subcommand_obj_sp : command_obj_sp,
883 args_string.c_str()))
Enrico Granata212130a2016-03-08 05:37:15 +0000884 {
Enrico Granata45d0e232016-03-31 01:10:54 +0000885 if (m_command_options.m_help.OptionWasSet())
886 alias->SetHelp(m_command_options.m_help.GetCurrentValue());
887 if (m_command_options.m_long_help.OptionWasSet())
888 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue());
Enrico Granata212130a2016-03-08 05:37:15 +0000889 result.SetStatus (eReturnStatusSuccessFinishNoResult);
890 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000891 else
Enrico Granata212130a2016-03-08 05:37:15 +0000892 {
893 result.AppendError ("Unable to create requested alias.\n");
894 result.SetStatus (eReturnStatusFailed);
895 return false;
896 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000897 }
898 else
899 {
900 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
901 result.SetStatus (eReturnStatusFailed);
Caroline Ticee7941792010-10-28 23:17:48 +0000902 return false;
Jim Inghamebc09c32010-07-07 03:36:20 +0000903 }
904 }
905
906 return result.Succeeded();
907 }
908};
909
Enrico Granata45d0e232016-03-31 01:10:54 +0000910OptionDefinition
911CommandObjectCommandsAlias::CommandOptions::g_option_table[] =
912{
913 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command"},
914 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command"},
915 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
916};
917
Jim Inghamebc09c32010-07-07 03:36:20 +0000918#pragma mark CommandObjectCommandsUnalias
919//-------------------------------------------------------------------------
920// CommandObjectCommandsUnalias
921//-------------------------------------------------------------------------
922
Jim Ingham5a988412012-06-08 21:56:10 +0000923class CommandObjectCommandsUnalias : public CommandObjectParsed
Jim Inghamebc09c32010-07-07 03:36:20 +0000924{
925public:
Kate Stone7428a182016-07-14 22:03:10 +0000926 CommandObjectCommandsUnalias(CommandInterpreter &interpreter)
927 : CommandObjectParsed(interpreter, "command unalias",
928 "Delete one or more custom commands defined by 'command alias'.", nullptr)
Jim Inghamebc09c32010-07-07 03:36:20 +0000929 {
Caroline Tice405fe672010-10-04 22:28:36 +0000930 CommandArgumentEntry arg;
931 CommandArgumentData alias_arg;
932
933 // Define the first (and only) variant of this arg.
934 alias_arg.arg_type = eArgTypeAliasName;
935 alias_arg.arg_repetition = eArgRepeatPlain;
936
937 // There is only one variant this argument could be; put it into the argument entry.
938 arg.push_back (alias_arg);
939
940 // Push the data for the first argument into the m_arguments vector.
941 m_arguments.push_back (arg);
Jim Inghamebc09c32010-07-07 03:36:20 +0000942 }
943
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000944 ~CommandObjectCommandsUnalias() override = default;
Jim Inghamebc09c32010-07-07 03:36:20 +0000945
Jim Ingham5a988412012-06-08 21:56:10 +0000946protected:
Jim Inghamebc09c32010-07-07 03:36:20 +0000947 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000948 DoExecute (Args& args, CommandReturnObject &result) override
Jim Inghamebc09c32010-07-07 03:36:20 +0000949 {
950 CommandObject::CommandMap::iterator pos;
951 CommandObject *cmd_obj;
952
953 if (args.GetArgumentCount() != 0)
954 {
955 const char *command_name = args.GetArgumentAtIndex(0);
Greg Claytona7015092010-09-18 01:14:36 +0000956 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Inghamebc09c32010-07-07 03:36:20 +0000957 if (cmd_obj)
958 {
Greg Claytona7015092010-09-18 01:14:36 +0000959 if (m_interpreter.CommandExists (command_name))
Jim Inghamebc09c32010-07-07 03:36:20 +0000960 {
Greg Claytonb5472782015-01-09 19:08:20 +0000961 if (cmd_obj->IsRemovable())
962 {
963 result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n",
964 command_name);
965 }
966 else
967 {
968 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
969 command_name);
970 }
Jim Inghamebc09c32010-07-07 03:36:20 +0000971 result.SetStatus (eReturnStatusFailed);
972 }
973 else
974 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +0000975 if (!m_interpreter.RemoveAlias(command_name))
Jim Inghamebc09c32010-07-07 03:36:20 +0000976 {
Greg Claytona7015092010-09-18 01:14:36 +0000977 if (m_interpreter.AliasExists (command_name))
Jim Inghamebc09c32010-07-07 03:36:20 +0000978 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
979 command_name);
980 else
981 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
982 result.SetStatus (eReturnStatusFailed);
983 }
984 else
985 result.SetStatus (eReturnStatusSuccessFinishNoResult);
986 }
987 }
988 else
989 {
990 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
991 "current list of commands.\n",
992 command_name);
993 result.SetStatus (eReturnStatusFailed);
994 }
995 }
996 else
997 {
998 result.AppendError ("must call 'unalias' with a valid alias");
999 result.SetStatus (eReturnStatusFailed);
1000 }
1001
1002 return result.Succeeded();
1003 }
1004};
1005
Greg Claytonb5472782015-01-09 19:08:20 +00001006#pragma mark CommandObjectCommandsDelete
1007//-------------------------------------------------------------------------
1008// CommandObjectCommandsDelete
1009//-------------------------------------------------------------------------
1010
1011class CommandObjectCommandsDelete : public CommandObjectParsed
1012{
1013public:
Kate Stone7428a182016-07-14 22:03:10 +00001014 CommandObjectCommandsDelete(CommandInterpreter &interpreter)
1015 : CommandObjectParsed(interpreter, "command delete",
1016 "Delete one or more custom commands defined by 'command regex'.", nullptr)
Greg Claytonb5472782015-01-09 19:08:20 +00001017 {
1018 CommandArgumentEntry arg;
1019 CommandArgumentData alias_arg;
1020
1021 // Define the first (and only) variant of this arg.
1022 alias_arg.arg_type = eArgTypeCommandName;
1023 alias_arg.arg_repetition = eArgRepeatPlain;
1024
1025 // There is only one variant this argument could be; put it into the argument entry.
1026 arg.push_back (alias_arg);
1027
1028 // Push the data for the first argument into the m_arguments vector.
1029 m_arguments.push_back (arg);
1030 }
1031
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001032 ~CommandObjectCommandsDelete() override = default;
Greg Claytonb5472782015-01-09 19:08:20 +00001033
1034protected:
1035 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001036 DoExecute (Args& args, CommandReturnObject &result) override
Greg Claytonb5472782015-01-09 19:08:20 +00001037 {
1038 CommandObject::CommandMap::iterator pos;
1039
1040 if (args.GetArgumentCount() != 0)
1041 {
1042 const char *command_name = args.GetArgumentAtIndex(0);
1043 if (m_interpreter.CommandExists (command_name))
1044 {
1045 if (m_interpreter.RemoveCommand (command_name))
1046 {
1047 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1048 }
1049 else
1050 {
1051 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
1052 command_name);
1053 result.SetStatus (eReturnStatusFailed);
1054 }
1055 }
1056 else
1057 {
Enrico Granata46d4aa22016-02-29 23:22:53 +00001058 StreamString error_msg_stream;
1059 const bool generate_apropos = true;
1060 const bool generate_type_lookup = false;
1061 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
1062 command_name,
1063 nullptr,
1064 nullptr,
1065 generate_apropos,
1066 generate_type_lookup);
1067 result.AppendErrorWithFormat ("%s", error_msg_stream.GetData());
Greg Claytonb5472782015-01-09 19:08:20 +00001068 result.SetStatus (eReturnStatusFailed);
1069 }
1070 }
1071 else
1072 {
Kate Stone7428a182016-07-14 22:03:10 +00001073 result.AppendErrorWithFormat(
1074 "must call '%s' with one or more valid user defined regular expression command names",
1075 GetCommandName());
Greg Claytonb5472782015-01-09 19:08:20 +00001076 result.SetStatus (eReturnStatusFailed);
1077 }
1078
1079 return result.Succeeded();
1080 }
1081};
1082
Greg Claytonde164aa2011-04-20 16:37:46 +00001083//-------------------------------------------------------------------------
1084// CommandObjectCommandsAddRegex
1085//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001086#pragma mark CommandObjectCommandsAddRegex
Greg Claytonde164aa2011-04-20 16:37:46 +00001087
Greg Clayton44d93782014-01-27 23:43:24 +00001088class CommandObjectCommandsAddRegex :
1089 public CommandObjectParsed,
Greg Claytonea508632014-11-18 00:43:17 +00001090 public IOHandlerDelegateMultiline
Greg Claytonde164aa2011-04-20 16:37:46 +00001091{
1092public:
Kate Stone7428a182016-07-14 22:03:10 +00001093 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter)
1094 : CommandObjectParsed(interpreter, "command regex",
1095 "Define a custom command in terms of existing commands by matching regular expressions.",
1096 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
1097 IOHandlerDelegateMultiline("", IOHandlerDelegate::Completion::LLDBCommand),
Todd Fialae1cfbc72016-08-11 23:51:28 +00001098 m_options()
Greg Claytonde164aa2011-04-20 16:37:46 +00001099 {
Kate Stoneea671fb2015-07-14 05:48:36 +00001100 SetHelpLong(R"(
1101)" "This command allows the user to create powerful regular expression commands \
1102with substitutions. The regular expressions and substitutions are specified \
1103using the regular expression substitution format of:" R"(
1104
1105 s/<regex>/<subst>/
1106
1107)" "<regex> is a regular expression that can use parenthesis to capture regular \
1108expression input and substitute the captured matches in the output using %1 \
1109for the first match, %2 for the second, and so on." R"(
1110
1111)" "The regular expressions can all be specified on the command line if more than \
1112one argument is provided. If just the command name is provided on the command \
1113line, then the regular expressions and substitutions can be entered on separate \
1114lines, followed by an empty line to terminate the command definition." R"(
1115
1116EXAMPLES
1117
1118)" "The following example will define a regular expression command named 'f' that \
1119will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
1120a number follows 'f':" R"(
1121
1122 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
1123 );
Greg Claytonde164aa2011-04-20 16:37:46 +00001124 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001125
1126 ~CommandObjectCommandsAddRegex() override = default;
1127
Jim Ingham5a988412012-06-08 21:56:10 +00001128protected:
Greg Claytonea508632014-11-18 00:43:17 +00001129 void
1130 IOHandlerActivated (IOHandler &io_handler) override
Greg Clayton44d93782014-01-27 23:43:24 +00001131 {
1132 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1133 if (output_sp)
1134 {
1135 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");
1136 output_sp->Flush();
1137 }
1138 }
1139
Greg Claytonea508632014-11-18 00:43:17 +00001140 void
1141 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
Greg Clayton44d93782014-01-27 23:43:24 +00001142 {
1143 io_handler.SetIsDone(true);
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001144 if (m_regex_cmd_ap)
Greg Clayton44d93782014-01-27 23:43:24 +00001145 {
1146 StringList lines;
1147 if (lines.SplitIntoLines (data))
1148 {
1149 const size_t num_lines = lines.GetSize();
1150 bool check_only = false;
1151 for (size_t i=0; i<num_lines; ++i)
1152 {
Greg Clayton44d93782014-01-27 23:43:24 +00001153 llvm::StringRef bytes_strref (lines[i]);
1154 Error error = AppendRegexSubstitution (bytes_strref, check_only);
1155 if (error.Fail())
1156 {
1157 if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
1158 {
1159 StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream();
1160 out_stream->Printf("error: %s\n", error.AsCString());
1161 }
1162 }
1163 }
1164 }
1165 if (m_regex_cmd_ap->HasRegexEntries())
1166 {
1167 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1168 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1169 }
1170 }
1171 }
Greg Clayton44d93782014-01-27 23:43:24 +00001172
Greg Claytonde164aa2011-04-20 16:37:46 +00001173 bool
Eric Christopherb0a18142014-11-18 22:40:27 +00001174 DoExecute (Args& command, CommandReturnObject &result) override
Greg Claytonde164aa2011-04-20 16:37:46 +00001175 {
Jim Ingham5a988412012-06-08 21:56:10 +00001176 const size_t argc = command.GetArgumentCount();
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001177 if (argc == 0)
Greg Claytonde164aa2011-04-20 16:37:46 +00001178 {
Jason Molenda69c12cc2011-11-10 22:43:35 +00001179 result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001180 result.SetStatus (eReturnStatusFailed);
1181 }
1182 else
1183 {
1184 Error error;
Jim Ingham5a988412012-06-08 21:56:10 +00001185 const char *name = command.GetArgumentAtIndex(0);
Greg Claytonde164aa2011-04-20 16:37:46 +00001186 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
1187 name,
1188 m_options.GetHelp (),
1189 m_options.GetSyntax (),
Greg Claytonb5472782015-01-09 19:08:20 +00001190 10,
1191 0,
1192 true));
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001193
1194 if (argc == 1)
Greg Claytonde164aa2011-04-20 16:37:46 +00001195 {
Greg Clayton44d93782014-01-27 23:43:24 +00001196 Debugger &debugger = m_interpreter.GetDebugger();
Kate Stonee30f11d2014-11-17 19:06:59 +00001197 bool color_prompt = debugger.GetUseColor();
Greg Clayton44d93782014-01-27 23:43:24 +00001198 const bool multiple_lines = true; // Get multiple lines
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001199 IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
1200 IOHandler::Type::Other,
1201 "lldb-regex", // Name of input reader for history
1202 "> ", // Prompt
1203 nullptr, // Continuation prompt
1204 multiple_lines,
1205 color_prompt,
1206 0, // Don't show line numbers
1207 *this));
Greg Clayton44d93782014-01-27 23:43:24 +00001208
1209 if (io_handler_sp)
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001210 {
Greg Clayton44d93782014-01-27 23:43:24 +00001211 debugger.PushIOHandler(io_handler_sp);
1212 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Claytonde164aa2011-04-20 16:37:46 +00001213 }
1214 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001215 else
1216 {
1217 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
1218 {
Jim Ingham5a988412012-06-08 21:56:10 +00001219 llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
Greg Clayton44d93782014-01-27 23:43:24 +00001220 bool check_only = false;
1221 error = AppendRegexSubstitution (arg_strref, check_only);
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001222 if (error.Fail())
1223 break;
1224 }
1225
1226 if (error.Success())
1227 {
1228 AddRegexCommandToInterpreter();
1229 }
1230 }
1231 if (error.Fail())
1232 {
1233 result.AppendError (error.AsCString());
1234 result.SetStatus (eReturnStatusFailed);
1235 }
Greg Claytonde164aa2011-04-20 16:37:46 +00001236 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001237
Greg Claytonde164aa2011-04-20 16:37:46 +00001238 return result.Succeeded();
1239 }
1240
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001241 Error
Greg Clayton44d93782014-01-27 23:43:24 +00001242 AppendRegexSubstitution (const llvm::StringRef &regex_sed, bool check_only)
Greg Claytonde164aa2011-04-20 16:37:46 +00001243 {
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001244 Error error;
1245
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001246 if (!m_regex_cmd_ap)
Greg Claytonde164aa2011-04-20 16:37:46 +00001247 {
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001248 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
1249 (int)regex_sed.size(),
1250 regex_sed.data());
1251 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001252 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001253
1254 size_t regex_sed_size = regex_sed.size();
1255
1256 if (regex_sed_size <= 1)
1257 {
1258 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
1259 (int)regex_sed.size(),
1260 regex_sed.data());
1261 return error;
1262 }
1263
1264 if (regex_sed[0] != 's')
1265 {
1266 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
1267 (int)regex_sed.size(),
1268 regex_sed.data());
1269 return error;
1270 }
1271 const size_t first_separator_char_pos = 1;
1272 // use the char that follows 's' as the regex separator character
1273 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1274 const char separator_char = regex_sed[first_separator_char_pos];
1275 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
1276
1277 if (second_separator_char_pos == std::string::npos)
1278 {
Greg Claytonea508632014-11-18 00:43:17 +00001279 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'",
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001280 separator_char,
1281 (int)(regex_sed.size() - first_separator_char_pos - 1),
Greg Claytonea508632014-11-18 00:43:17 +00001282 regex_sed.data() + (first_separator_char_pos + 1),
1283 (int)regex_sed.size(),
1284 regex_sed.data());
1285 return error;
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001286 }
1287
1288 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
1289
1290 if (third_separator_char_pos == std::string::npos)
1291 {
Greg Claytonea508632014-11-18 00:43:17 +00001292 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'",
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001293 separator_char,
1294 (int)(regex_sed.size() - second_separator_char_pos - 1),
Greg Claytonea508632014-11-18 00:43:17 +00001295 regex_sed.data() + (second_separator_char_pos + 1),
1296 (int)regex_sed.size(),
1297 regex_sed.data());
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001298 return error;
1299 }
1300
1301 if (third_separator_char_pos != regex_sed_size - 1)
1302 {
1303 // Make sure that everything that follows the last regex
1304 // separator char
1305 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
1306 {
1307 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
1308 (int)third_separator_char_pos + 1,
1309 regex_sed.data(),
1310 (int)(regex_sed.size() - third_separator_char_pos - 1),
1311 regex_sed.data() + (third_separator_char_pos + 1));
1312 return error;
1313 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001314 }
1315 else if (first_separator_char_pos + 1 == second_separator_char_pos)
1316 {
1317 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1318 separator_char,
1319 separator_char,
1320 separator_char,
1321 (int)regex_sed.size(),
1322 regex_sed.data());
1323 return error;
1324 }
1325 else if (second_separator_char_pos + 1 == third_separator_char_pos)
1326 {
1327 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1328 separator_char,
1329 separator_char,
1330 separator_char,
1331 (int)regex_sed.size(),
1332 regex_sed.data());
1333 return error;
1334 }
Greg Clayton44d93782014-01-27 23:43:24 +00001335
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001336 if (!check_only)
Greg Clayton44d93782014-01-27 23:43:24 +00001337 {
1338 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
1339 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
1340 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
1341 subst.c_str());
1342 }
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001343 return error;
Greg Claytonde164aa2011-04-20 16:37:46 +00001344 }
1345
1346 void
Greg Clayton0e5e5a72011-04-20 22:55:21 +00001347 AddRegexCommandToInterpreter()
Greg Claytonde164aa2011-04-20 16:37:46 +00001348 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001349 if (m_regex_cmd_ap)
Greg Claytonde164aa2011-04-20 16:37:46 +00001350 {
1351 if (m_regex_cmd_ap->HasRegexEntries())
1352 {
1353 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1354 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1355 }
1356 }
1357 }
1358
Greg Claytonde164aa2011-04-20 16:37:46 +00001359private:
Greg Clayton7b0992d2013-04-18 22:45:39 +00001360 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
Greg Claytonde164aa2011-04-20 16:37:46 +00001361
1362 class CommandOptions : public Options
1363 {
1364 public:
Todd Fialae1cfbc72016-08-11 23:51:28 +00001365 CommandOptions() :
1366 Options()
Greg Claytonde164aa2011-04-20 16:37:46 +00001367 {
1368 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001369
1370 ~CommandOptions() override = default;
1371
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001372 Error
Todd Fialae1cfbc72016-08-11 23:51:28 +00001373 SetOptionValue (uint32_t option_idx, const char *option_arg,
1374 ExecutionContext *execution_context) override
Greg Claytonde164aa2011-04-20 16:37:46 +00001375 {
1376 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001377 const int short_option = m_getopt_table[option_idx].val;
Greg Claytonde164aa2011-04-20 16:37:46 +00001378
1379 switch (short_option)
1380 {
1381 case 'h':
1382 m_help.assign (option_arg);
1383 break;
1384 case 's':
1385 m_syntax.assign (option_arg);
1386 break;
Greg Claytonde164aa2011-04-20 16:37:46 +00001387 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001388 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Greg Claytonde164aa2011-04-20 16:37:46 +00001389 break;
1390 }
1391
1392 return error;
1393 }
1394
1395 void
Todd Fialae1cfbc72016-08-11 23:51:28 +00001396 OptionParsingStarting (ExecutionContext *execution_context) override
Greg Claytonde164aa2011-04-20 16:37:46 +00001397 {
1398 m_help.clear();
1399 m_syntax.clear();
1400 }
1401
1402 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001403 GetDefinitions () override
Greg Claytonde164aa2011-04-20 16:37:46 +00001404 {
1405 return g_option_table;
1406 }
1407
1408 // Options table: Required for subclasses of Options.
1409
1410 static OptionDefinition g_option_table[];
1411
1412 const char *
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001413 GetHelp()
Greg Claytonde164aa2011-04-20 16:37:46 +00001414 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001415 return (m_help.empty() ? nullptr : m_help.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001416 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001417
Greg Claytonde164aa2011-04-20 16:37:46 +00001418 const char *
1419 GetSyntax ()
1420 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001421 return (m_syntax.empty() ? nullptr : m_syntax.c_str());
Greg Claytonde164aa2011-04-20 16:37:46 +00001422 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001423
Greg Claytonde164aa2011-04-20 16:37:46 +00001424 protected:
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001425 // Instance variables to hold the values for command options.
1426
Greg Claytonde164aa2011-04-20 16:37:46 +00001427 std::string m_help;
1428 std::string m_syntax;
1429 };
Jim Ingham5a988412012-06-08 21:56:10 +00001430
Eric Christopherb0a18142014-11-18 22:40:27 +00001431 Options *
1432 GetOptions () override
Greg Claytonde164aa2011-04-20 16:37:46 +00001433 {
1434 return &m_options;
1435 }
Jim Ingham5a988412012-06-08 21:56:10 +00001436
1437 CommandOptions m_options;
Greg Claytonde164aa2011-04-20 16:37:46 +00001438};
1439
Greg Claytonde164aa2011-04-20 16:37:46 +00001440OptionDefinition
1441CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1442{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001443{ LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."},
1444{ LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1445{ 0 , false, nullptr , 0 , 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr }
Greg Claytonde164aa2011-04-20 16:37:46 +00001446};
1447
Jim Ingham5a988412012-06-08 21:56:10 +00001448class CommandObjectPythonFunction : public CommandObjectRaw
Enrico Granata223383e2011-08-16 23:24:13 +00001449{
Enrico Granata223383e2011-08-16 23:24:13 +00001450public:
Enrico Granata223383e2011-08-16 23:24:13 +00001451 CommandObjectPythonFunction (CommandInterpreter &interpreter,
1452 std::string name,
Enrico Granata0a305db2011-11-07 22:57:04 +00001453 std::string funct,
Enrico Granata735152e2014-09-15 17:52:44 +00001454 std::string help,
Enrico Granata0a305db2011-11-07 22:57:04 +00001455 ScriptedCommandSynchronicity synch) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001456 CommandObjectRaw(interpreter,
1457 name.c_str(),
1458 nullptr,
1459 nullptr),
Jim Ingham5a988412012-06-08 21:56:10 +00001460 m_function_name(funct),
Enrico Granatafac939e2012-09-18 21:53:02 +00001461 m_synchro(synch),
1462 m_fetched_help_long(false)
Enrico Granata223383e2011-08-16 23:24:13 +00001463 {
Enrico Granata735152e2014-09-15 17:52:44 +00001464 if (!help.empty())
1465 SetHelp(help.c_str());
1466 else
1467 {
1468 StreamString stream;
1469 stream.Printf("For more information run 'help %s'",name.c_str());
1470 SetHelp(stream.GetData());
1471 }
Enrico Granata223383e2011-08-16 23:24:13 +00001472 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001473
1474 ~CommandObjectPythonFunction() override = default;
1475
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001476 bool
1477 IsRemovable () const override
Jim Ingham5a988412012-06-08 21:56:10 +00001478 {
1479 return true;
1480 }
1481
1482 const std::string&
1483 GetFunctionName ()
1484 {
1485 return m_function_name;
1486 }
1487
1488 ScriptedCommandSynchronicity
1489 GetSynchronicity ()
1490 {
1491 return m_synchro;
1492 }
1493
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001494 const char *
1495 GetHelpLong () override
Enrico Granatafac939e2012-09-18 21:53:02 +00001496 {
1497 if (!m_fetched_help_long)
1498 {
1499 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1500 if (scripter)
1501 {
1502 std::string docstring;
1503 m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring);
1504 if (!docstring.empty())
Enrico Granatabfb75e92016-03-22 22:12:59 +00001505 SetHelpLong(docstring.c_str());
Enrico Granatafac939e2012-09-18 21:53:02 +00001506 }
1507 }
1508 return CommandObjectRaw::GetHelpLong();
1509 }
1510
Jim Ingham5a988412012-06-08 21:56:10 +00001511protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001512 bool
1513 DoExecute (const char *raw_command_line, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00001514 {
1515 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1516
1517 Error error;
1518
Jim Ingham70f11f82012-06-27 17:25:36 +00001519 result.SetStatus(eReturnStatusInvalid);
1520
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001521 if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1522 raw_command_line,
1523 m_synchro,
1524 result,
1525 error,
1526 m_exe_ctx))
Enrico Granata223383e2011-08-16 23:24:13 +00001527 {
1528 result.AppendError(error.AsCString());
1529 result.SetStatus(eReturnStatusFailed);
1530 }
1531 else
Jim Ingham70f11f82012-06-27 17:25:36 +00001532 {
1533 // Don't change the status if the command already set it...
1534 if (result.GetStatus() == eReturnStatusInvalid)
1535 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001536 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0')
Jim Ingham70f11f82012-06-27 17:25:36 +00001537 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1538 else
1539 result.SetStatus(eReturnStatusSuccessFinishResult);
1540 }
1541 }
Enrico Granata223383e2011-08-16 23:24:13 +00001542
1543 return result.Succeeded();
1544 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001545
1546private:
1547 std::string m_function_name;
1548 ScriptedCommandSynchronicity m_synchro;
1549 bool m_fetched_help_long;
Enrico Granata223383e2011-08-16 23:24:13 +00001550};
1551
Enrico Granata9fe00e52015-03-13 02:20:41 +00001552class CommandObjectScriptingObject : public CommandObjectRaw
1553{
Enrico Granata9fe00e52015-03-13 02:20:41 +00001554public:
Enrico Granata9fe00e52015-03-13 02:20:41 +00001555 CommandObjectScriptingObject (CommandInterpreter &interpreter,
1556 std::string name,
Zachary Turner0641ca12015-03-17 20:04:04 +00001557 StructuredData::GenericSP cmd_obj_sp,
Enrico Granata9fe00e52015-03-13 02:20:41 +00001558 ScriptedCommandSynchronicity synch) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001559 CommandObjectRaw(interpreter,
1560 name.c_str(),
1561 nullptr,
1562 nullptr),
1563 m_cmd_obj_sp(cmd_obj_sp),
1564 m_synchro(synch),
1565 m_fetched_help_short(false),
1566 m_fetched_help_long(false)
Enrico Granata9fe00e52015-03-13 02:20:41 +00001567 {
1568 StreamString stream;
1569 stream.Printf("For more information run 'help %s'",name.c_str());
1570 SetHelp(stream.GetData());
Enrico Granatae87764f2015-05-27 05:04:35 +00001571 if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter())
1572 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
Enrico Granata9fe00e52015-03-13 02:20:41 +00001573 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001574
1575 ~CommandObjectScriptingObject() override = default;
1576
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001577 bool
1578 IsRemovable () const override
Enrico Granata9fe00e52015-03-13 02:20:41 +00001579 {
1580 return true;
1581 }
1582
Zachary Turner0641ca12015-03-17 20:04:04 +00001583 StructuredData::GenericSP
Enrico Granata9fe00e52015-03-13 02:20:41 +00001584 GetImplementingObject ()
1585 {
1586 return m_cmd_obj_sp;
1587 }
1588
1589 ScriptedCommandSynchronicity
1590 GetSynchronicity ()
1591 {
1592 return m_synchro;
1593 }
Enrico Granata6f79bb22015-03-13 22:22:28 +00001594
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001595 const char *
1596 GetHelp () override
Enrico Granata6f79bb22015-03-13 22:22:28 +00001597 {
1598 if (!m_fetched_help_short)
1599 {
1600 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1601 if (scripter)
1602 {
1603 std::string docstring;
1604 m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring);
1605 if (!docstring.empty())
Enrico Granatabfb75e92016-03-22 22:12:59 +00001606 SetHelp(docstring.c_str());
Enrico Granata6f79bb22015-03-13 22:22:28 +00001607 }
1608 }
1609 return CommandObjectRaw::GetHelp();
1610 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001611
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001612 const char *
1613 GetHelpLong () override
Enrico Granata9fe00e52015-03-13 02:20:41 +00001614 {
Enrico Granata6f79bb22015-03-13 22:22:28 +00001615 if (!m_fetched_help_long)
1616 {
1617 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1618 if (scripter)
1619 {
1620 std::string docstring;
1621 m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring);
1622 if (!docstring.empty())
Enrico Granatabfb75e92016-03-22 22:12:59 +00001623 SetHelpLong(docstring.c_str());
Enrico Granata6f79bb22015-03-13 22:22:28 +00001624 }
1625 }
Enrico Granata9fe00e52015-03-13 02:20:41 +00001626 return CommandObjectRaw::GetHelpLong();
1627 }
1628
1629protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001630 bool
1631 DoExecute (const char *raw_command_line, CommandReturnObject &result) override
Enrico Granata9fe00e52015-03-13 02:20:41 +00001632 {
1633 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1634
1635 Error error;
1636
1637 result.SetStatus(eReturnStatusInvalid);
1638
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001639 if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp,
1640 raw_command_line,
1641 m_synchro,
1642 result,
1643 error,
1644 m_exe_ctx))
Enrico Granata9fe00e52015-03-13 02:20:41 +00001645 {
1646 result.AppendError(error.AsCString());
1647 result.SetStatus(eReturnStatusFailed);
1648 }
1649 else
1650 {
1651 // Don't change the status if the command already set it...
1652 if (result.GetStatus() == eReturnStatusInvalid)
1653 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001654 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0')
Enrico Granata9fe00e52015-03-13 02:20:41 +00001655 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1656 else
1657 result.SetStatus(eReturnStatusSuccessFinishResult);
1658 }
1659 }
1660
1661 return result.Succeeded();
1662 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001663
1664private:
1665 StructuredData::GenericSP m_cmd_obj_sp;
1666 ScriptedCommandSynchronicity m_synchro;
1667 bool m_fetched_help_short: 1;
1668 bool m_fetched_help_long: 1;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001669};
1670
Enrico Granataa9dbf432011-10-17 21:45:27 +00001671//-------------------------------------------------------------------------
1672// CommandObjectCommandsScriptImport
1673//-------------------------------------------------------------------------
1674
Jim Ingham5a988412012-06-08 21:56:10 +00001675class CommandObjectCommandsScriptImport : public CommandObjectParsed
Enrico Granataa9dbf432011-10-17 21:45:27 +00001676{
Jim Ingham5a988412012-06-08 21:56:10 +00001677public:
1678 CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001679 CommandObjectParsed(interpreter,
1680 "command script import",
1681 "Import a scripting module in LLDB.",
1682 nullptr),
Todd Fialae1cfbc72016-08-11 23:51:28 +00001683 m_options()
Jim Ingham5a988412012-06-08 21:56:10 +00001684 {
1685 CommandArgumentEntry arg1;
1686 CommandArgumentData cmd_arg;
1687
1688 // Define the first (and only) variant of this arg.
1689 cmd_arg.arg_type = eArgTypeFilename;
Enrico Granata3b00e352015-06-16 18:31:04 +00001690 cmd_arg.arg_repetition = eArgRepeatPlus;
Jim Ingham5a988412012-06-08 21:56:10 +00001691
1692 // There is only one variant this argument could be; put it into the argument entry.
1693 arg1.push_back (cmd_arg);
1694
1695 // Push the data for the first argument into the m_arguments vector.
1696 m_arguments.push_back (arg1);
1697 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001698
1699 ~CommandObjectCommandsScriptImport() override = default;
1700
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001701 int
Jim Ingham5a988412012-06-08 21:56:10 +00001702 HandleArgumentCompletion (Args &input,
1703 int &cursor_index,
1704 int &cursor_char_position,
1705 OptionElementVector &opt_element_vector,
1706 int match_start_point,
1707 int max_return_elements,
1708 bool &word_complete,
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001709 StringList &matches) override
Jim Ingham5a988412012-06-08 21:56:10 +00001710 {
1711 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1712 completion_str.erase (cursor_char_position);
Todd Fialae1cfbc72016-08-11 23:51:28 +00001713
1714 CommandCompletions::InvokeCommonCompletionCallbacks(GetCommandInterpreter(),
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001715 CommandCompletions::eDiskFileCompletion,
1716 completion_str.c_str(),
1717 match_start_point,
1718 max_return_elements,
1719 nullptr,
1720 word_complete,
1721 matches);
Jim Ingham5a988412012-06-08 21:56:10 +00001722 return matches.GetSize();
1723 }
1724
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001725 Options *
1726 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +00001727 {
1728 return &m_options;
1729 }
1730
1731protected:
Enrico Granata0a305db2011-11-07 22:57:04 +00001732 class CommandOptions : public Options
1733 {
1734 public:
Todd Fialae1cfbc72016-08-11 23:51:28 +00001735 CommandOptions() :
1736 Options()
Enrico Granata0a305db2011-11-07 22:57:04 +00001737 {
1738 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001739
1740 ~CommandOptions() override = default;
1741
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001742 Error
Todd Fialae1cfbc72016-08-11 23:51:28 +00001743 SetOptionValue (uint32_t option_idx, const char *option_arg,
1744 ExecutionContext *execution_context) override
Enrico Granata0a305db2011-11-07 22:57:04 +00001745 {
1746 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001747 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata0a305db2011-11-07 22:57:04 +00001748
1749 switch (short_option)
1750 {
1751 case 'r':
1752 m_allow_reload = true;
1753 break;
1754 default:
1755 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1756 break;
1757 }
1758
1759 return error;
1760 }
1761
1762 void
Todd Fialae1cfbc72016-08-11 23:51:28 +00001763 OptionParsingStarting(ExecutionContext *execution_context) override
Enrico Granata0a305db2011-11-07 22:57:04 +00001764 {
Enrico Granatae0c70f12013-05-31 01:03:09 +00001765 m_allow_reload = true;
Enrico Granata0a305db2011-11-07 22:57:04 +00001766 }
1767
1768 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001769 GetDefinitions () override
Enrico Granata0a305db2011-11-07 22:57:04 +00001770 {
1771 return g_option_table;
1772 }
1773
1774 // Options table: Required for subclasses of Options.
1775
1776 static OptionDefinition g_option_table[];
1777
1778 // Instance variables to hold the values for command options.
1779
1780 bool m_allow_reload;
1781 };
Enrico Granata0a305db2011-11-07 22:57:04 +00001782
Enrico Granataa9dbf432011-10-17 21:45:27 +00001783 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001784 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granataa9dbf432011-10-17 21:45:27 +00001785 {
Enrico Granataa9dbf432011-10-17 21:45:27 +00001786 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1787 {
1788 result.AppendError ("only scripting language supported for module importing is currently Python");
1789 result.SetStatus (eReturnStatusFailed);
1790 return false;
1791 }
1792
Jim Ingham5a988412012-06-08 21:56:10 +00001793 size_t argc = command.GetArgumentCount();
Enrico Granata3b00e352015-06-16 18:31:04 +00001794 if (0 == argc)
Enrico Granataa9dbf432011-10-17 21:45:27 +00001795 {
Enrico Granata3b00e352015-06-16 18:31:04 +00001796 result.AppendError("command script import needs one or more arguments");
Enrico Granataa9dbf432011-10-17 21:45:27 +00001797 result.SetStatus (eReturnStatusFailed);
1798 return false;
1799 }
1800
Ed Maste0e978482015-06-17 17:29:56 +00001801 for (size_t i = 0;
Enrico Granata3b00e352015-06-16 18:31:04 +00001802 i < argc;
1803 i++)
Enrico Granataa9dbf432011-10-17 21:45:27 +00001804 {
Enrico Granata3b00e352015-06-16 18:31:04 +00001805 std::string path = command.GetArgumentAtIndex(i);
1806 Error error;
1807
1808 const bool init_session = true;
1809 // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
1810 // commands won't ever be recursively invoked, but it's actually possible to craft
1811 // a Python script that does other "command script imports" in __lldb_init_module
1812 // the real fix is to have recursive commands possible with a CommandInvocation object
1813 // separate from the CommandObject itself, so that recursive command invocations
1814 // won't stomp on each other (wrt to execution contents, options, and more)
1815 m_exe_ctx.Clear();
1816 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
1817 m_options.m_allow_reload,
1818 init_session,
1819 error))
1820 {
1821 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1822 }
1823 else
1824 {
1825 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
1826 result.SetStatus (eReturnStatusFailed);
1827 }
Enrico Granataa9dbf432011-10-17 21:45:27 +00001828 }
1829
1830 return result.Succeeded();
1831 }
Enrico Granata0a305db2011-11-07 22:57:04 +00001832
Jim Ingham5a988412012-06-08 21:56:10 +00001833 CommandOptions m_options;
Enrico Granataa9dbf432011-10-17 21:45:27 +00001834};
Enrico Granata223383e2011-08-16 23:24:13 +00001835
Enrico Granata0a305db2011-11-07 22:57:04 +00001836OptionDefinition
1837CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
1838{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001839 { 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."},
1840 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata0a305db2011-11-07 22:57:04 +00001841};
1842
Enrico Granata223383e2011-08-16 23:24:13 +00001843//-------------------------------------------------------------------------
1844// CommandObjectCommandsScriptAdd
1845//-------------------------------------------------------------------------
1846
Greg Clayton44d93782014-01-27 23:43:24 +00001847class CommandObjectCommandsScriptAdd :
1848 public CommandObjectParsed,
1849 public IOHandlerDelegateMultiline
Enrico Granata223383e2011-08-16 23:24:13 +00001850{
Jim Ingham5a988412012-06-08 21:56:10 +00001851public:
1852 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001853 CommandObjectParsed(interpreter,
1854 "command script add",
1855 "Add a scripted function as an LLDB command.",
1856 nullptr),
Greg Claytonc3d874a2014-05-08 16:59:00 +00001857 IOHandlerDelegateMultiline ("DONE"),
Todd Fialae1cfbc72016-08-11 23:51:28 +00001858 m_options()
Jim Ingham5a988412012-06-08 21:56:10 +00001859 {
1860 CommandArgumentEntry arg1;
1861 CommandArgumentData cmd_arg;
1862
1863 // Define the first (and only) variant of this arg.
1864 cmd_arg.arg_type = eArgTypeCommandName;
1865 cmd_arg.arg_repetition = eArgRepeatPlain;
1866
1867 // There is only one variant this argument could be; put it into the argument entry.
1868 arg1.push_back (cmd_arg);
1869
1870 // Push the data for the first argument into the m_arguments vector.
1871 m_arguments.push_back (arg1);
1872 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001873
1874 ~CommandObjectCommandsScriptAdd() override = default;
1875
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001876 Options *
1877 GetOptions () override
Jim Ingham5a988412012-06-08 21:56:10 +00001878 {
1879 return &m_options;
1880 }
1881
1882protected:
Enrico Granata223383e2011-08-16 23:24:13 +00001883 class CommandOptions : public Options
1884 {
1885 public:
Todd Fialae1cfbc72016-08-11 23:51:28 +00001886 CommandOptions() :
1887 Options(),
Enrico Granata9fe00e52015-03-13 02:20:41 +00001888 m_class_name(),
1889 m_funct_name(),
1890 m_short_help(),
1891 m_synchronicity(eScriptedCommandSynchronicitySynchronous)
Enrico Granata223383e2011-08-16 23:24:13 +00001892 {
1893 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00001894
1895 ~CommandOptions() override = default;
1896
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001897 Error
Todd Fialae1cfbc72016-08-11 23:51:28 +00001898 SetOptionValue (uint32_t option_idx, const char *option_arg,
1899 ExecutionContext *execution_context) override
Enrico Granata223383e2011-08-16 23:24:13 +00001900 {
1901 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001902 const int short_option = m_getopt_table[option_idx].val;
Enrico Granata223383e2011-08-16 23:24:13 +00001903
1904 switch (short_option)
1905 {
1906 case 'f':
Enrico Granata735152e2014-09-15 17:52:44 +00001907 if (option_arg)
1908 m_funct_name.assign(option_arg);
1909 break;
Enrico Granata9fe00e52015-03-13 02:20:41 +00001910 case 'c':
1911 if (option_arg)
1912 m_class_name.assign(option_arg);
1913 break;
Enrico Granata735152e2014-09-15 17:52:44 +00001914 case 'h':
1915 if (option_arg)
1916 m_short_help.assign(option_arg);
Enrico Granata223383e2011-08-16 23:24:13 +00001917 break;
Enrico Granata0a305db2011-11-07 22:57:04 +00001918 case 's':
Greg Clayton44d93782014-01-27 23:43:24 +00001919 m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
Enrico Granata0a305db2011-11-07 22:57:04 +00001920 if (!error.Success())
1921 error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
1922 break;
Enrico Granata223383e2011-08-16 23:24:13 +00001923 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001924 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Enrico Granata223383e2011-08-16 23:24:13 +00001925 break;
1926 }
1927
1928 return error;
1929 }
1930
1931 void
Todd Fialae1cfbc72016-08-11 23:51:28 +00001932 OptionParsingStarting(ExecutionContext *execution_context) override
Enrico Granata223383e2011-08-16 23:24:13 +00001933 {
Enrico Granata9fe00e52015-03-13 02:20:41 +00001934 m_class_name.clear();
Enrico Granata735152e2014-09-15 17:52:44 +00001935 m_funct_name.clear();
1936 m_short_help.clear();
Greg Clayton44d93782014-01-27 23:43:24 +00001937 m_synchronicity = eScriptedCommandSynchronicitySynchronous;
Enrico Granata223383e2011-08-16 23:24:13 +00001938 }
1939
1940 const OptionDefinition*
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001941 GetDefinitions () override
Enrico Granata223383e2011-08-16 23:24:13 +00001942 {
1943 return g_option_table;
1944 }
1945
1946 // Options table: Required for subclasses of Options.
1947
1948 static OptionDefinition g_option_table[];
1949
1950 // Instance variables to hold the values for command options.
1951
Enrico Granata9fe00e52015-03-13 02:20:41 +00001952 std::string m_class_name;
Enrico Granata223383e2011-08-16 23:24:13 +00001953 std::string m_funct_name;
Enrico Granata735152e2014-09-15 17:52:44 +00001954 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00001955 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00001956 };
Jim Ingham5a988412012-06-08 21:56:10 +00001957
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001958 void
1959 IOHandlerActivated (IOHandler &io_handler) override
Enrico Granata223383e2011-08-16 23:24:13 +00001960 {
Greg Clayton44d93782014-01-27 23:43:24 +00001961 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1962 if (output_sp)
Enrico Granata223383e2011-08-16 23:24:13 +00001963 {
Greg Clayton44d93782014-01-27 23:43:24 +00001964 output_sp->PutCString(g_python_command_instructions);
1965 output_sp->Flush();
Enrico Granata223383e2011-08-16 23:24:13 +00001966 }
Greg Clayton44d93782014-01-27 23:43:24 +00001967 }
Enrico Granata223383e2011-08-16 23:24:13 +00001968
Greg Clayton44d93782014-01-27 23:43:24 +00001969
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001970 void
1971 IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
Greg Clayton44d93782014-01-27 23:43:24 +00001972 {
1973 StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1974
1975 ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1976 if (interpreter)
1977 {
1978
1979 StringList lines;
1980 lines.SplitIntoLines(data);
1981 if (lines.GetSize() > 0)
1982 {
1983 std::string funct_name_str;
1984 if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str))
1985 {
1986 if (funct_name_str.empty())
1987 {
1988 error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n");
1989 error_sp->Flush();
1990 }
1991 else
1992 {
1993 // everything should be fine now, let's add this alias
1994
1995 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
1996 m_cmd_name,
1997 funct_name_str.c_str(),
Enrico Granata735152e2014-09-15 17:52:44 +00001998 m_short_help,
Greg Clayton44d93782014-01-27 23:43:24 +00001999 m_synchronicity));
2000
2001 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
2002 {
2003 error_sp->Printf ("error: unable to add selected command, didn't add python command.\n");
2004 error_sp->Flush();
2005 }
2006 }
2007 }
2008 else
2009 {
2010 error_sp->Printf ("error: unable to create function, didn't add python command.\n");
2011 error_sp->Flush();
2012 }
2013 }
2014 else
2015 {
2016 error_sp->Printf ("error: empty function, didn't add python command.\n");
2017 error_sp->Flush();
2018 }
2019 }
2020 else
2021 {
2022 error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
2023 error_sp->Flush();
2024 }
2025
2026 io_handler.SetIsDone(true);
Greg Clayton44d93782014-01-27 23:43:24 +00002027 }
2028
Jim Ingham5a988412012-06-08 21:56:10 +00002029protected:
Enrico Granata223383e2011-08-16 23:24:13 +00002030 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002031 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002032 {
Enrico Granata99f0b8f2011-08-17 01:30:04 +00002033 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
2034 {
2035 result.AppendError ("only scripting language supported for scripted commands is currently Python");
2036 result.SetStatus (eReturnStatusFailed);
2037 return false;
2038 }
2039
Jim Ingham5a988412012-06-08 21:56:10 +00002040 size_t argc = command.GetArgumentCount();
Enrico Granata223383e2011-08-16 23:24:13 +00002041
2042 if (argc != 1)
2043 {
2044 result.AppendError ("'command script add' requires one argument");
2045 result.SetStatus (eReturnStatusFailed);
2046 return false;
2047 }
2048
Enrico Granata735152e2014-09-15 17:52:44 +00002049 // Store the options in case we get multi-line input
Greg Clayton44d93782014-01-27 23:43:24 +00002050 m_cmd_name = command.GetArgumentAtIndex(0);
Enrico Granata735152e2014-09-15 17:52:44 +00002051 m_short_help.assign(m_options.m_short_help);
Greg Clayton44d93782014-01-27 23:43:24 +00002052 m_synchronicity = m_options.m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00002053
Enrico Granata9fe00e52015-03-13 02:20:41 +00002054 if (m_options.m_class_name.empty())
Enrico Granata223383e2011-08-16 23:24:13 +00002055 {
Enrico Granata9fe00e52015-03-13 02:20:41 +00002056 if (m_options.m_funct_name.empty())
2057 {
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002058 m_interpreter.GetPythonCommandsFromIOHandler(" ", // Prompt
2059 *this, // IOHandlerDelegate
2060 true, // Run IOHandler in async mode
2061 nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
Enrico Granata9fe00e52015-03-13 02:20:41 +00002062 }
2063 else
2064 {
2065 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
2066 m_cmd_name,
2067 m_options.m_funct_name,
2068 m_options.m_short_help,
2069 m_synchronicity));
2070 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
2071 {
2072 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2073 }
2074 else
2075 {
2076 result.AppendError("cannot add command");
2077 result.SetStatus (eReturnStatusFailed);
2078 }
2079 }
Enrico Granata223383e2011-08-16 23:24:13 +00002080 }
2081 else
2082 {
Enrico Granata9fe00e52015-03-13 02:20:41 +00002083 ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter();
2084 if (!interpreter)
2085 {
2086 result.AppendError("cannot find ScriptInterpreter");
2087 result.SetStatus(eReturnStatusFailed);
2088 return false;
2089 }
2090
2091 auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str());
2092 if (!cmd_obj_sp)
2093 {
2094 result.AppendError("cannot create helper object");
2095 result.SetStatus(eReturnStatusFailed);
2096 return false;
2097 }
2098
2099 CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter,
2100 m_cmd_name,
2101 cmd_obj_sp,
2102 m_synchronicity));
Greg Clayton44d93782014-01-27 23:43:24 +00002103 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
Enrico Granata223383e2011-08-16 23:24:13 +00002104 {
2105 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2106 }
2107 else
2108 {
2109 result.AppendError("cannot add command");
2110 result.SetStatus (eReturnStatusFailed);
2111 }
2112 }
2113
2114 return result.Succeeded();
Enrico Granata223383e2011-08-16 23:24:13 +00002115 }
Jim Ingham5a988412012-06-08 21:56:10 +00002116
2117 CommandOptions m_options;
Greg Clayton44d93782014-01-27 23:43:24 +00002118 std::string m_cmd_name;
Enrico Granata735152e2014-09-15 17:52:44 +00002119 std::string m_short_help;
Greg Clayton44d93782014-01-27 23:43:24 +00002120 ScriptedCommandSynchronicity m_synchronicity;
Enrico Granata223383e2011-08-16 23:24:13 +00002121};
2122
Enrico Granata0a305db2011-11-07 22:57:04 +00002123static OptionEnumValueElement g_script_synchro_type[] =
2124{
2125 { eScriptedCommandSynchronicitySynchronous, "synchronous", "Run synchronous"},
2126 { eScriptedCommandSynchronicityAsynchronous, "asynchronous", "Run asynchronous"},
2127 { eScriptedCommandSynchronicityCurrentValue, "current", "Do not alter current setting"},
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002128 { 0, nullptr, nullptr }
Enrico Granata0a305db2011-11-07 22:57:04 +00002129};
2130
Enrico Granata223383e2011-08-16 23:24:13 +00002131OptionDefinition
2132CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
2133{
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002134 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
2135 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."},
2136 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."},
2137 { 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."},
2138 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
Enrico Granata223383e2011-08-16 23:24:13 +00002139};
2140
2141//-------------------------------------------------------------------------
2142// CommandObjectCommandsScriptList
2143//-------------------------------------------------------------------------
2144
Jim Ingham5a988412012-06-08 21:56:10 +00002145class CommandObjectCommandsScriptList : public CommandObjectParsed
Enrico Granata223383e2011-08-16 23:24:13 +00002146{
Enrico Granata223383e2011-08-16 23:24:13 +00002147public:
2148 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002149 CommandObjectParsed(interpreter,
2150 "command script list",
2151 "List defined scripted commands.",
2152 nullptr)
Enrico Granata223383e2011-08-16 23:24:13 +00002153 {
2154 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002155
2156 ~CommandObjectCommandsScriptList() override = default;
2157
Enrico Granata223383e2011-08-16 23:24:13 +00002158 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002159 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002160 {
Enrico Granata223383e2011-08-16 23:24:13 +00002161 m_interpreter.GetHelp(result,
2162 CommandInterpreter::eCommandTypesUserDef);
2163
2164 result.SetStatus (eReturnStatusSuccessFinishResult);
2165
2166 return true;
Enrico Granata223383e2011-08-16 23:24:13 +00002167 }
2168};
2169
2170//-------------------------------------------------------------------------
2171// CommandObjectCommandsScriptClear
2172//-------------------------------------------------------------------------
2173
Jim Ingham5a988412012-06-08 21:56:10 +00002174class CommandObjectCommandsScriptClear : public CommandObjectParsed
Enrico Granata223383e2011-08-16 23:24:13 +00002175{
Enrico Granata223383e2011-08-16 23:24:13 +00002176public:
2177 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002178 CommandObjectParsed(interpreter,
2179 "command script clear",
2180 "Delete all scripted commands.",
2181 nullptr)
Enrico Granata223383e2011-08-16 23:24:13 +00002182 {
2183 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002184
2185 ~CommandObjectCommandsScriptClear() override = default;
2186
Jim Ingham5a988412012-06-08 21:56:10 +00002187protected:
Enrico Granata223383e2011-08-16 23:24:13 +00002188 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002189 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002190 {
Enrico Granata223383e2011-08-16 23:24:13 +00002191 m_interpreter.RemoveAllUser();
2192
2193 result.SetStatus (eReturnStatusSuccessFinishResult);
2194
2195 return true;
Enrico Granata223383e2011-08-16 23:24:13 +00002196 }
2197};
2198
2199//-------------------------------------------------------------------------
2200// CommandObjectCommandsScriptDelete
2201//-------------------------------------------------------------------------
2202
Jim Ingham5a988412012-06-08 21:56:10 +00002203class CommandObjectCommandsScriptDelete : public CommandObjectParsed
Enrico Granata223383e2011-08-16 23:24:13 +00002204{
Enrico Granata223383e2011-08-16 23:24:13 +00002205public:
2206 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002207 CommandObjectParsed(interpreter,
2208 "command script delete",
2209 "Delete a scripted command.",
2210 nullptr)
Enrico Granata223383e2011-08-16 23:24:13 +00002211 {
2212 CommandArgumentEntry arg1;
2213 CommandArgumentData cmd_arg;
2214
2215 // Define the first (and only) variant of this arg.
2216 cmd_arg.arg_type = eArgTypeCommandName;
2217 cmd_arg.arg_repetition = eArgRepeatPlain;
2218
2219 // There is only one variant this argument could be; put it into the argument entry.
2220 arg1.push_back (cmd_arg);
2221
2222 // Push the data for the first argument into the m_arguments vector.
2223 m_arguments.push_back (arg1);
2224 }
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002225
2226 ~CommandObjectCommandsScriptDelete() override = default;
2227
Jim Ingham5a988412012-06-08 21:56:10 +00002228protected:
Enrico Granata223383e2011-08-16 23:24:13 +00002229 bool
Bruce Mitchener13d21e92015-10-07 16:56:17 +00002230 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata223383e2011-08-16 23:24:13 +00002231 {
2232
Jim Ingham5a988412012-06-08 21:56:10 +00002233 size_t argc = command.GetArgumentCount();
Enrico Granata223383e2011-08-16 23:24:13 +00002234
2235 if (argc != 1)
2236 {
2237 result.AppendError ("'command script delete' requires one argument");
2238 result.SetStatus (eReturnStatusFailed);
2239 return false;
2240 }
2241
Jim Ingham5a988412012-06-08 21:56:10 +00002242 const char* cmd_name = command.GetArgumentAtIndex(0);
Enrico Granata223383e2011-08-16 23:24:13 +00002243
2244 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
2245 {
2246 m_interpreter.RemoveUser(cmd_name);
2247 result.SetStatus (eReturnStatusSuccessFinishResult);
2248 }
2249 else
2250 {
2251 result.AppendErrorWithFormat ("command %s not found", cmd_name);
2252 result.SetStatus (eReturnStatusFailed);
2253 }
2254
2255 return result.Succeeded();
Enrico Granata223383e2011-08-16 23:24:13 +00002256 }
2257};
2258
2259#pragma mark CommandObjectMultiwordCommandsScript
2260
2261//-------------------------------------------------------------------------
2262// CommandObjectMultiwordCommandsScript
2263//-------------------------------------------------------------------------
2264
2265class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
2266{
2267public:
Kate Stone7428a182016-07-14 22:03:10 +00002268 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter)
2269 : CommandObjectMultiword(interpreter, "command script",
2270 "Commands for managing custom commands implemented by interpreter scripts.",
2271 "command script <subcommand> [<subcommand-options>]")
Enrico Granata223383e2011-08-16 23:24:13 +00002272 {
Greg Claytonb5472782015-01-09 19:08:20 +00002273 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
2274 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
2275 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
Enrico Granata223383e2011-08-16 23:24:13 +00002276 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
Greg Claytonb5472782015-01-09 19:08:20 +00002277 LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
Enrico Granata223383e2011-08-16 23:24:13 +00002278 }
2279
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002280 ~CommandObjectMultiwordCommandsScript() override = default;
Enrico Granata223383e2011-08-16 23:24:13 +00002281};
2282
Jim Inghamebc09c32010-07-07 03:36:20 +00002283#pragma mark CommandObjectMultiwordCommands
2284
2285//-------------------------------------------------------------------------
2286// CommandObjectMultiwordCommands
2287//-------------------------------------------------------------------------
2288
Kate Stone7428a182016-07-14 22:03:10 +00002289CommandObjectMultiwordCommands::CommandObjectMultiwordCommands(CommandInterpreter &interpreter)
2290 : CommandObjectMultiword(interpreter, "command", "Commands for managing custom LLDB commands.",
2291 "command <subcommand> [<subcommand-options>]")
Jim Inghamebc09c32010-07-07 03:36:20 +00002292{
Greg Claytona7015092010-09-18 01:14:36 +00002293 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
2294 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
2295 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytonb5472782015-01-09 19:08:20 +00002296 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsDelete (interpreter)));
Greg Claytonde164aa2011-04-20 16:37:46 +00002297 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Greg Claytonb5472782015-01-09 19:08:20 +00002298 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
2299 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
Jim Inghamebc09c32010-07-07 03:36:20 +00002300}
2301
Eugene Zelenko6e3d8e72016-02-22 23:46:47 +00002302CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;