blob: 142f29d79e77685bb1b2b3576cc62766fcf303ef [file] [log] [blame]
Jim Ingham767af882010-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
10#include "CommandObjectCommands.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
Greg Clayton40e48242011-04-20 22:55:21 +000015#include "llvm/ADT/StringRef.h"
16
Jim Ingham767af882010-07-07 03:36:20 +000017// Project includes
Jim Ingham767af882010-07-07 03:36:20 +000018#include "lldb/Core/Debugger.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000019#include "lldb/Core/InputReader.h"
20#include "lldb/Interpreter/Args.h"
Jim Ingham767af882010-07-07 03:36:20 +000021#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000022#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Jim Ingham767af882010-07-07 03:36:20 +000023#include "lldb/Interpreter/CommandReturnObject.h"
24#include "lldb/Interpreter/Options.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
Jim Ingham767af882010-07-07 03:36:20 +000029//-------------------------------------------------------------------------
30// CommandObjectCommandsSource
31//-------------------------------------------------------------------------
32
33class CommandObjectCommandsSource : public CommandObject
34{
Jim Ingham949d5ac2011-02-18 00:54:25 +000035private:
36
37 class CommandOptions : public Options
38 {
39 public:
40
Greg Claytonf15996e2011-04-07 22:46:35 +000041 CommandOptions (CommandInterpreter &interpreter) :
42 Options (interpreter)
43 {
44 }
Jim Ingham949d5ac2011-02-18 00:54:25 +000045
46 virtual
47 ~CommandOptions (){}
48
49 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +000050 SetOptionValue (uint32_t option_idx, const char *option_arg)
Jim Ingham949d5ac2011-02-18 00:54:25 +000051 {
52 Error error;
53 char short_option = (char) m_getopt_table[option_idx].val;
54 bool success;
55
56 switch (short_option)
57 {
58 case 'e':
59 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
60 if (!success)
61 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
62 break;
63 case 'c':
64 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
65 if (!success)
66 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
67 break;
68 default:
69 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
70 break;
71 }
72
73 return error;
74 }
75
76 void
Greg Clayton143fcc32011-04-13 00:18:08 +000077 OptionParsingStarting ()
Jim Ingham949d5ac2011-02-18 00:54:25 +000078 {
Jim Ingham949d5ac2011-02-18 00:54:25 +000079 m_stop_on_error = true;
80 m_stop_on_continue = true;
81 }
82
Greg Claytonb3448432011-03-24 21:19:54 +000083 const OptionDefinition*
Jim Ingham949d5ac2011-02-18 00:54:25 +000084 GetDefinitions ()
85 {
86 return g_option_table;
87 }
88
89 // Options table: Required for subclasses of Options.
90
Greg Claytonb3448432011-03-24 21:19:54 +000091 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +000092
93 // Instance variables to hold the values for command options.
94
95 bool m_stop_on_error;
96 bool m_stop_on_continue;
97 };
98
Jim Ingham949d5ac2011-02-18 00:54:25 +000099 CommandOptions m_options;
100
101 virtual Options *
102 GetOptions ()
103 {
104 return &m_options;
105 }
106
Jim Ingham767af882010-07-07 03:36:20 +0000107public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000108 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
109 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000110 "command source",
Greg Clayton238c0a12010-09-18 01:14:36 +0000111 "Read in debugger commands from the file <filename> and execute them.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000112 NULL),
113 m_options (interpreter)
Jim Ingham767af882010-07-07 03:36:20 +0000114 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000115 CommandArgumentEntry arg;
116 CommandArgumentData file_arg;
117
118 // Define the first (and only) variant of this arg.
119 file_arg.arg_type = eArgTypeFilename;
120 file_arg.arg_repetition = eArgRepeatPlain;
121
122 // There is only one variant this argument could be; put it into the argument entry.
123 arg.push_back (file_arg);
124
125 // Push the data for the first argument into the m_arguments vector.
126 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000127 }
128
129 ~CommandObjectCommandsSource ()
130 {
131 }
132
133 bool
134 Execute
135 (
Jim Ingham767af882010-07-07 03:36:20 +0000136 Args& args,
137 CommandReturnObject &result
138 )
139 {
140 const int argc = args.GetArgumentCount();
141 if (argc == 1)
142 {
143 const char *filename = args.GetArgumentAtIndex(0);
Jim Ingham767af882010-07-07 03:36:20 +0000144
145 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
146
Johnny Chena83ea882010-10-20 21:40:50 +0000147 FileSpec cmd_file (filename, true);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000148 ExecutionContext *exe_ctx = NULL; // Just use the default context.
149 bool echo_commands = true;
150 bool print_results = true;
Jim Ingham767af882010-07-07 03:36:20 +0000151
Jim Ingham949d5ac2011-02-18 00:54:25 +0000152 m_interpreter.HandleCommandsFromFile (cmd_file,
153 exe_ctx,
154 m_options.m_stop_on_continue,
155 m_options.m_stop_on_error,
156 echo_commands,
157 print_results,
158 result);
Jim Ingham767af882010-07-07 03:36:20 +0000159 }
160 else
161 {
162 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
163 result.SetStatus (eReturnStatusFailed);
164 }
165 return result.Succeeded();
166
167 }
168};
169
Greg Claytonb3448432011-03-24 21:19:54 +0000170OptionDefinition
Jim Ingham949d5ac2011-02-18 00:54:25 +0000171CommandObjectCommandsSource::CommandOptions::g_option_table[] =
172{
173{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
174{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
175{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
176};
177
Jim Ingham767af882010-07-07 03:36:20 +0000178#pragma mark CommandObjectCommandsAlias
179//-------------------------------------------------------------------------
180// CommandObjectCommandsAlias
181//-------------------------------------------------------------------------
182
183class CommandObjectCommandsAlias : public CommandObject
184{
185public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000186 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
187 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000188 "command alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000189 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000190 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000191 {
192 SetHelpLong(
193 "'alias' allows the user to create a short-cut or abbreviation for long \n\
194 commands, multi-word commands, and commands that take particular options. \n\
195 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000196 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
197 // command. \n\
198 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
199 // command. Since breakpoint commands are two-word \n\
200 // commands, the user will still need to enter the \n\
201 // second word after 'bp', e.g. 'bp enable' or \n\
202 // 'bp delete'. \n\
203 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
204 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000205 \nAn alias can include some options for the command, with the values either \n\
206 filled in at the time the alias is created, or specified as positional \n\
207 arguments, to be filled in when the alias is invoked. The following example \n\
208 shows how to create aliases with options: \n\
209 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000210 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000211 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
212 options already part of the alias. So if the user wants to set a breakpoint \n\
213 by file and line without explicitly having to use the -f and -l options, the \n\
214 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
215 for the actual arguments that will be passed when the alias command is used. \n\
216 The number in the placeholder refers to the position/order the actual value \n\
217 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
218 will be replaced with the first argument, all the occurrences of '%2' in the \n\
219 alias will be replaced with the second argument, and so on. This also allows \n\
220 actual arguments to be used multiple times within an alias (see 'process \n\
221 launch' example below). So in the 'bfl' case, the actual file value will be \n\
222 filled in with the first argument following 'bfl' and the actual line number \n\
223 value will be filled in with the second argument. The user would use this \n\
224 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000225 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000226 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000227 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000228 \nThis would be the same as if the user had entered \n\
229 'breakpoint set -f my-file.c -l 137'. \n\
230 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000231 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
232 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000233 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000234 \nIf the user always wanted to pass the same value to a particular option, the \n\
235 alias could be defined with that value directly in the alias as a constant, \n\
236 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000237 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
238 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000239
Caroline Tice43b014a2010-10-04 22:28:36 +0000240 CommandArgumentEntry arg1;
241 CommandArgumentEntry arg2;
242 CommandArgumentEntry arg3;
243 CommandArgumentData alias_arg;
244 CommandArgumentData cmd_arg;
245 CommandArgumentData options_arg;
246
247 // Define the first (and only) variant of this arg.
248 alias_arg.arg_type = eArgTypeAliasName;
249 alias_arg.arg_repetition = eArgRepeatPlain;
250
251 // There is only one variant this argument could be; put it into the argument entry.
252 arg1.push_back (alias_arg);
253
254 // Define the first (and only) variant of this arg.
255 cmd_arg.arg_type = eArgTypeCommandName;
256 cmd_arg.arg_repetition = eArgRepeatPlain;
257
258 // There is only one variant this argument could be; put it into the argument entry.
259 arg2.push_back (cmd_arg);
260
261 // Define the first (and only) variant of this arg.
262 options_arg.arg_type = eArgTypeAliasOptions;
263 options_arg.arg_repetition = eArgRepeatOptional;
264
265 // There is only one variant this argument could be; put it into the argument entry.
266 arg3.push_back (options_arg);
267
268 // Push the data for the first argument into the m_arguments vector.
269 m_arguments.push_back (arg1);
270 m_arguments.push_back (arg2);
271 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000272 }
273
274 ~CommandObjectCommandsAlias ()
275 {
276 }
277
Caroline Ticee0da7a52010-12-09 22:52:49 +0000278 bool
279 WantsRawCommandString ()
280 {
281 return true;
282 }
283
284 bool
285 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
286 {
287 Args args (raw_command_line);
288 std::string raw_command_string (raw_command_line);
289
290 size_t argc = args.GetArgumentCount();
291
292 if (argc < 2)
293 {
294 result.AppendError ("'alias' requires at least two arguments");
295 result.SetStatus (eReturnStatusFailed);
296 return false;
297 }
298
299 // Get the alias command.
300
301 const std::string alias_command = args.GetArgumentAtIndex (0);
302
303 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
304 // does the stripping itself.
305 size_t pos = raw_command_string.find (alias_command);
306 if (pos == 0)
307 {
308 raw_command_string = raw_command_string.substr (alias_command.size());
309 pos = raw_command_string.find_first_not_of (' ');
310 if ((pos != std::string::npos) && (pos > 0))
311 raw_command_string = raw_command_string.substr (pos);
312 }
313 else
314 {
315 result.AppendError ("Error parsing command string. No alias created.");
316 result.SetStatus (eReturnStatusFailed);
317 return false;
318 }
319
320
321 // Verify that the command is alias-able.
322 if (m_interpreter.CommandExists (alias_command.c_str()))
323 {
324 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
325 alias_command.c_str());
326 result.SetStatus (eReturnStatusFailed);
327 return false;
328 }
329
330 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
331 // raw_command_string is returned with the name of the command object stripped off the front.
332 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
333
334 if (!cmd_obj)
335 {
336 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
337 " No alias created.", raw_command_string.c_str());
338 result.SetStatus (eReturnStatusFailed);
339 return false;
340 }
341 else if (!cmd_obj->WantsRawCommandString ())
342 {
343 // Note that args was initialized with the original command, and has not been updated to this point.
344 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
345 return Execute (args, result);
346 }
347 else
348 {
349 // Verify & handle any options/arguments passed to the alias command
350
351 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
352 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
353
354 // Check to see if there's anything left in the input command string.
355 if (raw_command_string.size() > 0)
356 {
357
358 // Check to see if the command being aliased can take any command options.
359 Options *options = cmd_obj->GetOptions();
360 if (options)
361 {
362 // See if any options were specified as part of the alias; if so, handle them appropriately
Greg Clayton143fcc32011-04-13 00:18:08 +0000363 options->NotifyOptionParsingStarting ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000364 Args tmp_args (raw_command_string.c_str());
365 args.Unshift ("dummy_arg");
366 args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
367 args.Shift ();
368 if (result.Succeeded())
369 options->VerifyPartialOptions (result);
370 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
371 {
372 result.AppendError ("Unable to create requested alias.\n");
373 return false;
374 }
375 }
376 // Anything remaining must be plain raw input. Push it in as a single raw input argument.
377 if (raw_command_string.size() > 0)
378 option_arg_vector->push_back (OptionArgPair ("<argument>",
379 OptionArgValue (-1,
380 raw_command_string)));
381 }
382
383 // Create the alias
384 if (m_interpreter.AliasExists (alias_command.c_str())
385 || m_interpreter.UserCommandExists (alias_command.c_str()))
386 {
387 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
388 if (temp_option_arg_sp.get())
389 {
390 if (option_arg_vector->size() == 0)
391 m_interpreter.RemoveAliasOptions (alias_command.c_str());
392 }
393 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
394 alias_command.c_str());
395 }
396
397 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
Caroline Tice56d2fc42010-12-14 18:51:39 +0000398 if (cmd_obj_sp)
399 {
400 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
401 if (option_arg_vector->size() > 0)
402 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
403 result.SetStatus (eReturnStatusSuccessFinishNoResult);
404 }
405 else
406 {
407 result.AppendError ("Unable to create requested alias.\n");
408 result.SetStatus (eReturnStatusFailed);
409 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000410 }
411 return result.Succeeded();
412 }
Jim Ingham767af882010-07-07 03:36:20 +0000413
414 bool
415 Execute
416 (
Jim Ingham767af882010-07-07 03:36:20 +0000417 Args& args,
418 CommandReturnObject &result
419 )
420 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000421 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000422
423 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000424 {
Jim Ingham767af882010-07-07 03:36:20 +0000425 result.AppendError ("'alias' requires at least two arguments");
426 result.SetStatus (eReturnStatusFailed);
427 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000428 }
Jim Ingham767af882010-07-07 03:36:20 +0000429
430 const std::string alias_command = args.GetArgumentAtIndex(0);
431 const std::string actual_command = args.GetArgumentAtIndex(1);
432
433 args.Shift(); // Shift the alias command word off the argument vector.
434 args.Shift(); // Shift the old command word off the argument vector.
435
436 // Verify that the command is alias'able, and get the appropriate command object.
437
Greg Clayton238c0a12010-09-18 01:14:36 +0000438 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000439 {
440 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
441 alias_command.c_str());
442 result.SetStatus (eReturnStatusFailed);
443 }
444 else
445 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000446 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000447 CommandObjectSP subcommand_obj_sp;
448 bool use_subcommand = false;
449 if (command_obj_sp.get())
450 {
451 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000452 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000453 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
454 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
455
Caroline Ticee0da7a52010-12-09 22:52:49 +0000456 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000457 {
458 if (argc >= 3)
459 {
460 const std::string sub_command = args.GetArgumentAtIndex(0);
461 assert (sub_command.length() != 0);
462 subcommand_obj_sp =
463 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
464 if (subcommand_obj_sp.get())
465 {
466 sub_cmd_obj = subcommand_obj_sp.get();
467 use_subcommand = true;
468 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000469 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000470 }
471 else
472 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000473 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
474 "Unable to create alias.\n",
475 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000476 result.SetStatus (eReturnStatusFailed);
477 return false;
478 }
479 }
480 }
481
482 // Verify & handle any options/arguments passed to the alias command
483
484 if (args.GetArgumentCount () > 0)
485 {
Jim Ingham767af882010-07-07 03:36:20 +0000486 if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
487 || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
488 {
489 Options *options;
490 if (use_subcommand)
491 options = sub_cmd_obj->GetOptions();
492 else
493 options = cmd_obj->GetOptions();
Greg Clayton143fcc32011-04-13 00:18:08 +0000494 options->NotifyOptionParsingStarting ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000495 std::string empty_string;
Jim Ingham767af882010-07-07 03:36:20 +0000496 args.Unshift ("dummy_arg");
Caroline Ticee0da7a52010-12-09 22:52:49 +0000497 args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
Jim Ingham767af882010-07-07 03:36:20 +0000498 args.Shift ();
499 if (result.Succeeded())
500 options->VerifyPartialOptions (result);
Caroline Tice8bb61f02010-09-21 23:25:40 +0000501 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
502 {
503 result.AppendError ("Unable to create requested command alias.\n");
Caroline Ticee6866a32010-10-28 23:17:48 +0000504 return false;
Caroline Tice8bb61f02010-09-21 23:25:40 +0000505 }
Jim Ingham767af882010-07-07 03:36:20 +0000506 }
Caroline Tice8bb61f02010-09-21 23:25:40 +0000507
508 // Anything remaining in args must be a plain argument.
509
510 argc = args.GetArgumentCount();
511 for (size_t i = 0; i < argc; ++i)
Caroline Tice44c841d2010-12-07 19:58:26 +0000512 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
513 option_arg_vector->push_back
514 (OptionArgPair ("<argument>",
515 OptionArgValue (-1,
516 std::string (args.GetArgumentAtIndex (i)))));
Jim Ingham767af882010-07-07 03:36:20 +0000517 }
518
519 // Create the alias.
520
Greg Clayton238c0a12010-09-18 01:14:36 +0000521 if (m_interpreter.AliasExists (alias_command.c_str())
522 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000523 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000524 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000525 if (tmp_option_arg_sp.get())
526 {
527 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000528 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000529 }
530 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
531 alias_command.c_str());
532 }
533
534 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000535 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000536 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000537 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000538 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000539 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000540 result.SetStatus (eReturnStatusSuccessFinishNoResult);
541 }
542 else
543 {
544 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
545 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000546 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000547 }
548 }
549
550 return result.Succeeded();
551 }
552};
553
554#pragma mark CommandObjectCommandsUnalias
555//-------------------------------------------------------------------------
556// CommandObjectCommandsUnalias
557//-------------------------------------------------------------------------
558
559class CommandObjectCommandsUnalias : public CommandObject
560{
561public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000562 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
563 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000564 "command unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000565 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000566 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000567 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000568 CommandArgumentEntry arg;
569 CommandArgumentData alias_arg;
570
571 // Define the first (and only) variant of this arg.
572 alias_arg.arg_type = eArgTypeAliasName;
573 alias_arg.arg_repetition = eArgRepeatPlain;
574
575 // There is only one variant this argument could be; put it into the argument entry.
576 arg.push_back (alias_arg);
577
578 // Push the data for the first argument into the m_arguments vector.
579 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000580 }
581
582 ~CommandObjectCommandsUnalias()
583 {
584 }
585
586
587 bool
588 Execute
589 (
Jim Ingham767af882010-07-07 03:36:20 +0000590 Args& args,
591 CommandReturnObject &result
592 )
593 {
594 CommandObject::CommandMap::iterator pos;
595 CommandObject *cmd_obj;
596
597 if (args.GetArgumentCount() != 0)
598 {
599 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000600 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000601 if (cmd_obj)
602 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000603 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000604 {
605 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
606 command_name);
607 result.SetStatus (eReturnStatusFailed);
608 }
609 else
610 {
611
Greg Clayton238c0a12010-09-18 01:14:36 +0000612 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000613 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000614 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000615 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
616 command_name);
617 else
618 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
619 result.SetStatus (eReturnStatusFailed);
620 }
621 else
622 result.SetStatus (eReturnStatusSuccessFinishNoResult);
623 }
624 }
625 else
626 {
627 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
628 "current list of commands.\n",
629 command_name);
630 result.SetStatus (eReturnStatusFailed);
631 }
632 }
633 else
634 {
635 result.AppendError ("must call 'unalias' with a valid alias");
636 result.SetStatus (eReturnStatusFailed);
637 }
638
639 return result.Succeeded();
640 }
641};
642
Greg Claytond12aeab2011-04-20 16:37:46 +0000643#pragma mark CommandObjectCommandsAddRegex
644//-------------------------------------------------------------------------
645// CommandObjectCommandsAddRegex
646//-------------------------------------------------------------------------
647
648class CommandObjectCommandsAddRegex : public CommandObject
649{
650public:
651 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
652 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000653 "command regex",
Greg Claytond12aeab2011-04-20 16:37:46 +0000654 "Allow the user to create a regular expression command.",
Greg Clayton40e48242011-04-20 22:55:21 +0000655 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
Greg Claytond12aeab2011-04-20 16:37:46 +0000656 m_options (interpreter)
657 {
Greg Clayton40e48242011-04-20 22:55:21 +0000658 SetHelpLong(
659"This command allows the user to create powerful regular expression commands\n"
660"with substitutions. The regular expressions and substitutions are specified\n"
661"using the regular exression substitution format of:\n"
662"\n"
663" s/<regex>/<subst>/\n"
664"\n"
665"<regex> is a regular expression that can use parenthesis to capture regular\n"
666"expression input and substitute the captured matches in the output using %1\n"
667"for the first match, %2 for the second, and so on.\n"
668"\n"
669"The regular expressions can all be specified on the command line if more than\n"
670"one argument is provided. If just the command name is provided on the command\n"
671"line, then the regular expressions and substitutions can be entered on separate\n"
672" lines, followed by an empty line to terminate the command definition.\n"
673"\n"
674"EXAMPLES\n"
675"\n"
676"The following example with define a regular expression command named 'f' that\n"
677"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
678"a number follows 'f':\n"
679"(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
680 );
Greg Claytond12aeab2011-04-20 16:37:46 +0000681 }
682
683 ~CommandObjectCommandsAddRegex()
684 {
685 }
686
687
688 bool
689 Execute (Args& args, CommandReturnObject &result)
690 {
Greg Clayton40e48242011-04-20 22:55:21 +0000691 const size_t argc = args.GetArgumentCount();
692 if (argc == 0)
Greg Claytond12aeab2011-04-20 16:37:46 +0000693 {
Greg Clayton40e48242011-04-20 22:55:21 +0000694 result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
695 result.SetStatus (eReturnStatusFailed);
696 }
697 else
698 {
699 Error error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000700 const char *name = args.GetArgumentAtIndex(0);
Greg Claytond12aeab2011-04-20 16:37:46 +0000701 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
702 name,
703 m_options.GetHelp (),
704 m_options.GetSyntax (),
705 10));
Greg Clayton40e48242011-04-20 22:55:21 +0000706
707 if (argc == 1)
Greg Claytond12aeab2011-04-20 16:37:46 +0000708 {
Greg Clayton40e48242011-04-20 22:55:21 +0000709 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
710 if (reader_sp)
711 {
712 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
Greg Claytond12aeab2011-04-20 16:37:46 +0000713 this, // baton
714 eInputReaderGranularityLine, // token size, to pass to callback function
Greg Clayton40e48242011-04-20 22:55:21 +0000715 NULL, // end token
Greg Claytond12aeab2011-04-20 16:37:46 +0000716 "> ", // prompt
Greg Clayton40e48242011-04-20 22:55:21 +0000717 true); // echo input
718 if (error.Success())
719 {
720 m_interpreter.GetDebugger().PushInputReader (reader_sp);
721 result.SetStatus (eReturnStatusSuccessFinishNoResult);
722 return true;
723 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000724 }
725 }
Greg Clayton40e48242011-04-20 22:55:21 +0000726 else
727 {
728 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
729 {
730 llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
731 error = AppendRegexSubstitution (arg_strref);
732 if (error.Fail())
733 break;
734 }
735
736 if (error.Success())
737 {
738 AddRegexCommandToInterpreter();
739 }
740 }
741 if (error.Fail())
742 {
743 result.AppendError (error.AsCString());
744 result.SetStatus (eReturnStatusFailed);
745 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000746 }
Greg Clayton40e48242011-04-20 22:55:21 +0000747
Greg Claytond12aeab2011-04-20 16:37:46 +0000748 return result.Succeeded();
749 }
750
Greg Clayton40e48242011-04-20 22:55:21 +0000751 Error
752 AppendRegexSubstitution (const llvm::StringRef &regex_sed)
Greg Claytond12aeab2011-04-20 16:37:46 +0000753 {
Greg Clayton40e48242011-04-20 22:55:21 +0000754 Error error;
755
756 if (m_regex_cmd_ap.get() == NULL)
Greg Claytond12aeab2011-04-20 16:37:46 +0000757 {
Greg Clayton40e48242011-04-20 22:55:21 +0000758 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
759 (int)regex_sed.size(),
760 regex_sed.data());
761 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000762 }
Greg Clayton40e48242011-04-20 22:55:21 +0000763
764 size_t regex_sed_size = regex_sed.size();
765
766 if (regex_sed_size <= 1)
767 {
768 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
769 (int)regex_sed.size(),
770 regex_sed.data());
771 return error;
772 }
773
774 if (regex_sed[0] != 's')
775 {
776 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
777 (int)regex_sed.size(),
778 regex_sed.data());
779 return error;
780 }
781 const size_t first_separator_char_pos = 1;
782 // use the char that follows 's' as the regex separator character
783 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
784 const char separator_char = regex_sed[first_separator_char_pos];
785 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
786
787 if (second_separator_char_pos == std::string::npos)
788 {
789 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
790 separator_char,
791 (int)(regex_sed.size() - first_separator_char_pos - 1),
792 regex_sed.data() + (first_separator_char_pos + 1));
793 return error;
794 }
795
796 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
797
798 if (third_separator_char_pos == std::string::npos)
799 {
800 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
801 separator_char,
802 (int)(regex_sed.size() - second_separator_char_pos - 1),
803 regex_sed.data() + (second_separator_char_pos + 1));
804 return error;
805 }
806
807 if (third_separator_char_pos != regex_sed_size - 1)
808 {
809 // Make sure that everything that follows the last regex
810 // separator char
811 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
812 {
813 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
814 (int)third_separator_char_pos + 1,
815 regex_sed.data(),
816 (int)(regex_sed.size() - third_separator_char_pos - 1),
817 regex_sed.data() + (third_separator_char_pos + 1));
818 return error;
819 }
820
821 }
822 else if (first_separator_char_pos + 1 == second_separator_char_pos)
823 {
824 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
825 separator_char,
826 separator_char,
827 separator_char,
828 (int)regex_sed.size(),
829 regex_sed.data());
830 return error;
831 }
832 else if (second_separator_char_pos + 1 == third_separator_char_pos)
833 {
834 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
835 separator_char,
836 separator_char,
837 separator_char,
838 (int)regex_sed.size(),
839 regex_sed.data());
840 return error;
841 }
842 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
843 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
844 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
845 subst.c_str());
846 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000847 }
848
849 void
Greg Clayton40e48242011-04-20 22:55:21 +0000850 AddRegexCommandToInterpreter()
Greg Claytond12aeab2011-04-20 16:37:46 +0000851 {
852 if (m_regex_cmd_ap.get())
853 {
854 if (m_regex_cmd_ap->HasRegexEntries())
855 {
856 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
857 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
858 }
859 }
860 }
861
Greg Clayton40e48242011-04-20 22:55:21 +0000862 void
863 InputReaderDidCancel()
864 {
865 m_regex_cmd_ap.reset();
866 }
867
Greg Claytond12aeab2011-04-20 16:37:46 +0000868 static size_t
869 InputReaderCallback (void *baton,
870 InputReader &reader,
871 lldb::InputReaderAction notification,
872 const char *bytes,
873 size_t bytes_len);
874private:
875 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
876
877 class CommandOptions : public Options
878 {
879 public:
880
881 CommandOptions (CommandInterpreter &interpreter) :
882 Options (interpreter)
883 {
884 }
885
886 virtual
887 ~CommandOptions (){}
888
889 virtual Error
890 SetOptionValue (uint32_t option_idx, const char *option_arg)
891 {
892 Error error;
893 char short_option = (char) m_getopt_table[option_idx].val;
894
895 switch (short_option)
896 {
897 case 'h':
898 m_help.assign (option_arg);
899 break;
900 case 's':
901 m_syntax.assign (option_arg);
902 break;
903
904 default:
905 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
906 break;
907 }
908
909 return error;
910 }
911
912 void
913 OptionParsingStarting ()
914 {
915 m_help.clear();
916 m_syntax.clear();
917 }
918
919 const OptionDefinition*
920 GetDefinitions ()
921 {
922 return g_option_table;
923 }
924
925 // Options table: Required for subclasses of Options.
926
927 static OptionDefinition g_option_table[];
928
929 const char *
930 GetHelp ()
931 {
932 if (m_help.empty())
933 return NULL;
934 return m_help.c_str();
935 }
936 const char *
937 GetSyntax ()
938 {
939 if (m_syntax.empty())
940 return NULL;
941 return m_syntax.c_str();
942 }
943 // Instance variables to hold the values for command options.
944 protected:
945 std::string m_help;
946 std::string m_syntax;
947 };
948
949 CommandOptions m_options;
950
951 virtual Options *
952 GetOptions ()
953 {
954 return &m_options;
955 }
956
957};
958
959size_t
960CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
961 InputReader &reader,
962 lldb::InputReaderAction notification,
963 const char *bytes,
964 size_t bytes_len)
965{
966 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
967
968 switch (notification)
969 {
970 case eInputReaderActivate:
Greg Clayton40e48242011-04-20 22:55:21 +0000971 reader.GetDebugger().GetOutputStream().Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
Greg Claytond12aeab2011-04-20 16:37:46 +0000972 break;
973 case eInputReaderReactivate:
974 break;
975
976 case eInputReaderDeactivate:
977 break;
978
979 case eInputReaderGotToken:
Greg Clayton40e48242011-04-20 22:55:21 +0000980 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
981 --bytes_len;
Greg Claytond12aeab2011-04-20 16:37:46 +0000982 if (bytes_len == 0)
983 reader.SetIsDone(true);
984 else if (bytes)
985 {
Greg Clayton40e48242011-04-20 22:55:21 +0000986 llvm::StringRef bytes_strref (bytes, bytes_len);
987 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
988 if (error.Fail())
Greg Claytond12aeab2011-04-20 16:37:46 +0000989 {
Greg Clayton40e48242011-04-20 22:55:21 +0000990 reader.GetDebugger().GetOutputStream().Printf("error: %s\n", error.AsCString());
991 add_regex_cmd->InputReaderDidCancel ();
992 reader.SetIsDone (true);
Greg Claytond12aeab2011-04-20 16:37:46 +0000993 }
994 }
995 break;
996
997 case eInputReaderInterrupt:
998 reader.SetIsDone (true);
999 reader.GetDebugger().GetOutputStream().PutCString("Regular expression command creations was cancelled.\n");
Greg Clayton40e48242011-04-20 22:55:21 +00001000 add_regex_cmd->InputReaderDidCancel ();
Greg Claytond12aeab2011-04-20 16:37:46 +00001001 break;
1002
1003 case eInputReaderEndOfFile:
1004 reader.SetIsDone (true);
1005 break;
1006
1007 case eInputReaderDone:
Greg Clayton40e48242011-04-20 22:55:21 +00001008 add_regex_cmd->AddRegexCommandToInterpreter();
Greg Claytond12aeab2011-04-20 16:37:46 +00001009 break;
1010 }
1011
1012 return bytes_len;
1013}
1014
1015
1016OptionDefinition
1017CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1018{
Greg Clayton40e48242011-04-20 22:55:21 +00001019{ LLDB_OPT_SET_1, false, "help" , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
Greg Claytond12aeab2011-04-20 16:37:46 +00001020{ LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
Greg Clayton40e48242011-04-20 22:55:21 +00001021{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Greg Claytond12aeab2011-04-20 16:37:46 +00001022};
1023
1024
Jim Ingham767af882010-07-07 03:36:20 +00001025#pragma mark CommandObjectMultiwordCommands
1026
1027//-------------------------------------------------------------------------
1028// CommandObjectMultiwordCommands
1029//-------------------------------------------------------------------------
1030
1031CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001032 CommandObjectMultiword (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +00001033 "command",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001034 "A set of commands for managing or customizing the debugger commands.",
Greg Clayton40e48242011-04-20 22:55:21 +00001035 "command <subcommand> [<subcommand-options>]")
Jim Ingham767af882010-07-07 03:36:20 +00001036{
Greg Clayton238c0a12010-09-18 01:14:36 +00001037 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1038 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1039 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +00001040 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +00001041}
1042
1043CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1044{
1045}
1046