blob: 6c12126d4f5e2830ecfdeb9561775caf73011847 [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"
27
28using namespace lldb;
29using namespace lldb_private;
30
Jim Ingham767af882010-07-07 03:36:20 +000031//-------------------------------------------------------------------------
32// CommandObjectCommandsSource
33//-------------------------------------------------------------------------
34
Jim Ingham6247dbe2011-07-12 03:12:18 +000035class CommandObjectCommandsHistory : public CommandObject
36{
37private:
38
39 class CommandOptions : public Options
40 {
41 public:
42
43 CommandOptions (CommandInterpreter &interpreter) :
44 Options (interpreter)
45 {
46 }
47
48 virtual
49 ~CommandOptions (){}
50
51 virtual Error
52 SetOptionValue (uint32_t option_idx, const char *option_arg)
53 {
54 Error error;
55 char short_option = (char) m_getopt_table[option_idx].val;
56 bool success;
57
58 switch (short_option)
59 {
60 case 'c':
61 m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
62 if (!success)
63 error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
64 if (m_end_idx != 0)
65 m_end_idx--;
66 m_start_idx = 0;
67 break;
68 case 'e':
69 m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
70 if (!success)
71 error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
72 break;
73 case 's':
74 m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
75 if (!success)
76 error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
77 break;
78 default:
79 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
80 break;
81 }
82
83 return error;
84 }
85
86 void
87 OptionParsingStarting ()
88 {
89 m_start_idx = 0;
90 m_end_idx = UINT_MAX;
91 }
92
93 const OptionDefinition*
94 GetDefinitions ()
95 {
96 return g_option_table;
97 }
98
99 // Options table: Required for subclasses of Options.
100
101 static OptionDefinition g_option_table[];
102
103 // Instance variables to hold the values for command options.
104
105 uint32_t m_start_idx;
106 uint32_t m_end_idx;
107 };
108
109 CommandOptions m_options;
110
111 virtual Options *
112 GetOptions ()
113 {
114 return &m_options;
115 }
116
117public:
118 CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
119 CommandObject (interpreter,
120 "command history",
121 "Dump the history of commands in this session.",
122 NULL),
123 m_options (interpreter)
124 {
125 }
126
127 ~CommandObjectCommandsHistory ()
128 {
129 }
130
131 bool
132 Execute
133 (
134 Args& args,
135 CommandReturnObject &result
136 )
137 {
138
139 m_interpreter.DumpHistory (result.GetOutputStream(),
140 m_options.m_start_idx,
141 m_options.m_end_idx);
142 return result.Succeeded();
143
144 }
145};
146
147OptionDefinition
148CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
149{
150{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
151{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands."},
152{ LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
153{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
154};
155
156
157//-------------------------------------------------------------------------
158// CommandObjectCommandsSource
159//-------------------------------------------------------------------------
160
Jim Ingham767af882010-07-07 03:36:20 +0000161class CommandObjectCommandsSource : public CommandObject
162{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000163private:
164
165 class CommandOptions : public Options
166 {
167 public:
168
Greg Claytonf15996e2011-04-07 22:46:35 +0000169 CommandOptions (CommandInterpreter &interpreter) :
170 Options (interpreter)
171 {
172 }
Jim Ingham949d5ac2011-02-18 00:54:25 +0000173
174 virtual
175 ~CommandOptions (){}
176
177 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000178 SetOptionValue (uint32_t option_idx, const char *option_arg)
Jim Ingham949d5ac2011-02-18 00:54:25 +0000179 {
180 Error error;
181 char short_option = (char) m_getopt_table[option_idx].val;
182 bool success;
183
184 switch (short_option)
185 {
186 case 'e':
187 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
188 if (!success)
189 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
190 break;
191 case 'c':
192 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
193 if (!success)
194 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
195 break;
196 default:
197 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
198 break;
199 }
200
201 return error;
202 }
203
204 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000205 OptionParsingStarting ()
Jim Ingham949d5ac2011-02-18 00:54:25 +0000206 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000207 m_stop_on_error = true;
208 m_stop_on_continue = true;
209 }
210
Greg Claytonb3448432011-03-24 21:19:54 +0000211 const OptionDefinition*
Jim Ingham949d5ac2011-02-18 00:54:25 +0000212 GetDefinitions ()
213 {
214 return g_option_table;
215 }
216
217 // Options table: Required for subclasses of Options.
218
Greg Claytonb3448432011-03-24 21:19:54 +0000219 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +0000220
221 // Instance variables to hold the values for command options.
222
223 bool m_stop_on_error;
224 bool m_stop_on_continue;
225 };
226
Jim Ingham949d5ac2011-02-18 00:54:25 +0000227 CommandOptions m_options;
228
229 virtual Options *
230 GetOptions ()
231 {
232 return &m_options;
233 }
234
Jim Ingham767af882010-07-07 03:36:20 +0000235public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000236 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
237 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000238 "command source",
Greg Clayton238c0a12010-09-18 01:14:36 +0000239 "Read in debugger commands from the file <filename> and execute them.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000240 NULL),
241 m_options (interpreter)
Jim Ingham767af882010-07-07 03:36:20 +0000242 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000243 CommandArgumentEntry arg;
244 CommandArgumentData file_arg;
245
246 // Define the first (and only) variant of this arg.
247 file_arg.arg_type = eArgTypeFilename;
248 file_arg.arg_repetition = eArgRepeatPlain;
249
250 // There is only one variant this argument could be; put it into the argument entry.
251 arg.push_back (file_arg);
252
253 // Push the data for the first argument into the m_arguments vector.
254 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000255 }
256
257 ~CommandObjectCommandsSource ()
258 {
259 }
260
261 bool
262 Execute
263 (
Jim Ingham767af882010-07-07 03:36:20 +0000264 Args& args,
265 CommandReturnObject &result
266 )
267 {
268 const int argc = args.GetArgumentCount();
269 if (argc == 1)
270 {
271 const char *filename = args.GetArgumentAtIndex(0);
Jim Ingham767af882010-07-07 03:36:20 +0000272
273 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
274
Johnny Chena83ea882010-10-20 21:40:50 +0000275 FileSpec cmd_file (filename, true);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000276 ExecutionContext *exe_ctx = NULL; // Just use the default context.
277 bool echo_commands = true;
278 bool print_results = true;
Jim Ingham767af882010-07-07 03:36:20 +0000279
Jim Ingham949d5ac2011-02-18 00:54:25 +0000280 m_interpreter.HandleCommandsFromFile (cmd_file,
281 exe_ctx,
282 m_options.m_stop_on_continue,
283 m_options.m_stop_on_error,
284 echo_commands,
285 print_results,
286 result);
Jim Ingham767af882010-07-07 03:36:20 +0000287 }
288 else
289 {
290 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
291 result.SetStatus (eReturnStatusFailed);
292 }
293 return result.Succeeded();
294
295 }
296};
297
Greg Claytonb3448432011-03-24 21:19:54 +0000298OptionDefinition
Jim Ingham949d5ac2011-02-18 00:54:25 +0000299CommandObjectCommandsSource::CommandOptions::g_option_table[] =
300{
301{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
302{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
303{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
304};
305
Jim Ingham767af882010-07-07 03:36:20 +0000306#pragma mark CommandObjectCommandsAlias
307//-------------------------------------------------------------------------
308// CommandObjectCommandsAlias
309//-------------------------------------------------------------------------
310
Enrico Granatac2a28252011-08-16 16:49:25 +0000311static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
312 "You must define a Python function with this signature:\n"
Enrico Granata6b1596d2011-08-16 23:24:13 +0000313 "def my_command_impl(debugger, args, result, dict):";
Enrico Granatac2a28252011-08-16 16:49:25 +0000314
315
Jim Ingham767af882010-07-07 03:36:20 +0000316class CommandObjectCommandsAlias : public CommandObject
317{
Enrico Granatac2a28252011-08-16 16:49:25 +0000318
Enrico Granatac2a28252011-08-16 16:49:25 +0000319
Jim Ingham767af882010-07-07 03:36:20 +0000320public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000321 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
322 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000323 "command alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000324 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000325 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000326 {
327 SetHelpLong(
328 "'alias' allows the user to create a short-cut or abbreviation for long \n\
329 commands, multi-word commands, and commands that take particular options. \n\
330 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000331 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
332 // command. \n\
333 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
334 // command. Since breakpoint commands are two-word \n\
335 // commands, the user will still need to enter the \n\
336 // second word after 'bp', e.g. 'bp enable' or \n\
337 // 'bp delete'. \n\
338 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
339 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000340 \nAn alias can include some options for the command, with the values either \n\
341 filled in at the time the alias is created, or specified as positional \n\
342 arguments, to be filled in when the alias is invoked. The following example \n\
343 shows how to create aliases with options: \n\
344 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000345 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000346 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
347 options already part of the alias. So if the user wants to set a breakpoint \n\
348 by file and line without explicitly having to use the -f and -l options, the \n\
349 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
350 for the actual arguments that will be passed when the alias command is used. \n\
351 The number in the placeholder refers to the position/order the actual value \n\
352 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
353 will be replaced with the first argument, all the occurrences of '%2' in the \n\
354 alias will be replaced with the second argument, and so on. This also allows \n\
355 actual arguments to be used multiple times within an alias (see 'process \n\
356 launch' example below). So in the 'bfl' case, the actual file value will be \n\
357 filled in with the first argument following 'bfl' and the actual line number \n\
358 value will be filled in with the second argument. The user would use this \n\
359 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000360 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000361 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000362 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000363 \nThis would be the same as if the user had entered \n\
364 'breakpoint set -f my-file.c -l 137'. \n\
365 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000366 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
367 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000368 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000369 \nIf the user always wanted to pass the same value to a particular option, the \n\
370 alias could be defined with that value directly in the alias as a constant, \n\
371 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000372 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
373 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000374
Caroline Tice43b014a2010-10-04 22:28:36 +0000375 CommandArgumentEntry arg1;
376 CommandArgumentEntry arg2;
377 CommandArgumentEntry arg3;
378 CommandArgumentData alias_arg;
379 CommandArgumentData cmd_arg;
380 CommandArgumentData options_arg;
381
382 // Define the first (and only) variant of this arg.
383 alias_arg.arg_type = eArgTypeAliasName;
384 alias_arg.arg_repetition = eArgRepeatPlain;
385
386 // There is only one variant this argument could be; put it into the argument entry.
387 arg1.push_back (alias_arg);
388
389 // Define the first (and only) variant of this arg.
390 cmd_arg.arg_type = eArgTypeCommandName;
391 cmd_arg.arg_repetition = eArgRepeatPlain;
392
393 // There is only one variant this argument could be; put it into the argument entry.
394 arg2.push_back (cmd_arg);
395
396 // Define the first (and only) variant of this arg.
397 options_arg.arg_type = eArgTypeAliasOptions;
398 options_arg.arg_repetition = eArgRepeatOptional;
399
400 // There is only one variant this argument could be; put it into the argument entry.
401 arg3.push_back (options_arg);
402
403 // Push the data for the first argument into the m_arguments vector.
404 m_arguments.push_back (arg1);
405 m_arguments.push_back (arg2);
406 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000407 }
408
409 ~CommandObjectCommandsAlias ()
410 {
411 }
412
Caroline Ticee0da7a52010-12-09 22:52:49 +0000413 bool
414 WantsRawCommandString ()
415 {
416 return true;
417 }
418
419 bool
420 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
421 {
422 Args args (raw_command_line);
423 std::string raw_command_string (raw_command_line);
424
425 size_t argc = args.GetArgumentCount();
426
427 if (argc < 2)
428 {
429 result.AppendError ("'alias' requires at least two arguments");
430 result.SetStatus (eReturnStatusFailed);
431 return false;
432 }
433
434 // Get the alias command.
435
436 const std::string alias_command = args.GetArgumentAtIndex (0);
Enrico Granatac2a28252011-08-16 16:49:25 +0000437
Caroline Ticee0da7a52010-12-09 22:52:49 +0000438 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
439 // does the stripping itself.
440 size_t pos = raw_command_string.find (alias_command);
441 if (pos == 0)
442 {
443 raw_command_string = raw_command_string.substr (alias_command.size());
444 pos = raw_command_string.find_first_not_of (' ');
445 if ((pos != std::string::npos) && (pos > 0))
446 raw_command_string = raw_command_string.substr (pos);
447 }
448 else
449 {
450 result.AppendError ("Error parsing command string. No alias created.");
451 result.SetStatus (eReturnStatusFailed);
452 return false;
453 }
454
455
456 // Verify that the command is alias-able.
457 if (m_interpreter.CommandExists (alias_command.c_str()))
458 {
459 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
460 alias_command.c_str());
461 result.SetStatus (eReturnStatusFailed);
462 return false;
463 }
464
465 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
466 // raw_command_string is returned with the name of the command object stripped off the front.
467 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
468
469 if (!cmd_obj)
470 {
471 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
472 " No alias created.", raw_command_string.c_str());
473 result.SetStatus (eReturnStatusFailed);
474 return false;
475 }
476 else if (!cmd_obj->WantsRawCommandString ())
477 {
478 // Note that args was initialized with the original command, and has not been updated to this point.
479 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
480 return Execute (args, result);
481 }
482 else
483 {
484 // Verify & handle any options/arguments passed to the alias command
485
486 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
487 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
488
Caroline Tice5ddbe212011-05-06 21:37:15 +0000489 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
490
491 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
Caroline Ticee0da7a52010-12-09 22:52:49 +0000492 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000493 result.AppendError ("Unable to create requested alias.\n");
494 result.SetStatus (eReturnStatusFailed);
495 return false;
Caroline Ticee0da7a52010-12-09 22:52:49 +0000496 }
497
498 // Create the alias
499 if (m_interpreter.AliasExists (alias_command.c_str())
500 || m_interpreter.UserCommandExists (alias_command.c_str()))
501 {
502 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
503 if (temp_option_arg_sp.get())
504 {
505 if (option_arg_vector->size() == 0)
506 m_interpreter.RemoveAliasOptions (alias_command.c_str());
507 }
508 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
509 alias_command.c_str());
510 }
511
Caroline Tice56d2fc42010-12-14 18:51:39 +0000512 if (cmd_obj_sp)
513 {
514 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
515 if (option_arg_vector->size() > 0)
516 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
517 result.SetStatus (eReturnStatusSuccessFinishNoResult);
518 }
519 else
520 {
521 result.AppendError ("Unable to create requested alias.\n");
522 result.SetStatus (eReturnStatusFailed);
523 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000524 }
525 return result.Succeeded();
526 }
Jim Ingham767af882010-07-07 03:36:20 +0000527
528 bool
529 Execute
530 (
Jim Ingham767af882010-07-07 03:36:20 +0000531 Args& args,
532 CommandReturnObject &result
533 )
534 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000535 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000536
537 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000538 {
Jim Ingham767af882010-07-07 03:36:20 +0000539 result.AppendError ("'alias' requires at least two arguments");
540 result.SetStatus (eReturnStatusFailed);
541 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000542 }
Jim Ingham767af882010-07-07 03:36:20 +0000543
544 const std::string alias_command = args.GetArgumentAtIndex(0);
545 const std::string actual_command = args.GetArgumentAtIndex(1);
546
547 args.Shift(); // Shift the alias command word off the argument vector.
548 args.Shift(); // Shift the old command word off the argument vector.
549
550 // Verify that the command is alias'able, and get the appropriate command object.
551
Greg Clayton238c0a12010-09-18 01:14:36 +0000552 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000553 {
554 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
555 alias_command.c_str());
556 result.SetStatus (eReturnStatusFailed);
557 }
558 else
559 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000560 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000561 CommandObjectSP subcommand_obj_sp;
562 bool use_subcommand = false;
563 if (command_obj_sp.get())
564 {
565 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000566 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000567 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
568 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
569
Caroline Ticee0da7a52010-12-09 22:52:49 +0000570 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000571 {
572 if (argc >= 3)
573 {
574 const std::string sub_command = args.GetArgumentAtIndex(0);
575 assert (sub_command.length() != 0);
576 subcommand_obj_sp =
577 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
578 if (subcommand_obj_sp.get())
579 {
580 sub_cmd_obj = subcommand_obj_sp.get();
581 use_subcommand = true;
582 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000583 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000584 }
585 else
586 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000587 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
588 "Unable to create alias.\n",
589 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000590 result.SetStatus (eReturnStatusFailed);
591 return false;
592 }
593 }
594 }
595
596 // Verify & handle any options/arguments passed to the alias command
597
598 if (args.GetArgumentCount () > 0)
599 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000600 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
601 if (use_subcommand)
602 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
603
604 std::string args_string;
605 args.GetCommandString (args_string);
606
607 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
608 {
609 result.AppendError ("Unable to create requested alias.\n");
610 result.SetStatus (eReturnStatusFailed);
611 return false;
612 }
Jim Ingham767af882010-07-07 03:36:20 +0000613 }
614
615 // Create the alias.
616
Greg Clayton238c0a12010-09-18 01:14:36 +0000617 if (m_interpreter.AliasExists (alias_command.c_str())
618 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000619 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000620 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000621 if (tmp_option_arg_sp.get())
622 {
623 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000624 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000625 }
626 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
627 alias_command.c_str());
628 }
629
630 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000631 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000632 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000633 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000634 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000635 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000636 result.SetStatus (eReturnStatusSuccessFinishNoResult);
637 }
638 else
639 {
640 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
641 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000642 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000643 }
644 }
645
646 return result.Succeeded();
647 }
648};
649
650#pragma mark CommandObjectCommandsUnalias
651//-------------------------------------------------------------------------
652// CommandObjectCommandsUnalias
653//-------------------------------------------------------------------------
654
655class CommandObjectCommandsUnalias : public CommandObject
656{
657public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000658 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
659 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000660 "command unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000661 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000662 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000663 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000664 CommandArgumentEntry arg;
665 CommandArgumentData alias_arg;
666
667 // Define the first (and only) variant of this arg.
668 alias_arg.arg_type = eArgTypeAliasName;
669 alias_arg.arg_repetition = eArgRepeatPlain;
670
671 // There is only one variant this argument could be; put it into the argument entry.
672 arg.push_back (alias_arg);
673
674 // Push the data for the first argument into the m_arguments vector.
675 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000676 }
677
678 ~CommandObjectCommandsUnalias()
679 {
680 }
681
682
683 bool
684 Execute
685 (
Jim Ingham767af882010-07-07 03:36:20 +0000686 Args& args,
687 CommandReturnObject &result
688 )
689 {
690 CommandObject::CommandMap::iterator pos;
691 CommandObject *cmd_obj;
692
693 if (args.GetArgumentCount() != 0)
694 {
695 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000696 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000697 if (cmd_obj)
698 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000699 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000700 {
701 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
702 command_name);
703 result.SetStatus (eReturnStatusFailed);
704 }
705 else
706 {
707
Greg Clayton238c0a12010-09-18 01:14:36 +0000708 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000709 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000710 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000711 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
712 command_name);
713 else
714 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
715 result.SetStatus (eReturnStatusFailed);
716 }
717 else
718 result.SetStatus (eReturnStatusSuccessFinishNoResult);
719 }
720 }
721 else
722 {
723 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
724 "current list of commands.\n",
725 command_name);
726 result.SetStatus (eReturnStatusFailed);
727 }
728 }
729 else
730 {
731 result.AppendError ("must call 'unalias' with a valid alias");
732 result.SetStatus (eReturnStatusFailed);
733 }
734
735 return result.Succeeded();
736 }
737};
738
Greg Claytond12aeab2011-04-20 16:37:46 +0000739#pragma mark CommandObjectCommandsAddRegex
740//-------------------------------------------------------------------------
741// CommandObjectCommandsAddRegex
742//-------------------------------------------------------------------------
743
744class CommandObjectCommandsAddRegex : public CommandObject
745{
746public:
747 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
748 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000749 "command regex",
Greg Claytond12aeab2011-04-20 16:37:46 +0000750 "Allow the user to create a regular expression command.",
Greg Clayton40e48242011-04-20 22:55:21 +0000751 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
Greg Claytond12aeab2011-04-20 16:37:46 +0000752 m_options (interpreter)
753 {
Greg Clayton40e48242011-04-20 22:55:21 +0000754 SetHelpLong(
755"This command allows the user to create powerful regular expression commands\n"
756"with substitutions. The regular expressions and substitutions are specified\n"
757"using the regular exression substitution format of:\n"
758"\n"
759" s/<regex>/<subst>/\n"
760"\n"
761"<regex> is a regular expression that can use parenthesis to capture regular\n"
762"expression input and substitute the captured matches in the output using %1\n"
763"for the first match, %2 for the second, and so on.\n"
764"\n"
765"The regular expressions can all be specified on the command line if more than\n"
766"one argument is provided. If just the command name is provided on the command\n"
767"line, then the regular expressions and substitutions can be entered on separate\n"
768" lines, followed by an empty line to terminate the command definition.\n"
769"\n"
770"EXAMPLES\n"
771"\n"
772"The following example with define a regular expression command named 'f' that\n"
773"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
774"a number follows 'f':\n"
775"(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
776 );
Greg Claytond12aeab2011-04-20 16:37:46 +0000777 }
778
779 ~CommandObjectCommandsAddRegex()
780 {
781 }
782
783
784 bool
785 Execute (Args& args, CommandReturnObject &result)
786 {
Greg Clayton40e48242011-04-20 22:55:21 +0000787 const size_t argc = args.GetArgumentCount();
788 if (argc == 0)
Greg Claytond12aeab2011-04-20 16:37:46 +0000789 {
Greg Clayton40e48242011-04-20 22:55:21 +0000790 result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
791 result.SetStatus (eReturnStatusFailed);
792 }
793 else
794 {
795 Error error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000796 const char *name = args.GetArgumentAtIndex(0);
Greg Claytond12aeab2011-04-20 16:37:46 +0000797 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
798 name,
799 m_options.GetHelp (),
800 m_options.GetSyntax (),
801 10));
Greg Clayton40e48242011-04-20 22:55:21 +0000802
803 if (argc == 1)
Greg Claytond12aeab2011-04-20 16:37:46 +0000804 {
Greg Clayton40e48242011-04-20 22:55:21 +0000805 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
806 if (reader_sp)
807 {
808 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
Greg Claytond12aeab2011-04-20 16:37:46 +0000809 this, // baton
810 eInputReaderGranularityLine, // token size, to pass to callback function
Greg Clayton40e48242011-04-20 22:55:21 +0000811 NULL, // end token
Greg Claytond12aeab2011-04-20 16:37:46 +0000812 "> ", // prompt
Greg Clayton40e48242011-04-20 22:55:21 +0000813 true); // echo input
814 if (error.Success())
815 {
816 m_interpreter.GetDebugger().PushInputReader (reader_sp);
817 result.SetStatus (eReturnStatusSuccessFinishNoResult);
818 return true;
819 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000820 }
821 }
Greg Clayton40e48242011-04-20 22:55:21 +0000822 else
823 {
824 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
825 {
826 llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
827 error = AppendRegexSubstitution (arg_strref);
828 if (error.Fail())
829 break;
830 }
831
832 if (error.Success())
833 {
834 AddRegexCommandToInterpreter();
835 }
836 }
837 if (error.Fail())
838 {
839 result.AppendError (error.AsCString());
840 result.SetStatus (eReturnStatusFailed);
841 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000842 }
Greg Clayton40e48242011-04-20 22:55:21 +0000843
Greg Claytond12aeab2011-04-20 16:37:46 +0000844 return result.Succeeded();
845 }
846
Greg Clayton40e48242011-04-20 22:55:21 +0000847 Error
848 AppendRegexSubstitution (const llvm::StringRef &regex_sed)
Greg Claytond12aeab2011-04-20 16:37:46 +0000849 {
Greg Clayton40e48242011-04-20 22:55:21 +0000850 Error error;
851
852 if (m_regex_cmd_ap.get() == NULL)
Greg Claytond12aeab2011-04-20 16:37:46 +0000853 {
Greg Clayton40e48242011-04-20 22:55:21 +0000854 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
855 (int)regex_sed.size(),
856 regex_sed.data());
857 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000858 }
Greg Clayton40e48242011-04-20 22:55:21 +0000859
860 size_t regex_sed_size = regex_sed.size();
861
862 if (regex_sed_size <= 1)
863 {
864 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
865 (int)regex_sed.size(),
866 regex_sed.data());
867 return error;
868 }
869
870 if (regex_sed[0] != 's')
871 {
872 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
873 (int)regex_sed.size(),
874 regex_sed.data());
875 return error;
876 }
877 const size_t first_separator_char_pos = 1;
878 // use the char that follows 's' as the regex separator character
879 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
880 const char separator_char = regex_sed[first_separator_char_pos];
881 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
882
883 if (second_separator_char_pos == std::string::npos)
884 {
885 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
886 separator_char,
887 (int)(regex_sed.size() - first_separator_char_pos - 1),
888 regex_sed.data() + (first_separator_char_pos + 1));
889 return error;
890 }
891
892 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
893
894 if (third_separator_char_pos == std::string::npos)
895 {
896 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
897 separator_char,
898 (int)(regex_sed.size() - second_separator_char_pos - 1),
899 regex_sed.data() + (second_separator_char_pos + 1));
900 return error;
901 }
902
903 if (third_separator_char_pos != regex_sed_size - 1)
904 {
905 // Make sure that everything that follows the last regex
906 // separator char
907 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
908 {
909 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
910 (int)third_separator_char_pos + 1,
911 regex_sed.data(),
912 (int)(regex_sed.size() - third_separator_char_pos - 1),
913 regex_sed.data() + (third_separator_char_pos + 1));
914 return error;
915 }
916
917 }
918 else if (first_separator_char_pos + 1 == second_separator_char_pos)
919 {
920 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
921 separator_char,
922 separator_char,
923 separator_char,
924 (int)regex_sed.size(),
925 regex_sed.data());
926 return error;
927 }
928 else if (second_separator_char_pos + 1 == third_separator_char_pos)
929 {
930 error.SetErrorStringWithFormat("<subst> 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 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
939 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
940 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
941 subst.c_str());
942 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000943 }
944
945 void
Greg Clayton40e48242011-04-20 22:55:21 +0000946 AddRegexCommandToInterpreter()
Greg Claytond12aeab2011-04-20 16:37:46 +0000947 {
948 if (m_regex_cmd_ap.get())
949 {
950 if (m_regex_cmd_ap->HasRegexEntries())
951 {
952 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
953 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
954 }
955 }
956 }
957
Greg Clayton40e48242011-04-20 22:55:21 +0000958 void
959 InputReaderDidCancel()
960 {
961 m_regex_cmd_ap.reset();
962 }
963
Greg Claytond12aeab2011-04-20 16:37:46 +0000964 static size_t
965 InputReaderCallback (void *baton,
966 InputReader &reader,
967 lldb::InputReaderAction notification,
968 const char *bytes,
969 size_t bytes_len);
970private:
971 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
972
973 class CommandOptions : public Options
974 {
975 public:
976
977 CommandOptions (CommandInterpreter &interpreter) :
978 Options (interpreter)
979 {
980 }
981
982 virtual
983 ~CommandOptions (){}
984
985 virtual Error
986 SetOptionValue (uint32_t option_idx, const char *option_arg)
987 {
988 Error error;
989 char short_option = (char) m_getopt_table[option_idx].val;
990
991 switch (short_option)
992 {
993 case 'h':
994 m_help.assign (option_arg);
995 break;
996 case 's':
997 m_syntax.assign (option_arg);
998 break;
999
1000 default:
1001 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1002 break;
1003 }
1004
1005 return error;
1006 }
1007
1008 void
1009 OptionParsingStarting ()
1010 {
1011 m_help.clear();
1012 m_syntax.clear();
1013 }
1014
1015 const OptionDefinition*
1016 GetDefinitions ()
1017 {
1018 return g_option_table;
1019 }
1020
1021 // Options table: Required for subclasses of Options.
1022
1023 static OptionDefinition g_option_table[];
1024
1025 const char *
1026 GetHelp ()
1027 {
1028 if (m_help.empty())
1029 return NULL;
1030 return m_help.c_str();
1031 }
1032 const char *
1033 GetSyntax ()
1034 {
1035 if (m_syntax.empty())
1036 return NULL;
1037 return m_syntax.c_str();
1038 }
1039 // Instance variables to hold the values for command options.
1040 protected:
1041 std::string m_help;
1042 std::string m_syntax;
1043 };
1044
1045 CommandOptions m_options;
1046
1047 virtual Options *
1048 GetOptions ()
1049 {
1050 return &m_options;
1051 }
1052
1053};
1054
1055size_t
1056CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1057 InputReader &reader,
1058 lldb::InputReaderAction notification,
1059 const char *bytes,
1060 size_t bytes_len)
1061{
1062 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
Caroline Tice892fadd2011-06-16 16:27:19 +00001063 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Greg Claytond12aeab2011-04-20 16:37:46 +00001064
1065 switch (notification)
1066 {
1067 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +00001068 if (!batch_mode)
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001069 {
1070 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1071 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1072 out_stream->Flush();
1073 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001074 break;
1075 case eInputReaderReactivate:
1076 break;
1077
1078 case eInputReaderDeactivate:
1079 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001080
1081 case eInputReaderAsynchronousOutputWritten:
1082 break;
1083
Greg Claytond12aeab2011-04-20 16:37:46 +00001084 case eInputReaderGotToken:
Greg Clayton40e48242011-04-20 22:55:21 +00001085 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1086 --bytes_len;
Greg Claytond12aeab2011-04-20 16:37:46 +00001087 if (bytes_len == 0)
1088 reader.SetIsDone(true);
1089 else if (bytes)
1090 {
Greg Clayton40e48242011-04-20 22:55:21 +00001091 llvm::StringRef bytes_strref (bytes, bytes_len);
1092 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1093 if (error.Fail())
Greg Claytond12aeab2011-04-20 16:37:46 +00001094 {
Caroline Tice892fadd2011-06-16 16:27:19 +00001095 if (!batch_mode)
1096 {
1097 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1098 out_stream->Printf("error: %s\n", error.AsCString());
1099 out_stream->Flush();
1100 }
Greg Clayton40e48242011-04-20 22:55:21 +00001101 add_regex_cmd->InputReaderDidCancel ();
1102 reader.SetIsDone (true);
Greg Claytond12aeab2011-04-20 16:37:46 +00001103 }
1104 }
1105 break;
1106
1107 case eInputReaderInterrupt:
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001108 {
1109 reader.SetIsDone (true);
Caroline Tice892fadd2011-06-16 16:27:19 +00001110 if (!batch_mode)
1111 {
1112 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1113 out_stream->PutCString("Regular expression command creations was cancelled.\n");
1114 out_stream->Flush();
1115 }
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001116 add_regex_cmd->InputReaderDidCancel ();
1117 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001118 break;
1119
1120 case eInputReaderEndOfFile:
1121 reader.SetIsDone (true);
1122 break;
1123
1124 case eInputReaderDone:
Greg Clayton40e48242011-04-20 22:55:21 +00001125 add_regex_cmd->AddRegexCommandToInterpreter();
Greg Claytond12aeab2011-04-20 16:37:46 +00001126 break;
1127 }
1128
1129 return bytes_len;
1130}
1131
1132
1133OptionDefinition
1134CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1135{
Greg Clayton40e48242011-04-20 22:55:21 +00001136{ 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 +00001137{ 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 +00001138{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Greg Claytond12aeab2011-04-20 16:37:46 +00001139};
1140
1141
Enrico Granata6b1596d2011-08-16 23:24:13 +00001142class CommandObjectPythonFunction : public CommandObject
1143{
1144private:
1145 std::string m_function_name;
1146
1147public:
1148
1149 CommandObjectPythonFunction (CommandInterpreter &interpreter,
1150 std::string name,
1151 std::string funct) :
1152 CommandObject (interpreter,
1153 name.c_str(),
1154 (std::string("Run Python function ") + funct).c_str(),
1155 NULL),
1156 m_function_name(funct)
1157 {
1158 }
1159
1160 virtual
1161 ~CommandObjectPythonFunction ()
1162 {
1163 }
1164
1165 virtual bool
1166 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
1167 {
1168 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1169
1170 Error error;
1171
1172 if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(),
1173 raw_command_line,
1174 result,
1175 error) == false)
1176 {
1177 result.AppendError(error.AsCString());
1178 result.SetStatus(eReturnStatusFailed);
1179 }
1180 else
1181 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1182
1183 return result.Succeeded();
1184 }
1185
1186 virtual bool
1187 WantsRawCommandString ()
1188 {
1189 return true;
1190 }
1191
1192 bool
1193 Execute (Args& command,
1194 CommandReturnObject &result)
1195 {
1196 std::string cmd_string;
1197 command.GetCommandString(cmd_string);
1198 return ExecuteRawCommandString(cmd_string.c_str(), result);
1199 }
1200
1201 virtual bool
1202 IsRemovable() { return true; }
1203
1204};
1205
1206
1207//-------------------------------------------------------------------------
1208// CommandObjectCommandsScriptAdd
1209//-------------------------------------------------------------------------
1210
1211class CommandObjectCommandsScriptAdd : public CommandObject
1212{
1213private:
1214
1215 class CommandOptions : public Options
1216 {
1217 public:
1218
1219 CommandOptions (CommandInterpreter &interpreter) :
1220 Options (interpreter)
1221 {
1222 }
1223
1224 virtual
1225 ~CommandOptions (){}
1226
1227 virtual Error
1228 SetOptionValue (uint32_t option_idx, const char *option_arg)
1229 {
1230 Error error;
1231 char short_option = (char) m_getopt_table[option_idx].val;
1232
1233 switch (short_option)
1234 {
1235 case 'f':
1236 m_funct_name = std::string(option_arg);
1237 break;
1238 default:
1239 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1240 break;
1241 }
1242
1243 return error;
1244 }
1245
1246 void
1247 OptionParsingStarting ()
1248 {
1249 m_funct_name = "";
1250 }
1251
1252 const OptionDefinition*
1253 GetDefinitions ()
1254 {
1255 return g_option_table;
1256 }
1257
1258 // Options table: Required for subclasses of Options.
1259
1260 static OptionDefinition g_option_table[];
1261
1262 // Instance variables to hold the values for command options.
1263
1264 std::string m_funct_name;
1265 };
1266
1267 CommandOptions m_options;
1268
1269 virtual Options *
1270 GetOptions ()
1271 {
1272 return &m_options;
1273 }
1274
1275 class PythonAliasReader : public InputReaderEZ
1276 {
1277 private:
1278 CommandInterpreter& m_interpreter;
1279 std::string m_cmd_name;
1280 StringList m_user_input;
1281 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
1282 public:
1283 PythonAliasReader(Debugger& debugger,
1284 CommandInterpreter& interpreter,
1285 std::string cmd_name) :
1286 InputReaderEZ(debugger),
1287 m_interpreter(interpreter),
1288 m_cmd_name(cmd_name),
1289 m_user_input()
1290 {}
1291
1292 virtual
1293 ~PythonAliasReader()
1294 {
1295 }
1296
1297 virtual void ActivateHandler(HandlerData& data)
1298 {
1299 StreamSP out_stream = data.GetOutStream();
1300 bool batch_mode = data.GetBatchMode();
1301 if (!batch_mode)
1302 {
1303 out_stream->Printf ("%s\n", g_python_command_instructions);
1304 if (data.reader.GetPrompt())
1305 out_stream->Printf ("%s", data.reader.GetPrompt());
1306 out_stream->Flush();
1307 }
1308 }
1309
1310 virtual void ReactivateHandler(HandlerData& data)
1311 {
1312 StreamSP out_stream = data.GetOutStream();
1313 bool batch_mode = data.GetBatchMode();
1314 if (data.reader.GetPrompt() && !batch_mode)
1315 {
1316 out_stream->Printf ("%s", data.reader.GetPrompt());
1317 out_stream->Flush();
1318 }
1319 }
1320 virtual void GotTokenHandler(HandlerData& data)
1321 {
1322 StreamSP out_stream = data.GetOutStream();
1323 bool batch_mode = data.GetBatchMode();
1324 if (data.bytes && data.bytes_len)
1325 {
1326 m_user_input.AppendString(data.bytes, data.bytes_len);
1327 }
1328 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
1329 {
1330 out_stream->Printf ("%s", data.reader.GetPrompt());
1331 out_stream->Flush();
1332 }
1333 }
1334 virtual void InterruptHandler(HandlerData& data)
1335 {
1336 StreamSP out_stream = data.GetOutStream();
1337 bool batch_mode = data.GetBatchMode();
1338 data.reader.SetIsDone (true);
1339 if (!batch_mode)
1340 {
1341 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
1342 out_stream->Flush();
1343 }
1344 }
1345 virtual void EOFHandler(HandlerData& data)
1346 {
1347 data.reader.SetIsDone (true);
1348 }
1349 virtual void DoneHandler(HandlerData& data)
1350 {
1351 StreamSP out_stream = data.GetOutStream();
1352
1353 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1354 if (!interpreter)
1355 {
1356 out_stream->Printf ("Internal error #1: no script attached.\n");
1357 out_stream->Flush();
1358 return;
1359 }
1360 StringList funct_name_sl;
1361 if (!interpreter->GenerateScriptAliasFunction (m_user_input,
1362 funct_name_sl))
1363 {
1364 out_stream->Printf ("Internal error #2: no script attached.\n");
1365 out_stream->Flush();
1366 return;
1367 }
1368 if (funct_name_sl.GetSize() == 0)
1369 {
1370 out_stream->Printf ("Internal error #3: no script attached.\n");
1371 out_stream->Flush();
1372 return;
1373 }
1374 const char *funct_name = funct_name_sl.GetStringAtIndex(0);
1375 if (!funct_name || !funct_name[0])
1376 {
1377 out_stream->Printf ("Internal error #4: no script attached.\n");
1378 out_stream->Flush();
1379 return;
1380 }
1381
1382 // everything should be fine now, let's add this alias
1383
1384 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
1385 m_cmd_name,
1386 funct_name));
1387
1388 if (!m_interpreter.AddUserCommand(m_cmd_name.c_str(), command_obj_sp, true))
1389 {
1390 out_stream->Printf ("Internal error #5: no script attached.\n");
1391 out_stream->Flush();
1392 return;
1393 }
1394 }
1395 };
1396
1397public:
1398 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1399 CommandObject (interpreter,
1400 "command script add",
1401 "Add a scripted function as an LLDB command.",
1402 NULL),
1403 m_options (interpreter)
1404 {
1405 CommandArgumentEntry arg1;
1406 CommandArgumentData cmd_arg;
1407
1408 // Define the first (and only) variant of this arg.
1409 cmd_arg.arg_type = eArgTypeCommandName;
1410 cmd_arg.arg_repetition = eArgRepeatPlain;
1411
1412 // There is only one variant this argument could be; put it into the argument entry.
1413 arg1.push_back (cmd_arg);
1414
1415 // Push the data for the first argument into the m_arguments vector.
1416 m_arguments.push_back (arg1);
1417 }
1418
1419 ~CommandObjectCommandsScriptAdd ()
1420 {
1421 }
1422
1423 bool
1424 Execute
1425 (
1426 Args& args,
1427 CommandReturnObject &result
1428 )
1429 {
1430 size_t argc = args.GetArgumentCount();
1431
1432 if (argc != 1)
1433 {
1434 result.AppendError ("'command script add' requires one argument");
1435 result.SetStatus (eReturnStatusFailed);
1436 return false;
1437 }
1438
1439 std::string cmd_name = args.GetArgumentAtIndex(0);
1440
1441 if (m_options.m_funct_name.empty())
1442 {
1443 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
1444 m_interpreter,
1445 cmd_name));
1446
1447 if (reader_sp)
1448 {
1449
1450 InputReaderEZ::InitializationParameters ipr;
1451
1452 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
1453 if (err.Success())
1454 {
1455 m_interpreter.GetDebugger().PushInputReader (reader_sp);
1456 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1457 }
1458 else
1459 {
1460 result.AppendError (err.AsCString());
1461 result.SetStatus (eReturnStatusFailed);
1462 }
1463 }
1464 else
1465 {
1466 result.AppendError("out of memory");
1467 result.SetStatus (eReturnStatusFailed);
1468 }
1469 }
1470 else
1471 {
1472 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, cmd_name, m_options.m_funct_name));
1473 if (m_interpreter.AddUserCommand(cmd_name.c_str(), new_cmd, true))
1474 {
1475 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1476 }
1477 else
1478 {
1479 result.AppendError("cannot add command");
1480 result.SetStatus (eReturnStatusFailed);
1481 }
1482 }
1483
1484 return result.Succeeded();
1485
1486 }
1487};
1488
1489OptionDefinition
1490CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1491{
1492 { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypeName, "Name of a Python function to use."},
1493 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1494};
1495
1496//-------------------------------------------------------------------------
1497// CommandObjectCommandsScriptList
1498//-------------------------------------------------------------------------
1499
1500class CommandObjectCommandsScriptList : public CommandObject
1501{
1502private:
1503
1504public:
1505 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1506 CommandObject (interpreter,
1507 "command script list",
1508 "List defined scripted commands.",
1509 NULL)
1510 {
1511 }
1512
1513 ~CommandObjectCommandsScriptList ()
1514 {
1515 }
1516
1517 bool
1518 Execute
1519 (
1520 Args& args,
1521 CommandReturnObject &result
1522 )
1523 {
1524
1525 m_interpreter.GetHelp(result,
1526 CommandInterpreter::eCommandTypesUserDef);
1527
1528 result.SetStatus (eReturnStatusSuccessFinishResult);
1529
1530 return true;
1531
1532
1533 }
1534};
1535
1536//-------------------------------------------------------------------------
1537// CommandObjectCommandsScriptClear
1538//-------------------------------------------------------------------------
1539
1540class CommandObjectCommandsScriptClear : public CommandObject
1541{
1542private:
1543
1544public:
1545 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
1546 CommandObject (interpreter,
1547 "command script clear",
1548 "Delete all scripted commands.",
1549 NULL)
1550 {
1551 }
1552
1553 ~CommandObjectCommandsScriptClear ()
1554 {
1555 }
1556
1557 bool
1558 Execute
1559 (
1560 Args& args,
1561 CommandReturnObject &result
1562 )
1563 {
1564
1565 m_interpreter.RemoveAllUser();
1566
1567 result.SetStatus (eReturnStatusSuccessFinishResult);
1568
1569 return true;
1570
1571
1572 }
1573};
1574
1575//-------------------------------------------------------------------------
1576// CommandObjectCommandsScriptDelete
1577//-------------------------------------------------------------------------
1578
1579class CommandObjectCommandsScriptDelete : public CommandObject
1580{
1581private:
1582
1583public:
1584 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
1585 CommandObject (interpreter,
1586 "command script delete",
1587 "Delete a scripted command.",
1588 NULL)
1589 {
1590 CommandArgumentEntry arg1;
1591 CommandArgumentData cmd_arg;
1592
1593 // Define the first (and only) variant of this arg.
1594 cmd_arg.arg_type = eArgTypeCommandName;
1595 cmd_arg.arg_repetition = eArgRepeatPlain;
1596
1597 // There is only one variant this argument could be; put it into the argument entry.
1598 arg1.push_back (cmd_arg);
1599
1600 // Push the data for the first argument into the m_arguments vector.
1601 m_arguments.push_back (arg1);
1602 }
1603
1604 ~CommandObjectCommandsScriptDelete ()
1605 {
1606 }
1607
1608 bool
1609 Execute
1610 (
1611 Args& args,
1612 CommandReturnObject &result
1613 )
1614 {
1615
1616 size_t argc = args.GetArgumentCount();
1617
1618 if (argc != 1)
1619 {
1620 result.AppendError ("'command script delete' requires one argument");
1621 result.SetStatus (eReturnStatusFailed);
1622 return false;
1623 }
1624
1625 const char* cmd_name = args.GetArgumentAtIndex(0);
1626
1627 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
1628 {
1629 m_interpreter.RemoveUser(cmd_name);
1630 result.SetStatus (eReturnStatusSuccessFinishResult);
1631 }
1632 else
1633 {
1634 result.AppendErrorWithFormat ("command %s not found", cmd_name);
1635 result.SetStatus (eReturnStatusFailed);
1636 }
1637
1638 return result.Succeeded();
1639
1640 }
1641};
1642
1643#pragma mark CommandObjectMultiwordCommandsScript
1644
1645//-------------------------------------------------------------------------
1646// CommandObjectMultiwordCommandsScript
1647//-------------------------------------------------------------------------
1648
1649class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
1650{
1651public:
1652 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
1653 CommandObjectMultiword (interpreter,
1654 "command script",
1655 "A set of commands for managing or customizing script commands.",
1656 "command script <subcommand> [<subcommand-options>]")
1657 {
1658 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
1659 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
1660 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
1661 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
1662 }
1663
1664 ~CommandObjectMultiwordCommandsScript ()
1665 {
1666 }
1667
1668};
1669
1670
Jim Ingham767af882010-07-07 03:36:20 +00001671#pragma mark CommandObjectMultiwordCommands
1672
1673//-------------------------------------------------------------------------
1674// CommandObjectMultiwordCommands
1675//-------------------------------------------------------------------------
1676
1677CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001678 CommandObjectMultiword (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +00001679 "command",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001680 "A set of commands for managing or customizing the debugger commands.",
Greg Clayton40e48242011-04-20 22:55:21 +00001681 "command <subcommand> [<subcommand-options>]")
Jim Ingham767af882010-07-07 03:36:20 +00001682{
Greg Clayton238c0a12010-09-18 01:14:36 +00001683 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1684 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1685 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +00001686 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham6247dbe2011-07-12 03:12:18 +00001687 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
Enrico Granata6b1596d2011-08-16 23:24:13 +00001688 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +00001689}
1690
1691CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1692{
1693}
1694