blob: ba81f28ef2ef13ab58662df02e2d355ff8b23472 [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"
Enrico Granatac2a28252011-08-16 16:49:25 +000020#include "lldb/Core/InputReaderEZ.h"
21#include "lldb/Core/StringList.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000022#include "lldb/Interpreter/Args.h"
Jim Ingham767af882010-07-07 03:36:20 +000023#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000024#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Jim Ingham767af882010-07-07 03:36:20 +000025#include "lldb/Interpreter/CommandReturnObject.h"
26#include "lldb/Interpreter/Options.h"
Enrico Granatae5e34cb2011-08-17 01:30:04 +000027#include "lldb/Interpreter/ScriptInterpreter.h"
28#include "lldb/Interpreter/ScriptInterpreterPython.h"
Jim Ingham767af882010-07-07 03:36:20 +000029
30using namespace lldb;
31using namespace lldb_private;
32
Jim Ingham767af882010-07-07 03:36:20 +000033//-------------------------------------------------------------------------
34// CommandObjectCommandsSource
35//-------------------------------------------------------------------------
36
Jim Ingham6247dbe2011-07-12 03:12:18 +000037class CommandObjectCommandsHistory : public CommandObject
38{
39private:
40
41 class CommandOptions : public Options
42 {
43 public:
44
45 CommandOptions (CommandInterpreter &interpreter) :
46 Options (interpreter)
47 {
48 }
49
50 virtual
51 ~CommandOptions (){}
52
53 virtual Error
54 SetOptionValue (uint32_t option_idx, const char *option_arg)
55 {
56 Error error;
57 char short_option = (char) m_getopt_table[option_idx].val;
58 bool success;
59
60 switch (short_option)
61 {
62 case 'c':
63 m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
64 if (!success)
65 error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
66 if (m_end_idx != 0)
67 m_end_idx--;
68 m_start_idx = 0;
69 break;
70 case 'e':
71 m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
72 if (!success)
73 error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
74 break;
75 case 's':
76 m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
77 if (!success)
78 error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
79 break;
80 default:
81 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
82 break;
83 }
84
85 return error;
86 }
87
88 void
89 OptionParsingStarting ()
90 {
91 m_start_idx = 0;
92 m_end_idx = UINT_MAX;
93 }
94
95 const OptionDefinition*
96 GetDefinitions ()
97 {
98 return g_option_table;
99 }
100
101 // Options table: Required for subclasses of Options.
102
103 static OptionDefinition g_option_table[];
104
105 // Instance variables to hold the values for command options.
106
107 uint32_t m_start_idx;
108 uint32_t m_end_idx;
109 };
110
111 CommandOptions m_options;
112
113 virtual Options *
114 GetOptions ()
115 {
116 return &m_options;
117 }
118
119public:
120 CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
121 CommandObject (interpreter,
122 "command history",
123 "Dump the history of commands in this session.",
124 NULL),
125 m_options (interpreter)
126 {
127 }
128
129 ~CommandObjectCommandsHistory ()
130 {
131 }
132
133 bool
134 Execute
135 (
136 Args& args,
137 CommandReturnObject &result
138 )
139 {
140
141 m_interpreter.DumpHistory (result.GetOutputStream(),
142 m_options.m_start_idx,
143 m_options.m_end_idx);
144 return result.Succeeded();
145
146 }
147};
148
149OptionDefinition
150CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
151{
152{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
153{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands."},
154{ LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
155{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
156};
157
158
159//-------------------------------------------------------------------------
160// CommandObjectCommandsSource
161//-------------------------------------------------------------------------
162
Jim Ingham767af882010-07-07 03:36:20 +0000163class CommandObjectCommandsSource : public CommandObject
164{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000165private:
166
167 class CommandOptions : public Options
168 {
169 public:
170
Greg Claytonf15996e2011-04-07 22:46:35 +0000171 CommandOptions (CommandInterpreter &interpreter) :
172 Options (interpreter)
173 {
174 }
Jim Ingham949d5ac2011-02-18 00:54:25 +0000175
176 virtual
177 ~CommandOptions (){}
178
179 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000180 SetOptionValue (uint32_t option_idx, const char *option_arg)
Jim Ingham949d5ac2011-02-18 00:54:25 +0000181 {
182 Error error;
183 char short_option = (char) m_getopt_table[option_idx].val;
184 bool success;
185
186 switch (short_option)
187 {
188 case 'e':
189 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
190 if (!success)
191 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
192 break;
193 case 'c':
194 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
195 if (!success)
196 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
197 break;
198 default:
199 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
200 break;
201 }
202
203 return error;
204 }
205
206 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000207 OptionParsingStarting ()
Jim Ingham949d5ac2011-02-18 00:54:25 +0000208 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000209 m_stop_on_error = true;
210 m_stop_on_continue = true;
211 }
212
Greg Claytonb3448432011-03-24 21:19:54 +0000213 const OptionDefinition*
Jim Ingham949d5ac2011-02-18 00:54:25 +0000214 GetDefinitions ()
215 {
216 return g_option_table;
217 }
218
219 // Options table: Required for subclasses of Options.
220
Greg Claytonb3448432011-03-24 21:19:54 +0000221 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +0000222
223 // Instance variables to hold the values for command options.
224
225 bool m_stop_on_error;
226 bool m_stop_on_continue;
227 };
228
Jim Ingham949d5ac2011-02-18 00:54:25 +0000229 CommandOptions m_options;
230
231 virtual Options *
232 GetOptions ()
233 {
234 return &m_options;
235 }
236
Jim Ingham767af882010-07-07 03:36:20 +0000237public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000238 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
239 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000240 "command source",
Greg Clayton238c0a12010-09-18 01:14:36 +0000241 "Read in debugger commands from the file <filename> and execute them.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000242 NULL),
243 m_options (interpreter)
Jim Ingham767af882010-07-07 03:36:20 +0000244 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000245 CommandArgumentEntry arg;
246 CommandArgumentData file_arg;
247
248 // Define the first (and only) variant of this arg.
249 file_arg.arg_type = eArgTypeFilename;
250 file_arg.arg_repetition = eArgRepeatPlain;
251
252 // There is only one variant this argument could be; put it into the argument entry.
253 arg.push_back (file_arg);
254
255 // Push the data for the first argument into the m_arguments vector.
256 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000257 }
258
259 ~CommandObjectCommandsSource ()
260 {
261 }
262
263 bool
264 Execute
265 (
Jim Ingham767af882010-07-07 03:36:20 +0000266 Args& args,
267 CommandReturnObject &result
268 )
269 {
270 const int argc = args.GetArgumentCount();
271 if (argc == 1)
272 {
273 const char *filename = args.GetArgumentAtIndex(0);
Jim Ingham767af882010-07-07 03:36:20 +0000274
275 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
276
Johnny Chena83ea882010-10-20 21:40:50 +0000277 FileSpec cmd_file (filename, true);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000278 ExecutionContext *exe_ctx = NULL; // Just use the default context.
279 bool echo_commands = true;
280 bool print_results = true;
Jim Ingham767af882010-07-07 03:36:20 +0000281
Jim Ingham949d5ac2011-02-18 00:54:25 +0000282 m_interpreter.HandleCommandsFromFile (cmd_file,
283 exe_ctx,
284 m_options.m_stop_on_continue,
285 m_options.m_stop_on_error,
286 echo_commands,
287 print_results,
288 result);
Jim Ingham767af882010-07-07 03:36:20 +0000289 }
290 else
291 {
292 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
293 result.SetStatus (eReturnStatusFailed);
294 }
295 return result.Succeeded();
296
297 }
298};
299
Greg Claytonb3448432011-03-24 21:19:54 +0000300OptionDefinition
Jim Ingham949d5ac2011-02-18 00:54:25 +0000301CommandObjectCommandsSource::CommandOptions::g_option_table[] =
302{
303{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
304{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
305{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
306};
307
Jim Ingham767af882010-07-07 03:36:20 +0000308#pragma mark CommandObjectCommandsAlias
309//-------------------------------------------------------------------------
310// CommandObjectCommandsAlias
311//-------------------------------------------------------------------------
312
Enrico Granatac2a28252011-08-16 16:49:25 +0000313static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
314 "You must define a Python function with this signature:\n"
Enrico Granata6b1596d2011-08-16 23:24:13 +0000315 "def my_command_impl(debugger, args, result, dict):";
Enrico Granatac2a28252011-08-16 16:49:25 +0000316
317
Jim Ingham767af882010-07-07 03:36:20 +0000318class CommandObjectCommandsAlias : public CommandObject
319{
Enrico Granatac2a28252011-08-16 16:49:25 +0000320
Enrico Granatac2a28252011-08-16 16:49:25 +0000321
Jim Ingham767af882010-07-07 03:36:20 +0000322public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000323 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
324 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000325 "command alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000326 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000327 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000328 {
329 SetHelpLong(
330 "'alias' allows the user to create a short-cut or abbreviation for long \n\
331 commands, multi-word commands, and commands that take particular options. \n\
332 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000333 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
334 // command. \n\
335 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
336 // command. Since breakpoint commands are two-word \n\
337 // commands, the user will still need to enter the \n\
338 // second word after 'bp', e.g. 'bp enable' or \n\
339 // 'bp delete'. \n\
340 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
341 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000342 \nAn alias can include some options for the command, with the values either \n\
343 filled in at the time the alias is created, or specified as positional \n\
344 arguments, to be filled in when the alias is invoked. The following example \n\
345 shows how to create aliases with options: \n\
346 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000347 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000348 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
349 options already part of the alias. So if the user wants to set a breakpoint \n\
350 by file and line without explicitly having to use the -f and -l options, the \n\
351 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
352 for the actual arguments that will be passed when the alias command is used. \n\
353 The number in the placeholder refers to the position/order the actual value \n\
Jim Ingham536f6332011-08-18 02:29:05 +0000354 occupies when the alias is used. All the occurrences of '%1' in the alias \n\
Jim Ingham767af882010-07-07 03:36:20 +0000355 will be replaced with the first argument, all the occurrences of '%2' in the \n\
356 alias will be replaced with the second argument, and so on. This also allows \n\
357 actual arguments to be used multiple times within an alias (see 'process \n\
Jim Ingham536f6332011-08-18 02:29:05 +0000358 launch' example below). \n\
359 Note: the positional arguments must substitute as whole words in the resultant\n\
360 command, so you can't at present do something like:\n\
361 \n\
362 commands alias bcppfl breakpoint set -f %1.cpp -l %2\n\
363 \n\
364 to get the file extension \".cpp\" automatically appended. For more complex\n\
365 aliasing, use the \"command regex\" command instead.\n\
366 \nSo in the 'bfl' case, the actual file value will be \n\
Jim Ingham767af882010-07-07 03:36:20 +0000367 filled in with the first argument following 'bfl' and the actual line number \n\
368 value will be filled in with the second argument. The user would use this \n\
369 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000370 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000371 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000372 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000373 \nThis would be the same as if the user had entered \n\
374 'breakpoint set -f my-file.c -l 137'. \n\
375 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000376 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
377 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000378 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000379 \nIf the user always wanted to pass the same value to a particular option, the \n\
380 alias could be defined with that value directly in the alias as a constant, \n\
381 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000382 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
383 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000384
Caroline Tice43b014a2010-10-04 22:28:36 +0000385 CommandArgumentEntry arg1;
386 CommandArgumentEntry arg2;
387 CommandArgumentEntry arg3;
388 CommandArgumentData alias_arg;
389 CommandArgumentData cmd_arg;
390 CommandArgumentData options_arg;
391
392 // Define the first (and only) variant of this arg.
393 alias_arg.arg_type = eArgTypeAliasName;
394 alias_arg.arg_repetition = eArgRepeatPlain;
395
396 // There is only one variant this argument could be; put it into the argument entry.
397 arg1.push_back (alias_arg);
398
399 // Define the first (and only) variant of this arg.
400 cmd_arg.arg_type = eArgTypeCommandName;
401 cmd_arg.arg_repetition = eArgRepeatPlain;
402
403 // There is only one variant this argument could be; put it into the argument entry.
404 arg2.push_back (cmd_arg);
405
406 // Define the first (and only) variant of this arg.
407 options_arg.arg_type = eArgTypeAliasOptions;
408 options_arg.arg_repetition = eArgRepeatOptional;
409
410 // There is only one variant this argument could be; put it into the argument entry.
411 arg3.push_back (options_arg);
412
413 // Push the data for the first argument into the m_arguments vector.
414 m_arguments.push_back (arg1);
415 m_arguments.push_back (arg2);
416 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000417 }
418
419 ~CommandObjectCommandsAlias ()
420 {
421 }
422
Caroline Ticee0da7a52010-12-09 22:52:49 +0000423 bool
424 WantsRawCommandString ()
425 {
426 return true;
427 }
428
429 bool
430 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
431 {
432 Args args (raw_command_line);
433 std::string raw_command_string (raw_command_line);
434
435 size_t argc = args.GetArgumentCount();
436
437 if (argc < 2)
438 {
439 result.AppendError ("'alias' requires at least two arguments");
440 result.SetStatus (eReturnStatusFailed);
441 return false;
442 }
443
444 // Get the alias command.
445
446 const std::string alias_command = args.GetArgumentAtIndex (0);
Enrico Granatac2a28252011-08-16 16:49:25 +0000447
Caroline Ticee0da7a52010-12-09 22:52:49 +0000448 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
449 // does the stripping itself.
450 size_t pos = raw_command_string.find (alias_command);
451 if (pos == 0)
452 {
453 raw_command_string = raw_command_string.substr (alias_command.size());
454 pos = raw_command_string.find_first_not_of (' ');
455 if ((pos != std::string::npos) && (pos > 0))
456 raw_command_string = raw_command_string.substr (pos);
457 }
458 else
459 {
460 result.AppendError ("Error parsing command string. No alias created.");
461 result.SetStatus (eReturnStatusFailed);
462 return false;
463 }
464
465
466 // Verify that the command is alias-able.
467 if (m_interpreter.CommandExists (alias_command.c_str()))
468 {
469 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
470 alias_command.c_str());
471 result.SetStatus (eReturnStatusFailed);
472 return false;
473 }
474
475 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
476 // raw_command_string is returned with the name of the command object stripped off the front.
477 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
478
479 if (!cmd_obj)
480 {
481 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
482 " No alias created.", raw_command_string.c_str());
483 result.SetStatus (eReturnStatusFailed);
484 return false;
485 }
486 else if (!cmd_obj->WantsRawCommandString ())
487 {
488 // Note that args was initialized with the original command, and has not been updated to this point.
489 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
490 return Execute (args, result);
491 }
492 else
493 {
494 // Verify & handle any options/arguments passed to the alias command
495
496 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
497 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
498
Caroline Tice5ddbe212011-05-06 21:37:15 +0000499 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
500
501 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
Caroline Ticee0da7a52010-12-09 22:52:49 +0000502 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000503 result.AppendError ("Unable to create requested alias.\n");
504 result.SetStatus (eReturnStatusFailed);
505 return false;
Caroline Ticee0da7a52010-12-09 22:52:49 +0000506 }
507
508 // Create the alias
509 if (m_interpreter.AliasExists (alias_command.c_str())
510 || m_interpreter.UserCommandExists (alias_command.c_str()))
511 {
512 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
513 if (temp_option_arg_sp.get())
514 {
515 if (option_arg_vector->size() == 0)
516 m_interpreter.RemoveAliasOptions (alias_command.c_str());
517 }
518 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
519 alias_command.c_str());
520 }
521
Caroline Tice56d2fc42010-12-14 18:51:39 +0000522 if (cmd_obj_sp)
523 {
524 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
525 if (option_arg_vector->size() > 0)
526 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
527 result.SetStatus (eReturnStatusSuccessFinishNoResult);
528 }
529 else
530 {
531 result.AppendError ("Unable to create requested alias.\n");
532 result.SetStatus (eReturnStatusFailed);
533 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000534 }
535 return result.Succeeded();
536 }
Jim Ingham767af882010-07-07 03:36:20 +0000537
538 bool
539 Execute
540 (
Jim Ingham767af882010-07-07 03:36:20 +0000541 Args& args,
542 CommandReturnObject &result
543 )
544 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000545 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000546
547 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000548 {
Jim Ingham767af882010-07-07 03:36:20 +0000549 result.AppendError ("'alias' requires at least two arguments");
550 result.SetStatus (eReturnStatusFailed);
551 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000552 }
Jim Ingham767af882010-07-07 03:36:20 +0000553
554 const std::string alias_command = args.GetArgumentAtIndex(0);
555 const std::string actual_command = args.GetArgumentAtIndex(1);
556
557 args.Shift(); // Shift the alias command word off the argument vector.
558 args.Shift(); // Shift the old command word off the argument vector.
559
560 // Verify that the command is alias'able, and get the appropriate command object.
561
Greg Clayton238c0a12010-09-18 01:14:36 +0000562 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000563 {
564 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
565 alias_command.c_str());
566 result.SetStatus (eReturnStatusFailed);
567 }
568 else
569 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000570 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000571 CommandObjectSP subcommand_obj_sp;
572 bool use_subcommand = false;
573 if (command_obj_sp.get())
574 {
575 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000576 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000577 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
578 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
579
Caroline Ticee0da7a52010-12-09 22:52:49 +0000580 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000581 {
582 if (argc >= 3)
583 {
584 const std::string sub_command = args.GetArgumentAtIndex(0);
585 assert (sub_command.length() != 0);
586 subcommand_obj_sp =
587 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
588 if (subcommand_obj_sp.get())
589 {
590 sub_cmd_obj = subcommand_obj_sp.get();
591 use_subcommand = true;
592 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000593 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000594 }
595 else
596 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000597 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
598 "Unable to create alias.\n",
599 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000600 result.SetStatus (eReturnStatusFailed);
601 return false;
602 }
603 }
604 }
605
606 // Verify & handle any options/arguments passed to the alias command
607
608 if (args.GetArgumentCount () > 0)
609 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000610 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
611 if (use_subcommand)
612 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
613
614 std::string args_string;
615 args.GetCommandString (args_string);
616
617 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
618 {
619 result.AppendError ("Unable to create requested alias.\n");
620 result.SetStatus (eReturnStatusFailed);
621 return false;
622 }
Jim Ingham767af882010-07-07 03:36:20 +0000623 }
624
625 // Create the alias.
626
Greg Clayton238c0a12010-09-18 01:14:36 +0000627 if (m_interpreter.AliasExists (alias_command.c_str())
628 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000629 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000630 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000631 if (tmp_option_arg_sp.get())
632 {
633 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000634 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000635 }
636 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
637 alias_command.c_str());
638 }
639
640 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000641 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000642 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000643 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000644 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000645 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000646 result.SetStatus (eReturnStatusSuccessFinishNoResult);
647 }
648 else
649 {
650 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
651 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000652 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000653 }
654 }
655
656 return result.Succeeded();
657 }
658};
659
660#pragma mark CommandObjectCommandsUnalias
661//-------------------------------------------------------------------------
662// CommandObjectCommandsUnalias
663//-------------------------------------------------------------------------
664
665class CommandObjectCommandsUnalias : public CommandObject
666{
667public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000668 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
669 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000670 "command unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000671 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000672 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000673 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000674 CommandArgumentEntry arg;
675 CommandArgumentData alias_arg;
676
677 // Define the first (and only) variant of this arg.
678 alias_arg.arg_type = eArgTypeAliasName;
679 alias_arg.arg_repetition = eArgRepeatPlain;
680
681 // There is only one variant this argument could be; put it into the argument entry.
682 arg.push_back (alias_arg);
683
684 // Push the data for the first argument into the m_arguments vector.
685 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000686 }
687
688 ~CommandObjectCommandsUnalias()
689 {
690 }
691
692
693 bool
694 Execute
695 (
Jim Ingham767af882010-07-07 03:36:20 +0000696 Args& args,
697 CommandReturnObject &result
698 )
699 {
700 CommandObject::CommandMap::iterator pos;
701 CommandObject *cmd_obj;
702
703 if (args.GetArgumentCount() != 0)
704 {
705 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000706 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000707 if (cmd_obj)
708 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000709 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000710 {
711 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
712 command_name);
713 result.SetStatus (eReturnStatusFailed);
714 }
715 else
716 {
717
Greg Clayton238c0a12010-09-18 01:14:36 +0000718 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000719 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000720 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000721 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
722 command_name);
723 else
724 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
725 result.SetStatus (eReturnStatusFailed);
726 }
727 else
728 result.SetStatus (eReturnStatusSuccessFinishNoResult);
729 }
730 }
731 else
732 {
733 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
734 "current list of commands.\n",
735 command_name);
736 result.SetStatus (eReturnStatusFailed);
737 }
738 }
739 else
740 {
741 result.AppendError ("must call 'unalias' with a valid alias");
742 result.SetStatus (eReturnStatusFailed);
743 }
744
745 return result.Succeeded();
746 }
747};
748
Greg Claytond12aeab2011-04-20 16:37:46 +0000749#pragma mark CommandObjectCommandsAddRegex
750//-------------------------------------------------------------------------
751// CommandObjectCommandsAddRegex
752//-------------------------------------------------------------------------
753
754class CommandObjectCommandsAddRegex : public CommandObject
755{
756public:
757 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
758 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000759 "command regex",
Greg Claytond12aeab2011-04-20 16:37:46 +0000760 "Allow the user to create a regular expression command.",
Greg Clayton40e48242011-04-20 22:55:21 +0000761 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
Greg Claytond12aeab2011-04-20 16:37:46 +0000762 m_options (interpreter)
763 {
Greg Clayton40e48242011-04-20 22:55:21 +0000764 SetHelpLong(
765"This command allows the user to create powerful regular expression commands\n"
766"with substitutions. The regular expressions and substitutions are specified\n"
767"using the regular exression substitution format of:\n"
768"\n"
769" s/<regex>/<subst>/\n"
770"\n"
771"<regex> is a regular expression that can use parenthesis to capture regular\n"
772"expression input and substitute the captured matches in the output using %1\n"
773"for the first match, %2 for the second, and so on.\n"
774"\n"
775"The regular expressions can all be specified on the command line if more than\n"
776"one argument is provided. If just the command name is provided on the command\n"
777"line, then the regular expressions and substitutions can be entered on separate\n"
778" lines, followed by an empty line to terminate the command definition.\n"
779"\n"
780"EXAMPLES\n"
781"\n"
782"The following example with define a regular expression command named 'f' that\n"
783"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
784"a number follows 'f':\n"
785"(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
786 );
Greg Claytond12aeab2011-04-20 16:37:46 +0000787 }
788
789 ~CommandObjectCommandsAddRegex()
790 {
791 }
792
793
794 bool
795 Execute (Args& args, CommandReturnObject &result)
796 {
Greg Clayton40e48242011-04-20 22:55:21 +0000797 const size_t argc = args.GetArgumentCount();
798 if (argc == 0)
Greg Claytond12aeab2011-04-20 16:37:46 +0000799 {
Greg Clayton40e48242011-04-20 22:55:21 +0000800 result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
801 result.SetStatus (eReturnStatusFailed);
802 }
803 else
804 {
805 Error error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000806 const char *name = args.GetArgumentAtIndex(0);
Greg Claytond12aeab2011-04-20 16:37:46 +0000807 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
808 name,
809 m_options.GetHelp (),
810 m_options.GetSyntax (),
811 10));
Greg Clayton40e48242011-04-20 22:55:21 +0000812
813 if (argc == 1)
Greg Claytond12aeab2011-04-20 16:37:46 +0000814 {
Greg Clayton40e48242011-04-20 22:55:21 +0000815 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
816 if (reader_sp)
817 {
818 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
Greg Claytond12aeab2011-04-20 16:37:46 +0000819 this, // baton
820 eInputReaderGranularityLine, // token size, to pass to callback function
Greg Clayton40e48242011-04-20 22:55:21 +0000821 NULL, // end token
Greg Claytond12aeab2011-04-20 16:37:46 +0000822 "> ", // prompt
Greg Clayton40e48242011-04-20 22:55:21 +0000823 true); // echo input
824 if (error.Success())
825 {
826 m_interpreter.GetDebugger().PushInputReader (reader_sp);
827 result.SetStatus (eReturnStatusSuccessFinishNoResult);
828 return true;
829 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000830 }
831 }
Greg Clayton40e48242011-04-20 22:55:21 +0000832 else
833 {
834 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
835 {
836 llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
837 error = AppendRegexSubstitution (arg_strref);
838 if (error.Fail())
839 break;
840 }
841
842 if (error.Success())
843 {
844 AddRegexCommandToInterpreter();
845 }
846 }
847 if (error.Fail())
848 {
849 result.AppendError (error.AsCString());
850 result.SetStatus (eReturnStatusFailed);
851 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000852 }
Greg Clayton40e48242011-04-20 22:55:21 +0000853
Greg Claytond12aeab2011-04-20 16:37:46 +0000854 return result.Succeeded();
855 }
856
Greg Clayton40e48242011-04-20 22:55:21 +0000857 Error
858 AppendRegexSubstitution (const llvm::StringRef &regex_sed)
Greg Claytond12aeab2011-04-20 16:37:46 +0000859 {
Greg Clayton40e48242011-04-20 22:55:21 +0000860 Error error;
861
862 if (m_regex_cmd_ap.get() == NULL)
Greg Claytond12aeab2011-04-20 16:37:46 +0000863 {
Greg Clayton40e48242011-04-20 22:55:21 +0000864 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
865 (int)regex_sed.size(),
866 regex_sed.data());
867 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000868 }
Greg Clayton40e48242011-04-20 22:55:21 +0000869
870 size_t regex_sed_size = regex_sed.size();
871
872 if (regex_sed_size <= 1)
873 {
874 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
875 (int)regex_sed.size(),
876 regex_sed.data());
877 return error;
878 }
879
880 if (regex_sed[0] != 's')
881 {
882 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
883 (int)regex_sed.size(),
884 regex_sed.data());
885 return error;
886 }
887 const size_t first_separator_char_pos = 1;
888 // use the char that follows 's' as the regex separator character
889 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
890 const char separator_char = regex_sed[first_separator_char_pos];
891 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
892
893 if (second_separator_char_pos == std::string::npos)
894 {
895 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
896 separator_char,
897 (int)(regex_sed.size() - first_separator_char_pos - 1),
898 regex_sed.data() + (first_separator_char_pos + 1));
899 return error;
900 }
901
902 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
903
904 if (third_separator_char_pos == std::string::npos)
905 {
906 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
907 separator_char,
908 (int)(regex_sed.size() - second_separator_char_pos - 1),
909 regex_sed.data() + (second_separator_char_pos + 1));
910 return error;
911 }
912
913 if (third_separator_char_pos != regex_sed_size - 1)
914 {
915 // Make sure that everything that follows the last regex
916 // separator char
917 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
918 {
919 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
920 (int)third_separator_char_pos + 1,
921 regex_sed.data(),
922 (int)(regex_sed.size() - third_separator_char_pos - 1),
923 regex_sed.data() + (third_separator_char_pos + 1));
924 return error;
925 }
926
927 }
928 else if (first_separator_char_pos + 1 == second_separator_char_pos)
929 {
930 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
931 separator_char,
932 separator_char,
933 separator_char,
934 (int)regex_sed.size(),
935 regex_sed.data());
936 return error;
937 }
938 else if (second_separator_char_pos + 1 == third_separator_char_pos)
939 {
940 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
941 separator_char,
942 separator_char,
943 separator_char,
944 (int)regex_sed.size(),
945 regex_sed.data());
946 return error;
947 }
948 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
949 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
950 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
951 subst.c_str());
952 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000953 }
954
955 void
Greg Clayton40e48242011-04-20 22:55:21 +0000956 AddRegexCommandToInterpreter()
Greg Claytond12aeab2011-04-20 16:37:46 +0000957 {
958 if (m_regex_cmd_ap.get())
959 {
960 if (m_regex_cmd_ap->HasRegexEntries())
961 {
962 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
963 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
964 }
965 }
966 }
967
Greg Clayton40e48242011-04-20 22:55:21 +0000968 void
969 InputReaderDidCancel()
970 {
971 m_regex_cmd_ap.reset();
972 }
973
Greg Claytond12aeab2011-04-20 16:37:46 +0000974 static size_t
975 InputReaderCallback (void *baton,
976 InputReader &reader,
977 lldb::InputReaderAction notification,
978 const char *bytes,
979 size_t bytes_len);
980private:
981 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
982
983 class CommandOptions : public Options
984 {
985 public:
986
987 CommandOptions (CommandInterpreter &interpreter) :
988 Options (interpreter)
989 {
990 }
991
992 virtual
993 ~CommandOptions (){}
994
995 virtual Error
996 SetOptionValue (uint32_t option_idx, const char *option_arg)
997 {
998 Error error;
999 char short_option = (char) m_getopt_table[option_idx].val;
1000
1001 switch (short_option)
1002 {
1003 case 'h':
1004 m_help.assign (option_arg);
1005 break;
1006 case 's':
1007 m_syntax.assign (option_arg);
1008 break;
1009
1010 default:
1011 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1012 break;
1013 }
1014
1015 return error;
1016 }
1017
1018 void
1019 OptionParsingStarting ()
1020 {
1021 m_help.clear();
1022 m_syntax.clear();
1023 }
1024
1025 const OptionDefinition*
1026 GetDefinitions ()
1027 {
1028 return g_option_table;
1029 }
1030
1031 // Options table: Required for subclasses of Options.
1032
1033 static OptionDefinition g_option_table[];
1034
1035 const char *
1036 GetHelp ()
1037 {
1038 if (m_help.empty())
1039 return NULL;
1040 return m_help.c_str();
1041 }
1042 const char *
1043 GetSyntax ()
1044 {
1045 if (m_syntax.empty())
1046 return NULL;
1047 return m_syntax.c_str();
1048 }
1049 // Instance variables to hold the values for command options.
1050 protected:
1051 std::string m_help;
1052 std::string m_syntax;
1053 };
1054
1055 CommandOptions m_options;
1056
1057 virtual Options *
1058 GetOptions ()
1059 {
1060 return &m_options;
1061 }
1062
1063};
1064
1065size_t
1066CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1067 InputReader &reader,
1068 lldb::InputReaderAction notification,
1069 const char *bytes,
1070 size_t bytes_len)
1071{
1072 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
Caroline Tice892fadd2011-06-16 16:27:19 +00001073 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Greg Claytond12aeab2011-04-20 16:37:46 +00001074
1075 switch (notification)
1076 {
1077 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +00001078 if (!batch_mode)
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001079 {
1080 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1081 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1082 out_stream->Flush();
1083 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001084 break;
1085 case eInputReaderReactivate:
1086 break;
1087
1088 case eInputReaderDeactivate:
1089 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001090
1091 case eInputReaderAsynchronousOutputWritten:
1092 break;
1093
Greg Claytond12aeab2011-04-20 16:37:46 +00001094 case eInputReaderGotToken:
Greg Clayton40e48242011-04-20 22:55:21 +00001095 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1096 --bytes_len;
Greg Claytond12aeab2011-04-20 16:37:46 +00001097 if (bytes_len == 0)
1098 reader.SetIsDone(true);
1099 else if (bytes)
1100 {
Greg Clayton40e48242011-04-20 22:55:21 +00001101 llvm::StringRef bytes_strref (bytes, bytes_len);
1102 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1103 if (error.Fail())
Greg Claytond12aeab2011-04-20 16:37:46 +00001104 {
Caroline Tice892fadd2011-06-16 16:27:19 +00001105 if (!batch_mode)
1106 {
1107 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1108 out_stream->Printf("error: %s\n", error.AsCString());
1109 out_stream->Flush();
1110 }
Greg Clayton40e48242011-04-20 22:55:21 +00001111 add_regex_cmd->InputReaderDidCancel ();
1112 reader.SetIsDone (true);
Greg Claytond12aeab2011-04-20 16:37:46 +00001113 }
1114 }
1115 break;
1116
1117 case eInputReaderInterrupt:
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001118 {
1119 reader.SetIsDone (true);
Caroline Tice892fadd2011-06-16 16:27:19 +00001120 if (!batch_mode)
1121 {
1122 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1123 out_stream->PutCString("Regular expression command creations was cancelled.\n");
1124 out_stream->Flush();
1125 }
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001126 add_regex_cmd->InputReaderDidCancel ();
1127 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001128 break;
1129
1130 case eInputReaderEndOfFile:
1131 reader.SetIsDone (true);
1132 break;
1133
1134 case eInputReaderDone:
Greg Clayton40e48242011-04-20 22:55:21 +00001135 add_regex_cmd->AddRegexCommandToInterpreter();
Greg Claytond12aeab2011-04-20 16:37:46 +00001136 break;
1137 }
1138
1139 return bytes_len;
1140}
1141
1142
1143OptionDefinition
1144CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1145{
Greg Clayton40e48242011-04-20 22:55:21 +00001146{ 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 +00001147{ 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 +00001148{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Greg Claytond12aeab2011-04-20 16:37:46 +00001149};
1150
1151
Enrico Granata6b1596d2011-08-16 23:24:13 +00001152class CommandObjectPythonFunction : public CommandObject
1153{
1154private:
1155 std::string m_function_name;
1156
1157public:
1158
1159 CommandObjectPythonFunction (CommandInterpreter &interpreter,
1160 std::string name,
1161 std::string funct) :
1162 CommandObject (interpreter,
1163 name.c_str(),
1164 (std::string("Run Python function ") + funct).c_str(),
1165 NULL),
1166 m_function_name(funct)
1167 {
Enrico Granatae5e34cb2011-08-17 01:30:04 +00001168 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1169 if (scripter)
1170 {
1171 std::string docstring = scripter->GetDocumentationForItem(funct.c_str());
1172 if (!docstring.empty())
1173 SetHelpLong(docstring);
1174 }
Enrico Granata6b1596d2011-08-16 23:24:13 +00001175 }
1176
1177 virtual
1178 ~CommandObjectPythonFunction ()
1179 {
1180 }
1181
1182 virtual bool
1183 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
1184 {
1185 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1186
1187 Error error;
1188
1189 if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(),
1190 raw_command_line,
1191 result,
1192 error) == false)
1193 {
1194 result.AppendError(error.AsCString());
1195 result.SetStatus(eReturnStatusFailed);
1196 }
1197 else
1198 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1199
1200 return result.Succeeded();
1201 }
1202
1203 virtual bool
1204 WantsRawCommandString ()
1205 {
1206 return true;
1207 }
1208
1209 bool
1210 Execute (Args& command,
1211 CommandReturnObject &result)
1212 {
1213 std::string cmd_string;
1214 command.GetCommandString(cmd_string);
1215 return ExecuteRawCommandString(cmd_string.c_str(), result);
1216 }
1217
1218 virtual bool
1219 IsRemovable() { return true; }
1220
1221};
1222
Enrico Granata59df36f2011-10-17 21:45:27 +00001223//-------------------------------------------------------------------------
1224// CommandObjectCommandsScriptImport
1225//-------------------------------------------------------------------------
1226
1227class CommandObjectCommandsScriptImport : public CommandObject
1228{
1229public:
1230 CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
1231 CommandObject (interpreter,
1232 "command script import",
1233 "Import a scripting module in LLDB.",
1234 NULL)
1235 {
1236 CommandArgumentEntry arg1;
1237 CommandArgumentData cmd_arg;
1238
1239 // Define the first (and only) variant of this arg.
1240 cmd_arg.arg_type = eArgTypePath;
1241 cmd_arg.arg_repetition = eArgRepeatPlain;
1242
1243 // There is only one variant this argument could be; put it into the argument entry.
1244 arg1.push_back (cmd_arg);
1245
1246 // Push the data for the first argument into the m_arguments vector.
1247 m_arguments.push_back (arg1);
1248 }
1249
1250 ~CommandObjectCommandsScriptImport ()
1251 {
1252 }
1253
1254 bool
1255 Execute
1256 (
1257 Args& args,
1258 CommandReturnObject &result
1259 )
1260 {
1261
1262 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1263 {
1264 result.AppendError ("only scripting language supported for module importing is currently Python");
1265 result.SetStatus (eReturnStatusFailed);
1266 return false;
1267 }
1268
1269 size_t argc = args.GetArgumentCount();
1270
1271 if (argc != 1)
1272 {
1273 result.AppendError ("'command script import' requires one argument");
1274 result.SetStatus (eReturnStatusFailed);
1275 return false;
1276 }
1277
1278 std::string path = args.GetArgumentAtIndex(0);
1279 Error error;
1280
1281 if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
1282 error))
1283 {
1284 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1285 }
1286 else
1287 {
1288 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
1289 result.SetStatus (eReturnStatusFailed);
1290 }
1291
1292 return result.Succeeded();
1293 }
1294};
Enrico Granata6b1596d2011-08-16 23:24:13 +00001295
1296//-------------------------------------------------------------------------
1297// CommandObjectCommandsScriptAdd
1298//-------------------------------------------------------------------------
1299
1300class CommandObjectCommandsScriptAdd : public CommandObject
1301{
1302private:
1303
1304 class CommandOptions : public Options
1305 {
1306 public:
1307
1308 CommandOptions (CommandInterpreter &interpreter) :
1309 Options (interpreter)
1310 {
1311 }
1312
1313 virtual
1314 ~CommandOptions (){}
1315
1316 virtual Error
1317 SetOptionValue (uint32_t option_idx, const char *option_arg)
1318 {
1319 Error error;
1320 char short_option = (char) m_getopt_table[option_idx].val;
1321
1322 switch (short_option)
1323 {
1324 case 'f':
1325 m_funct_name = std::string(option_arg);
1326 break;
1327 default:
1328 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1329 break;
1330 }
1331
1332 return error;
1333 }
1334
1335 void
1336 OptionParsingStarting ()
1337 {
1338 m_funct_name = "";
1339 }
1340
1341 const OptionDefinition*
1342 GetDefinitions ()
1343 {
1344 return g_option_table;
1345 }
1346
1347 // Options table: Required for subclasses of Options.
1348
1349 static OptionDefinition g_option_table[];
1350
1351 // Instance variables to hold the values for command options.
1352
1353 std::string m_funct_name;
1354 };
1355
1356 CommandOptions m_options;
1357
1358 virtual Options *
1359 GetOptions ()
1360 {
1361 return &m_options;
1362 }
1363
1364 class PythonAliasReader : public InputReaderEZ
1365 {
1366 private:
1367 CommandInterpreter& m_interpreter;
1368 std::string m_cmd_name;
1369 StringList m_user_input;
1370 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
1371 public:
1372 PythonAliasReader(Debugger& debugger,
1373 CommandInterpreter& interpreter,
1374 std::string cmd_name) :
1375 InputReaderEZ(debugger),
1376 m_interpreter(interpreter),
1377 m_cmd_name(cmd_name),
1378 m_user_input()
1379 {}
1380
1381 virtual
1382 ~PythonAliasReader()
1383 {
1384 }
1385
1386 virtual void ActivateHandler(HandlerData& data)
1387 {
1388 StreamSP out_stream = data.GetOutStream();
1389 bool batch_mode = data.GetBatchMode();
1390 if (!batch_mode)
1391 {
1392 out_stream->Printf ("%s\n", g_python_command_instructions);
1393 if (data.reader.GetPrompt())
1394 out_stream->Printf ("%s", data.reader.GetPrompt());
1395 out_stream->Flush();
1396 }
1397 }
1398
1399 virtual void ReactivateHandler(HandlerData& data)
1400 {
1401 StreamSP out_stream = data.GetOutStream();
1402 bool batch_mode = data.GetBatchMode();
1403 if (data.reader.GetPrompt() && !batch_mode)
1404 {
1405 out_stream->Printf ("%s", data.reader.GetPrompt());
1406 out_stream->Flush();
1407 }
1408 }
1409 virtual void GotTokenHandler(HandlerData& data)
1410 {
1411 StreamSP out_stream = data.GetOutStream();
1412 bool batch_mode = data.GetBatchMode();
1413 if (data.bytes && data.bytes_len)
1414 {
1415 m_user_input.AppendString(data.bytes, data.bytes_len);
1416 }
1417 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
1418 {
1419 out_stream->Printf ("%s", data.reader.GetPrompt());
1420 out_stream->Flush();
1421 }
1422 }
1423 virtual void InterruptHandler(HandlerData& data)
1424 {
1425 StreamSP out_stream = data.GetOutStream();
1426 bool batch_mode = data.GetBatchMode();
1427 data.reader.SetIsDone (true);
1428 if (!batch_mode)
1429 {
1430 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
1431 out_stream->Flush();
1432 }
1433 }
1434 virtual void EOFHandler(HandlerData& data)
1435 {
1436 data.reader.SetIsDone (true);
1437 }
1438 virtual void DoneHandler(HandlerData& data)
1439 {
1440 StreamSP out_stream = data.GetOutStream();
1441
1442 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1443 if (!interpreter)
1444 {
1445 out_stream->Printf ("Internal error #1: no script attached.\n");
1446 out_stream->Flush();
1447 return;
1448 }
1449 StringList funct_name_sl;
1450 if (!interpreter->GenerateScriptAliasFunction (m_user_input,
1451 funct_name_sl))
1452 {
1453 out_stream->Printf ("Internal error #2: no script attached.\n");
1454 out_stream->Flush();
1455 return;
1456 }
1457 if (funct_name_sl.GetSize() == 0)
1458 {
1459 out_stream->Printf ("Internal error #3: no script attached.\n");
1460 out_stream->Flush();
1461 return;
1462 }
1463 const char *funct_name = funct_name_sl.GetStringAtIndex(0);
1464 if (!funct_name || !funct_name[0])
1465 {
1466 out_stream->Printf ("Internal error #4: no script attached.\n");
1467 out_stream->Flush();
1468 return;
1469 }
1470
1471 // everything should be fine now, let's add this alias
1472
1473 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
1474 m_cmd_name,
1475 funct_name));
1476
1477 if (!m_interpreter.AddUserCommand(m_cmd_name.c_str(), command_obj_sp, true))
1478 {
1479 out_stream->Printf ("Internal error #5: no script attached.\n");
1480 out_stream->Flush();
1481 return;
1482 }
1483 }
1484 };
1485
1486public:
1487 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1488 CommandObject (interpreter,
1489 "command script add",
1490 "Add a scripted function as an LLDB command.",
1491 NULL),
1492 m_options (interpreter)
1493 {
1494 CommandArgumentEntry arg1;
1495 CommandArgumentData cmd_arg;
1496
1497 // Define the first (and only) variant of this arg.
1498 cmd_arg.arg_type = eArgTypeCommandName;
1499 cmd_arg.arg_repetition = eArgRepeatPlain;
1500
1501 // There is only one variant this argument could be; put it into the argument entry.
1502 arg1.push_back (cmd_arg);
1503
1504 // Push the data for the first argument into the m_arguments vector.
1505 m_arguments.push_back (arg1);
1506 }
1507
1508 ~CommandObjectCommandsScriptAdd ()
1509 {
1510 }
1511
1512 bool
1513 Execute
1514 (
1515 Args& args,
1516 CommandReturnObject &result
1517 )
1518 {
Enrico Granatae5e34cb2011-08-17 01:30:04 +00001519
1520 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1521 {
1522 result.AppendError ("only scripting language supported for scripted commands is currently Python");
1523 result.SetStatus (eReturnStatusFailed);
1524 return false;
1525 }
1526
Enrico Granata6b1596d2011-08-16 23:24:13 +00001527 size_t argc = args.GetArgumentCount();
1528
1529 if (argc != 1)
1530 {
1531 result.AppendError ("'command script add' requires one argument");
1532 result.SetStatus (eReturnStatusFailed);
1533 return false;
1534 }
1535
1536 std::string cmd_name = args.GetArgumentAtIndex(0);
1537
1538 if (m_options.m_funct_name.empty())
1539 {
1540 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
1541 m_interpreter,
1542 cmd_name));
1543
1544 if (reader_sp)
1545 {
1546
1547 InputReaderEZ::InitializationParameters ipr;
1548
1549 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
1550 if (err.Success())
1551 {
1552 m_interpreter.GetDebugger().PushInputReader (reader_sp);
1553 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1554 }
1555 else
1556 {
1557 result.AppendError (err.AsCString());
1558 result.SetStatus (eReturnStatusFailed);
1559 }
1560 }
1561 else
1562 {
1563 result.AppendError("out of memory");
1564 result.SetStatus (eReturnStatusFailed);
1565 }
1566 }
1567 else
1568 {
1569 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, cmd_name, m_options.m_funct_name));
1570 if (m_interpreter.AddUserCommand(cmd_name.c_str(), new_cmd, true))
1571 {
1572 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1573 }
1574 else
1575 {
1576 result.AppendError("cannot add command");
1577 result.SetStatus (eReturnStatusFailed);
1578 }
1579 }
1580
1581 return result.Succeeded();
1582
1583 }
1584};
1585
1586OptionDefinition
1587CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1588{
Enrico Granata91544802011-09-06 19:20:51 +00001589 { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
Enrico Granata6b1596d2011-08-16 23:24:13 +00001590 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1591};
1592
1593//-------------------------------------------------------------------------
1594// CommandObjectCommandsScriptList
1595//-------------------------------------------------------------------------
1596
1597class CommandObjectCommandsScriptList : public CommandObject
1598{
1599private:
1600
1601public:
1602 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1603 CommandObject (interpreter,
1604 "command script list",
1605 "List defined scripted commands.",
1606 NULL)
1607 {
1608 }
1609
1610 ~CommandObjectCommandsScriptList ()
1611 {
1612 }
1613
1614 bool
1615 Execute
1616 (
1617 Args& args,
1618 CommandReturnObject &result
1619 )
1620 {
1621
1622 m_interpreter.GetHelp(result,
1623 CommandInterpreter::eCommandTypesUserDef);
1624
1625 result.SetStatus (eReturnStatusSuccessFinishResult);
1626
1627 return true;
1628
1629
1630 }
1631};
1632
1633//-------------------------------------------------------------------------
1634// CommandObjectCommandsScriptClear
1635//-------------------------------------------------------------------------
1636
1637class CommandObjectCommandsScriptClear : public CommandObject
1638{
1639private:
1640
1641public:
1642 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
1643 CommandObject (interpreter,
1644 "command script clear",
1645 "Delete all scripted commands.",
1646 NULL)
1647 {
1648 }
1649
1650 ~CommandObjectCommandsScriptClear ()
1651 {
1652 }
1653
1654 bool
1655 Execute
1656 (
1657 Args& args,
1658 CommandReturnObject &result
1659 )
1660 {
1661
1662 m_interpreter.RemoveAllUser();
1663
1664 result.SetStatus (eReturnStatusSuccessFinishResult);
1665
1666 return true;
1667
1668
1669 }
1670};
1671
1672//-------------------------------------------------------------------------
1673// CommandObjectCommandsScriptDelete
1674//-------------------------------------------------------------------------
1675
1676class CommandObjectCommandsScriptDelete : public CommandObject
1677{
1678private:
1679
1680public:
1681 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
1682 CommandObject (interpreter,
1683 "command script delete",
1684 "Delete a scripted command.",
1685 NULL)
1686 {
1687 CommandArgumentEntry arg1;
1688 CommandArgumentData cmd_arg;
1689
1690 // Define the first (and only) variant of this arg.
1691 cmd_arg.arg_type = eArgTypeCommandName;
1692 cmd_arg.arg_repetition = eArgRepeatPlain;
1693
1694 // There is only one variant this argument could be; put it into the argument entry.
1695 arg1.push_back (cmd_arg);
1696
1697 // Push the data for the first argument into the m_arguments vector.
1698 m_arguments.push_back (arg1);
1699 }
1700
1701 ~CommandObjectCommandsScriptDelete ()
1702 {
1703 }
1704
1705 bool
1706 Execute
1707 (
1708 Args& args,
1709 CommandReturnObject &result
1710 )
1711 {
1712
1713 size_t argc = args.GetArgumentCount();
1714
1715 if (argc != 1)
1716 {
1717 result.AppendError ("'command script delete' requires one argument");
1718 result.SetStatus (eReturnStatusFailed);
1719 return false;
1720 }
1721
1722 const char* cmd_name = args.GetArgumentAtIndex(0);
1723
1724 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
1725 {
1726 m_interpreter.RemoveUser(cmd_name);
1727 result.SetStatus (eReturnStatusSuccessFinishResult);
1728 }
1729 else
1730 {
1731 result.AppendErrorWithFormat ("command %s not found", cmd_name);
1732 result.SetStatus (eReturnStatusFailed);
1733 }
1734
1735 return result.Succeeded();
1736
1737 }
1738};
1739
1740#pragma mark CommandObjectMultiwordCommandsScript
1741
1742//-------------------------------------------------------------------------
1743// CommandObjectMultiwordCommandsScript
1744//-------------------------------------------------------------------------
1745
1746class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
1747{
1748public:
1749 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
1750 CommandObjectMultiword (interpreter,
1751 "command script",
1752 "A set of commands for managing or customizing script commands.",
1753 "command script <subcommand> [<subcommand-options>]")
1754 {
1755 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
1756 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
1757 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
1758 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
Enrico Granata59df36f2011-10-17 21:45:27 +00001759 LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
Enrico Granata6b1596d2011-08-16 23:24:13 +00001760 }
1761
1762 ~CommandObjectMultiwordCommandsScript ()
1763 {
1764 }
1765
1766};
1767
1768
Jim Ingham767af882010-07-07 03:36:20 +00001769#pragma mark CommandObjectMultiwordCommands
1770
1771//-------------------------------------------------------------------------
1772// CommandObjectMultiwordCommands
1773//-------------------------------------------------------------------------
1774
1775CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001776 CommandObjectMultiword (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +00001777 "command",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001778 "A set of commands for managing or customizing the debugger commands.",
Greg Clayton40e48242011-04-20 22:55:21 +00001779 "command <subcommand> [<subcommand-options>]")
Jim Ingham767af882010-07-07 03:36:20 +00001780{
Greg Clayton238c0a12010-09-18 01:14:36 +00001781 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1782 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1783 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +00001784 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham6247dbe2011-07-12 03:12:18 +00001785 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
Enrico Granata6b1596d2011-08-16 23:24:13 +00001786 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +00001787}
1788
1789CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1790{
1791}
1792