blob: 8f63bf29009d6d53fe308e70a22388e0f648d139 [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
1223
1224//-------------------------------------------------------------------------
1225// CommandObjectCommandsScriptAdd
1226//-------------------------------------------------------------------------
1227
1228class CommandObjectCommandsScriptAdd : public CommandObject
1229{
1230private:
1231
1232 class CommandOptions : public Options
1233 {
1234 public:
1235
1236 CommandOptions (CommandInterpreter &interpreter) :
1237 Options (interpreter)
1238 {
1239 }
1240
1241 virtual
1242 ~CommandOptions (){}
1243
1244 virtual Error
1245 SetOptionValue (uint32_t option_idx, const char *option_arg)
1246 {
1247 Error error;
1248 char short_option = (char) m_getopt_table[option_idx].val;
1249
1250 switch (short_option)
1251 {
1252 case 'f':
1253 m_funct_name = std::string(option_arg);
1254 break;
1255 default:
1256 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1257 break;
1258 }
1259
1260 return error;
1261 }
1262
1263 void
1264 OptionParsingStarting ()
1265 {
1266 m_funct_name = "";
1267 }
1268
1269 const OptionDefinition*
1270 GetDefinitions ()
1271 {
1272 return g_option_table;
1273 }
1274
1275 // Options table: Required for subclasses of Options.
1276
1277 static OptionDefinition g_option_table[];
1278
1279 // Instance variables to hold the values for command options.
1280
1281 std::string m_funct_name;
1282 };
1283
1284 CommandOptions m_options;
1285
1286 virtual Options *
1287 GetOptions ()
1288 {
1289 return &m_options;
1290 }
1291
1292 class PythonAliasReader : public InputReaderEZ
1293 {
1294 private:
1295 CommandInterpreter& m_interpreter;
1296 std::string m_cmd_name;
1297 StringList m_user_input;
1298 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
1299 public:
1300 PythonAliasReader(Debugger& debugger,
1301 CommandInterpreter& interpreter,
1302 std::string cmd_name) :
1303 InputReaderEZ(debugger),
1304 m_interpreter(interpreter),
1305 m_cmd_name(cmd_name),
1306 m_user_input()
1307 {}
1308
1309 virtual
1310 ~PythonAliasReader()
1311 {
1312 }
1313
1314 virtual void ActivateHandler(HandlerData& data)
1315 {
1316 StreamSP out_stream = data.GetOutStream();
1317 bool batch_mode = data.GetBatchMode();
1318 if (!batch_mode)
1319 {
1320 out_stream->Printf ("%s\n", g_python_command_instructions);
1321 if (data.reader.GetPrompt())
1322 out_stream->Printf ("%s", data.reader.GetPrompt());
1323 out_stream->Flush();
1324 }
1325 }
1326
1327 virtual void ReactivateHandler(HandlerData& data)
1328 {
1329 StreamSP out_stream = data.GetOutStream();
1330 bool batch_mode = data.GetBatchMode();
1331 if (data.reader.GetPrompt() && !batch_mode)
1332 {
1333 out_stream->Printf ("%s", data.reader.GetPrompt());
1334 out_stream->Flush();
1335 }
1336 }
1337 virtual void GotTokenHandler(HandlerData& data)
1338 {
1339 StreamSP out_stream = data.GetOutStream();
1340 bool batch_mode = data.GetBatchMode();
1341 if (data.bytes && data.bytes_len)
1342 {
1343 m_user_input.AppendString(data.bytes, data.bytes_len);
1344 }
1345 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
1346 {
1347 out_stream->Printf ("%s", data.reader.GetPrompt());
1348 out_stream->Flush();
1349 }
1350 }
1351 virtual void InterruptHandler(HandlerData& data)
1352 {
1353 StreamSP out_stream = data.GetOutStream();
1354 bool batch_mode = data.GetBatchMode();
1355 data.reader.SetIsDone (true);
1356 if (!batch_mode)
1357 {
1358 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
1359 out_stream->Flush();
1360 }
1361 }
1362 virtual void EOFHandler(HandlerData& data)
1363 {
1364 data.reader.SetIsDone (true);
1365 }
1366 virtual void DoneHandler(HandlerData& data)
1367 {
1368 StreamSP out_stream = data.GetOutStream();
1369
1370 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1371 if (!interpreter)
1372 {
1373 out_stream->Printf ("Internal error #1: no script attached.\n");
1374 out_stream->Flush();
1375 return;
1376 }
1377 StringList funct_name_sl;
1378 if (!interpreter->GenerateScriptAliasFunction (m_user_input,
1379 funct_name_sl))
1380 {
1381 out_stream->Printf ("Internal error #2: no script attached.\n");
1382 out_stream->Flush();
1383 return;
1384 }
1385 if (funct_name_sl.GetSize() == 0)
1386 {
1387 out_stream->Printf ("Internal error #3: no script attached.\n");
1388 out_stream->Flush();
1389 return;
1390 }
1391 const char *funct_name = funct_name_sl.GetStringAtIndex(0);
1392 if (!funct_name || !funct_name[0])
1393 {
1394 out_stream->Printf ("Internal error #4: no script attached.\n");
1395 out_stream->Flush();
1396 return;
1397 }
1398
1399 // everything should be fine now, let's add this alias
1400
1401 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
1402 m_cmd_name,
1403 funct_name));
1404
1405 if (!m_interpreter.AddUserCommand(m_cmd_name.c_str(), command_obj_sp, true))
1406 {
1407 out_stream->Printf ("Internal error #5: no script attached.\n");
1408 out_stream->Flush();
1409 return;
1410 }
1411 }
1412 };
1413
1414public:
1415 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1416 CommandObject (interpreter,
1417 "command script add",
1418 "Add a scripted function as an LLDB command.",
1419 NULL),
1420 m_options (interpreter)
1421 {
1422 CommandArgumentEntry arg1;
1423 CommandArgumentData cmd_arg;
1424
1425 // Define the first (and only) variant of this arg.
1426 cmd_arg.arg_type = eArgTypeCommandName;
1427 cmd_arg.arg_repetition = eArgRepeatPlain;
1428
1429 // There is only one variant this argument could be; put it into the argument entry.
1430 arg1.push_back (cmd_arg);
1431
1432 // Push the data for the first argument into the m_arguments vector.
1433 m_arguments.push_back (arg1);
1434 }
1435
1436 ~CommandObjectCommandsScriptAdd ()
1437 {
1438 }
1439
1440 bool
1441 Execute
1442 (
1443 Args& args,
1444 CommandReturnObject &result
1445 )
1446 {
Enrico Granatae5e34cb2011-08-17 01:30:04 +00001447
1448 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1449 {
1450 result.AppendError ("only scripting language supported for scripted commands is currently Python");
1451 result.SetStatus (eReturnStatusFailed);
1452 return false;
1453 }
1454
Enrico Granata6b1596d2011-08-16 23:24:13 +00001455 size_t argc = args.GetArgumentCount();
1456
1457 if (argc != 1)
1458 {
1459 result.AppendError ("'command script add' requires one argument");
1460 result.SetStatus (eReturnStatusFailed);
1461 return false;
1462 }
1463
1464 std::string cmd_name = args.GetArgumentAtIndex(0);
1465
1466 if (m_options.m_funct_name.empty())
1467 {
1468 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
1469 m_interpreter,
1470 cmd_name));
1471
1472 if (reader_sp)
1473 {
1474
1475 InputReaderEZ::InitializationParameters ipr;
1476
1477 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
1478 if (err.Success())
1479 {
1480 m_interpreter.GetDebugger().PushInputReader (reader_sp);
1481 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1482 }
1483 else
1484 {
1485 result.AppendError (err.AsCString());
1486 result.SetStatus (eReturnStatusFailed);
1487 }
1488 }
1489 else
1490 {
1491 result.AppendError("out of memory");
1492 result.SetStatus (eReturnStatusFailed);
1493 }
1494 }
1495 else
1496 {
1497 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, cmd_name, m_options.m_funct_name));
1498 if (m_interpreter.AddUserCommand(cmd_name.c_str(), new_cmd, true))
1499 {
1500 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1501 }
1502 else
1503 {
1504 result.AppendError("cannot add command");
1505 result.SetStatus (eReturnStatusFailed);
1506 }
1507 }
1508
1509 return result.Succeeded();
1510
1511 }
1512};
1513
1514OptionDefinition
1515CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1516{
1517 { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypeName, "Name of a Python function to use."},
1518 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1519};
1520
1521//-------------------------------------------------------------------------
1522// CommandObjectCommandsScriptList
1523//-------------------------------------------------------------------------
1524
1525class CommandObjectCommandsScriptList : public CommandObject
1526{
1527private:
1528
1529public:
1530 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1531 CommandObject (interpreter,
1532 "command script list",
1533 "List defined scripted commands.",
1534 NULL)
1535 {
1536 }
1537
1538 ~CommandObjectCommandsScriptList ()
1539 {
1540 }
1541
1542 bool
1543 Execute
1544 (
1545 Args& args,
1546 CommandReturnObject &result
1547 )
1548 {
1549
1550 m_interpreter.GetHelp(result,
1551 CommandInterpreter::eCommandTypesUserDef);
1552
1553 result.SetStatus (eReturnStatusSuccessFinishResult);
1554
1555 return true;
1556
1557
1558 }
1559};
1560
1561//-------------------------------------------------------------------------
1562// CommandObjectCommandsScriptClear
1563//-------------------------------------------------------------------------
1564
1565class CommandObjectCommandsScriptClear : public CommandObject
1566{
1567private:
1568
1569public:
1570 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
1571 CommandObject (interpreter,
1572 "command script clear",
1573 "Delete all scripted commands.",
1574 NULL)
1575 {
1576 }
1577
1578 ~CommandObjectCommandsScriptClear ()
1579 {
1580 }
1581
1582 bool
1583 Execute
1584 (
1585 Args& args,
1586 CommandReturnObject &result
1587 )
1588 {
1589
1590 m_interpreter.RemoveAllUser();
1591
1592 result.SetStatus (eReturnStatusSuccessFinishResult);
1593
1594 return true;
1595
1596
1597 }
1598};
1599
1600//-------------------------------------------------------------------------
1601// CommandObjectCommandsScriptDelete
1602//-------------------------------------------------------------------------
1603
1604class CommandObjectCommandsScriptDelete : public CommandObject
1605{
1606private:
1607
1608public:
1609 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
1610 CommandObject (interpreter,
1611 "command script delete",
1612 "Delete a scripted command.",
1613 NULL)
1614 {
1615 CommandArgumentEntry arg1;
1616 CommandArgumentData cmd_arg;
1617
1618 // Define the first (and only) variant of this arg.
1619 cmd_arg.arg_type = eArgTypeCommandName;
1620 cmd_arg.arg_repetition = eArgRepeatPlain;
1621
1622 // There is only one variant this argument could be; put it into the argument entry.
1623 arg1.push_back (cmd_arg);
1624
1625 // Push the data for the first argument into the m_arguments vector.
1626 m_arguments.push_back (arg1);
1627 }
1628
1629 ~CommandObjectCommandsScriptDelete ()
1630 {
1631 }
1632
1633 bool
1634 Execute
1635 (
1636 Args& args,
1637 CommandReturnObject &result
1638 )
1639 {
1640
1641 size_t argc = args.GetArgumentCount();
1642
1643 if (argc != 1)
1644 {
1645 result.AppendError ("'command script delete' requires one argument");
1646 result.SetStatus (eReturnStatusFailed);
1647 return false;
1648 }
1649
1650 const char* cmd_name = args.GetArgumentAtIndex(0);
1651
1652 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
1653 {
1654 m_interpreter.RemoveUser(cmd_name);
1655 result.SetStatus (eReturnStatusSuccessFinishResult);
1656 }
1657 else
1658 {
1659 result.AppendErrorWithFormat ("command %s not found", cmd_name);
1660 result.SetStatus (eReturnStatusFailed);
1661 }
1662
1663 return result.Succeeded();
1664
1665 }
1666};
1667
1668#pragma mark CommandObjectMultiwordCommandsScript
1669
1670//-------------------------------------------------------------------------
1671// CommandObjectMultiwordCommandsScript
1672//-------------------------------------------------------------------------
1673
1674class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
1675{
1676public:
1677 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
1678 CommandObjectMultiword (interpreter,
1679 "command script",
1680 "A set of commands for managing or customizing script commands.",
1681 "command script <subcommand> [<subcommand-options>]")
1682 {
1683 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
1684 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
1685 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
1686 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
1687 }
1688
1689 ~CommandObjectMultiwordCommandsScript ()
1690 {
1691 }
1692
1693};
1694
1695
Jim Ingham767af882010-07-07 03:36:20 +00001696#pragma mark CommandObjectMultiwordCommands
1697
1698//-------------------------------------------------------------------------
1699// CommandObjectMultiwordCommands
1700//-------------------------------------------------------------------------
1701
1702CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001703 CommandObjectMultiword (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +00001704 "command",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001705 "A set of commands for managing or customizing the debugger commands.",
Greg Clayton40e48242011-04-20 22:55:21 +00001706 "command <subcommand> [<subcommand-options>]")
Jim Ingham767af882010-07-07 03:36:20 +00001707{
Greg Clayton238c0a12010-09-18 01:14:36 +00001708 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1709 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1710 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +00001711 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham6247dbe2011-07-12 03:12:18 +00001712 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
Enrico Granata6b1596d2011-08-16 23:24:13 +00001713 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +00001714}
1715
1716CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1717{
1718}
1719