blob: d722d1d17e1a6336a6e1d8013e9e8e0e297ee61c [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\
354 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
355 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\
358 launch' example below). So in the 'bfl' case, the actual file value will be \n\
359 filled in with the first argument following 'bfl' and the actual line number \n\
360 value will be filled in with the second argument. The user would use this \n\
361 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000362 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000363 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000364 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000365 \nThis would be the same as if the user had entered \n\
366 'breakpoint set -f my-file.c -l 137'. \n\
367 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000368 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
369 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000370 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000371 \nIf the user always wanted to pass the same value to a particular option, the \n\
372 alias could be defined with that value directly in the alias as a constant, \n\
373 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000374 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
375 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000376
Caroline Tice43b014a2010-10-04 22:28:36 +0000377 CommandArgumentEntry arg1;
378 CommandArgumentEntry arg2;
379 CommandArgumentEntry arg3;
380 CommandArgumentData alias_arg;
381 CommandArgumentData cmd_arg;
382 CommandArgumentData options_arg;
383
384 // Define the first (and only) variant of this arg.
385 alias_arg.arg_type = eArgTypeAliasName;
386 alias_arg.arg_repetition = eArgRepeatPlain;
387
388 // There is only one variant this argument could be; put it into the argument entry.
389 arg1.push_back (alias_arg);
390
391 // Define the first (and only) variant of this arg.
392 cmd_arg.arg_type = eArgTypeCommandName;
393 cmd_arg.arg_repetition = eArgRepeatPlain;
394
395 // There is only one variant this argument could be; put it into the argument entry.
396 arg2.push_back (cmd_arg);
397
398 // Define the first (and only) variant of this arg.
399 options_arg.arg_type = eArgTypeAliasOptions;
400 options_arg.arg_repetition = eArgRepeatOptional;
401
402 // There is only one variant this argument could be; put it into the argument entry.
403 arg3.push_back (options_arg);
404
405 // Push the data for the first argument into the m_arguments vector.
406 m_arguments.push_back (arg1);
407 m_arguments.push_back (arg2);
408 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000409 }
410
411 ~CommandObjectCommandsAlias ()
412 {
413 }
414
Caroline Ticee0da7a52010-12-09 22:52:49 +0000415 bool
416 WantsRawCommandString ()
417 {
418 return true;
419 }
420
421 bool
422 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
423 {
424 Args args (raw_command_line);
425 std::string raw_command_string (raw_command_line);
426
427 size_t argc = args.GetArgumentCount();
428
429 if (argc < 2)
430 {
431 result.AppendError ("'alias' requires at least two arguments");
432 result.SetStatus (eReturnStatusFailed);
433 return false;
434 }
435
436 // Get the alias command.
437
438 const std::string alias_command = args.GetArgumentAtIndex (0);
Enrico Granatac2a28252011-08-16 16:49:25 +0000439
Caroline Ticee0da7a52010-12-09 22:52:49 +0000440 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
441 // does the stripping itself.
442 size_t pos = raw_command_string.find (alias_command);
443 if (pos == 0)
444 {
445 raw_command_string = raw_command_string.substr (alias_command.size());
446 pos = raw_command_string.find_first_not_of (' ');
447 if ((pos != std::string::npos) && (pos > 0))
448 raw_command_string = raw_command_string.substr (pos);
449 }
450 else
451 {
452 result.AppendError ("Error parsing command string. No alias created.");
453 result.SetStatus (eReturnStatusFailed);
454 return false;
455 }
456
457
458 // Verify that the command is alias-able.
459 if (m_interpreter.CommandExists (alias_command.c_str()))
460 {
461 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
462 alias_command.c_str());
463 result.SetStatus (eReturnStatusFailed);
464 return false;
465 }
466
467 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
468 // raw_command_string is returned with the name of the command object stripped off the front.
469 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
470
471 if (!cmd_obj)
472 {
473 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
474 " No alias created.", raw_command_string.c_str());
475 result.SetStatus (eReturnStatusFailed);
476 return false;
477 }
478 else if (!cmd_obj->WantsRawCommandString ())
479 {
480 // Note that args was initialized with the original command, and has not been updated to this point.
481 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
482 return Execute (args, result);
483 }
484 else
485 {
486 // Verify & handle any options/arguments passed to the alias command
487
488 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
489 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
490
Caroline Tice5ddbe212011-05-06 21:37:15 +0000491 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
492
493 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
Caroline Ticee0da7a52010-12-09 22:52:49 +0000494 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000495 result.AppendError ("Unable to create requested alias.\n");
496 result.SetStatus (eReturnStatusFailed);
497 return false;
Caroline Ticee0da7a52010-12-09 22:52:49 +0000498 }
499
500 // Create the alias
501 if (m_interpreter.AliasExists (alias_command.c_str())
502 || m_interpreter.UserCommandExists (alias_command.c_str()))
503 {
504 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
505 if (temp_option_arg_sp.get())
506 {
507 if (option_arg_vector->size() == 0)
508 m_interpreter.RemoveAliasOptions (alias_command.c_str());
509 }
510 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
511 alias_command.c_str());
512 }
513
Caroline Tice56d2fc42010-12-14 18:51:39 +0000514 if (cmd_obj_sp)
515 {
516 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
517 if (option_arg_vector->size() > 0)
518 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
519 result.SetStatus (eReturnStatusSuccessFinishNoResult);
520 }
521 else
522 {
523 result.AppendError ("Unable to create requested alias.\n");
524 result.SetStatus (eReturnStatusFailed);
525 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000526 }
527 return result.Succeeded();
528 }
Jim Ingham767af882010-07-07 03:36:20 +0000529
530 bool
531 Execute
532 (
Jim Ingham767af882010-07-07 03:36:20 +0000533 Args& args,
534 CommandReturnObject &result
535 )
536 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000537 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000538
539 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000540 {
Jim Ingham767af882010-07-07 03:36:20 +0000541 result.AppendError ("'alias' requires at least two arguments");
542 result.SetStatus (eReturnStatusFailed);
543 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000544 }
Jim Ingham767af882010-07-07 03:36:20 +0000545
546 const std::string alias_command = args.GetArgumentAtIndex(0);
547 const std::string actual_command = args.GetArgumentAtIndex(1);
548
549 args.Shift(); // Shift the alias command word off the argument vector.
550 args.Shift(); // Shift the old command word off the argument vector.
551
552 // Verify that the command is alias'able, and get the appropriate command object.
553
Greg Clayton238c0a12010-09-18 01:14:36 +0000554 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000555 {
556 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
557 alias_command.c_str());
558 result.SetStatus (eReturnStatusFailed);
559 }
560 else
561 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000562 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000563 CommandObjectSP subcommand_obj_sp;
564 bool use_subcommand = false;
565 if (command_obj_sp.get())
566 {
567 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000568 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000569 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
570 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
571
Caroline Ticee0da7a52010-12-09 22:52:49 +0000572 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000573 {
574 if (argc >= 3)
575 {
576 const std::string sub_command = args.GetArgumentAtIndex(0);
577 assert (sub_command.length() != 0);
578 subcommand_obj_sp =
579 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
580 if (subcommand_obj_sp.get())
581 {
582 sub_cmd_obj = subcommand_obj_sp.get();
583 use_subcommand = true;
584 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000585 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000586 }
587 else
588 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000589 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
590 "Unable to create alias.\n",
591 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000592 result.SetStatus (eReturnStatusFailed);
593 return false;
594 }
595 }
596 }
597
598 // Verify & handle any options/arguments passed to the alias command
599
600 if (args.GetArgumentCount () > 0)
601 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000602 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
603 if (use_subcommand)
604 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
605
606 std::string args_string;
607 args.GetCommandString (args_string);
608
609 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
610 {
611 result.AppendError ("Unable to create requested alias.\n");
612 result.SetStatus (eReturnStatusFailed);
613 return false;
614 }
Jim Ingham767af882010-07-07 03:36:20 +0000615 }
616
617 // Create the alias.
618
Greg Clayton238c0a12010-09-18 01:14:36 +0000619 if (m_interpreter.AliasExists (alias_command.c_str())
620 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000621 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000622 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000623 if (tmp_option_arg_sp.get())
624 {
625 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000626 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000627 }
628 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
629 alias_command.c_str());
630 }
631
632 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000633 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000634 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000635 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000636 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000637 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000638 result.SetStatus (eReturnStatusSuccessFinishNoResult);
639 }
640 else
641 {
642 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
643 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000644 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000645 }
646 }
647
648 return result.Succeeded();
649 }
650};
651
652#pragma mark CommandObjectCommandsUnalias
653//-------------------------------------------------------------------------
654// CommandObjectCommandsUnalias
655//-------------------------------------------------------------------------
656
657class CommandObjectCommandsUnalias : public CommandObject
658{
659public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000660 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
661 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000662 "command unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000663 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000664 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000665 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000666 CommandArgumentEntry arg;
667 CommandArgumentData alias_arg;
668
669 // Define the first (and only) variant of this arg.
670 alias_arg.arg_type = eArgTypeAliasName;
671 alias_arg.arg_repetition = eArgRepeatPlain;
672
673 // There is only one variant this argument could be; put it into the argument entry.
674 arg.push_back (alias_arg);
675
676 // Push the data for the first argument into the m_arguments vector.
677 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000678 }
679
680 ~CommandObjectCommandsUnalias()
681 {
682 }
683
684
685 bool
686 Execute
687 (
Jim Ingham767af882010-07-07 03:36:20 +0000688 Args& args,
689 CommandReturnObject &result
690 )
691 {
692 CommandObject::CommandMap::iterator pos;
693 CommandObject *cmd_obj;
694
695 if (args.GetArgumentCount() != 0)
696 {
697 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000698 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000699 if (cmd_obj)
700 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000701 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000702 {
703 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
704 command_name);
705 result.SetStatus (eReturnStatusFailed);
706 }
707 else
708 {
709
Greg Clayton238c0a12010-09-18 01:14:36 +0000710 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000711 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000712 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000713 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
714 command_name);
715 else
716 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
717 result.SetStatus (eReturnStatusFailed);
718 }
719 else
720 result.SetStatus (eReturnStatusSuccessFinishNoResult);
721 }
722 }
723 else
724 {
725 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
726 "current list of commands.\n",
727 command_name);
728 result.SetStatus (eReturnStatusFailed);
729 }
730 }
731 else
732 {
733 result.AppendError ("must call 'unalias' with a valid alias");
734 result.SetStatus (eReturnStatusFailed);
735 }
736
737 return result.Succeeded();
738 }
739};
740
Greg Claytond12aeab2011-04-20 16:37:46 +0000741#pragma mark CommandObjectCommandsAddRegex
742//-------------------------------------------------------------------------
743// CommandObjectCommandsAddRegex
744//-------------------------------------------------------------------------
745
746class CommandObjectCommandsAddRegex : public CommandObject
747{
748public:
749 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
750 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000751 "command regex",
Greg Claytond12aeab2011-04-20 16:37:46 +0000752 "Allow the user to create a regular expression command.",
Greg Clayton40e48242011-04-20 22:55:21 +0000753 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
Greg Claytond12aeab2011-04-20 16:37:46 +0000754 m_options (interpreter)
755 {
Greg Clayton40e48242011-04-20 22:55:21 +0000756 SetHelpLong(
757"This command allows the user to create powerful regular expression commands\n"
758"with substitutions. The regular expressions and substitutions are specified\n"
759"using the regular exression substitution format of:\n"
760"\n"
761" s/<regex>/<subst>/\n"
762"\n"
763"<regex> is a regular expression that can use parenthesis to capture regular\n"
764"expression input and substitute the captured matches in the output using %1\n"
765"for the first match, %2 for the second, and so on.\n"
766"\n"
767"The regular expressions can all be specified on the command line if more than\n"
768"one argument is provided. If just the command name is provided on the command\n"
769"line, then the regular expressions and substitutions can be entered on separate\n"
770" lines, followed by an empty line to terminate the command definition.\n"
771"\n"
772"EXAMPLES\n"
773"\n"
774"The following example with define a regular expression command named 'f' that\n"
775"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
776"a number follows 'f':\n"
777"(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
778 );
Greg Claytond12aeab2011-04-20 16:37:46 +0000779 }
780
781 ~CommandObjectCommandsAddRegex()
782 {
783 }
784
785
786 bool
787 Execute (Args& args, CommandReturnObject &result)
788 {
Greg Clayton40e48242011-04-20 22:55:21 +0000789 const size_t argc = args.GetArgumentCount();
790 if (argc == 0)
Greg Claytond12aeab2011-04-20 16:37:46 +0000791 {
Greg Clayton40e48242011-04-20 22:55:21 +0000792 result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
793 result.SetStatus (eReturnStatusFailed);
794 }
795 else
796 {
797 Error error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000798 const char *name = args.GetArgumentAtIndex(0);
Greg Claytond12aeab2011-04-20 16:37:46 +0000799 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
800 name,
801 m_options.GetHelp (),
802 m_options.GetSyntax (),
803 10));
Greg Clayton40e48242011-04-20 22:55:21 +0000804
805 if (argc == 1)
Greg Claytond12aeab2011-04-20 16:37:46 +0000806 {
Greg Clayton40e48242011-04-20 22:55:21 +0000807 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
808 if (reader_sp)
809 {
810 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
Greg Claytond12aeab2011-04-20 16:37:46 +0000811 this, // baton
812 eInputReaderGranularityLine, // token size, to pass to callback function
Greg Clayton40e48242011-04-20 22:55:21 +0000813 NULL, // end token
Greg Claytond12aeab2011-04-20 16:37:46 +0000814 "> ", // prompt
Greg Clayton40e48242011-04-20 22:55:21 +0000815 true); // echo input
816 if (error.Success())
817 {
818 m_interpreter.GetDebugger().PushInputReader (reader_sp);
819 result.SetStatus (eReturnStatusSuccessFinishNoResult);
820 return true;
821 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000822 }
823 }
Greg Clayton40e48242011-04-20 22:55:21 +0000824 else
825 {
826 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
827 {
828 llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
829 error = AppendRegexSubstitution (arg_strref);
830 if (error.Fail())
831 break;
832 }
833
834 if (error.Success())
835 {
836 AddRegexCommandToInterpreter();
837 }
838 }
839 if (error.Fail())
840 {
841 result.AppendError (error.AsCString());
842 result.SetStatus (eReturnStatusFailed);
843 }
Greg Claytond12aeab2011-04-20 16:37:46 +0000844 }
Greg Clayton40e48242011-04-20 22:55:21 +0000845
Greg Claytond12aeab2011-04-20 16:37:46 +0000846 return result.Succeeded();
847 }
848
Greg Clayton40e48242011-04-20 22:55:21 +0000849 Error
850 AppendRegexSubstitution (const llvm::StringRef &regex_sed)
Greg Claytond12aeab2011-04-20 16:37:46 +0000851 {
Greg Clayton40e48242011-04-20 22:55:21 +0000852 Error error;
853
854 if (m_regex_cmd_ap.get() == NULL)
Greg Claytond12aeab2011-04-20 16:37:46 +0000855 {
Greg Clayton40e48242011-04-20 22:55:21 +0000856 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
857 (int)regex_sed.size(),
858 regex_sed.data());
859 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000860 }
Greg Clayton40e48242011-04-20 22:55:21 +0000861
862 size_t regex_sed_size = regex_sed.size();
863
864 if (regex_sed_size <= 1)
865 {
866 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
867 (int)regex_sed.size(),
868 regex_sed.data());
869 return error;
870 }
871
872 if (regex_sed[0] != 's')
873 {
874 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
875 (int)regex_sed.size(),
876 regex_sed.data());
877 return error;
878 }
879 const size_t first_separator_char_pos = 1;
880 // use the char that follows 's' as the regex separator character
881 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
882 const char separator_char = regex_sed[first_separator_char_pos];
883 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
884
885 if (second_separator_char_pos == std::string::npos)
886 {
887 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
888 separator_char,
889 (int)(regex_sed.size() - first_separator_char_pos - 1),
890 regex_sed.data() + (first_separator_char_pos + 1));
891 return error;
892 }
893
894 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
895
896 if (third_separator_char_pos == std::string::npos)
897 {
898 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
899 separator_char,
900 (int)(regex_sed.size() - second_separator_char_pos - 1),
901 regex_sed.data() + (second_separator_char_pos + 1));
902 return error;
903 }
904
905 if (third_separator_char_pos != regex_sed_size - 1)
906 {
907 // Make sure that everything that follows the last regex
908 // separator char
909 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
910 {
911 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
912 (int)third_separator_char_pos + 1,
913 regex_sed.data(),
914 (int)(regex_sed.size() - third_separator_char_pos - 1),
915 regex_sed.data() + (third_separator_char_pos + 1));
916 return error;
917 }
918
919 }
920 else if (first_separator_char_pos + 1 == second_separator_char_pos)
921 {
922 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
923 separator_char,
924 separator_char,
925 separator_char,
926 (int)regex_sed.size(),
927 regex_sed.data());
928 return error;
929 }
930 else if (second_separator_char_pos + 1 == third_separator_char_pos)
931 {
932 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
933 separator_char,
934 separator_char,
935 separator_char,
936 (int)regex_sed.size(),
937 regex_sed.data());
938 return error;
939 }
940 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
941 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
942 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
943 subst.c_str());
944 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +0000945 }
946
947 void
Greg Clayton40e48242011-04-20 22:55:21 +0000948 AddRegexCommandToInterpreter()
Greg Claytond12aeab2011-04-20 16:37:46 +0000949 {
950 if (m_regex_cmd_ap.get())
951 {
952 if (m_regex_cmd_ap->HasRegexEntries())
953 {
954 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
955 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
956 }
957 }
958 }
959
Greg Clayton40e48242011-04-20 22:55:21 +0000960 void
961 InputReaderDidCancel()
962 {
963 m_regex_cmd_ap.reset();
964 }
965
Greg Claytond12aeab2011-04-20 16:37:46 +0000966 static size_t
967 InputReaderCallback (void *baton,
968 InputReader &reader,
969 lldb::InputReaderAction notification,
970 const char *bytes,
971 size_t bytes_len);
972private:
973 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
974
975 class CommandOptions : public Options
976 {
977 public:
978
979 CommandOptions (CommandInterpreter &interpreter) :
980 Options (interpreter)
981 {
982 }
983
984 virtual
985 ~CommandOptions (){}
986
987 virtual Error
988 SetOptionValue (uint32_t option_idx, const char *option_arg)
989 {
990 Error error;
991 char short_option = (char) m_getopt_table[option_idx].val;
992
993 switch (short_option)
994 {
995 case 'h':
996 m_help.assign (option_arg);
997 break;
998 case 's':
999 m_syntax.assign (option_arg);
1000 break;
1001
1002 default:
1003 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1004 break;
1005 }
1006
1007 return error;
1008 }
1009
1010 void
1011 OptionParsingStarting ()
1012 {
1013 m_help.clear();
1014 m_syntax.clear();
1015 }
1016
1017 const OptionDefinition*
1018 GetDefinitions ()
1019 {
1020 return g_option_table;
1021 }
1022
1023 // Options table: Required for subclasses of Options.
1024
1025 static OptionDefinition g_option_table[];
1026
1027 const char *
1028 GetHelp ()
1029 {
1030 if (m_help.empty())
1031 return NULL;
1032 return m_help.c_str();
1033 }
1034 const char *
1035 GetSyntax ()
1036 {
1037 if (m_syntax.empty())
1038 return NULL;
1039 return m_syntax.c_str();
1040 }
1041 // Instance variables to hold the values for command options.
1042 protected:
1043 std::string m_help;
1044 std::string m_syntax;
1045 };
1046
1047 CommandOptions m_options;
1048
1049 virtual Options *
1050 GetOptions ()
1051 {
1052 return &m_options;
1053 }
1054
1055};
1056
1057size_t
1058CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1059 InputReader &reader,
1060 lldb::InputReaderAction notification,
1061 const char *bytes,
1062 size_t bytes_len)
1063{
1064 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
Caroline Tice892fadd2011-06-16 16:27:19 +00001065 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Greg Claytond12aeab2011-04-20 16:37:46 +00001066
1067 switch (notification)
1068 {
1069 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +00001070 if (!batch_mode)
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001071 {
1072 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1073 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1074 out_stream->Flush();
1075 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001076 break;
1077 case eInputReaderReactivate:
1078 break;
1079
1080 case eInputReaderDeactivate:
1081 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001082
1083 case eInputReaderAsynchronousOutputWritten:
1084 break;
1085
Greg Claytond12aeab2011-04-20 16:37:46 +00001086 case eInputReaderGotToken:
Greg Clayton40e48242011-04-20 22:55:21 +00001087 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1088 --bytes_len;
Greg Claytond12aeab2011-04-20 16:37:46 +00001089 if (bytes_len == 0)
1090 reader.SetIsDone(true);
1091 else if (bytes)
1092 {
Greg Clayton40e48242011-04-20 22:55:21 +00001093 llvm::StringRef bytes_strref (bytes, bytes_len);
1094 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1095 if (error.Fail())
Greg Claytond12aeab2011-04-20 16:37:46 +00001096 {
Caroline Tice892fadd2011-06-16 16:27:19 +00001097 if (!batch_mode)
1098 {
1099 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1100 out_stream->Printf("error: %s\n", error.AsCString());
1101 out_stream->Flush();
1102 }
Greg Clayton40e48242011-04-20 22:55:21 +00001103 add_regex_cmd->InputReaderDidCancel ();
1104 reader.SetIsDone (true);
Greg Claytond12aeab2011-04-20 16:37:46 +00001105 }
1106 }
1107 break;
1108
1109 case eInputReaderInterrupt:
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001110 {
1111 reader.SetIsDone (true);
Caroline Tice892fadd2011-06-16 16:27:19 +00001112 if (!batch_mode)
1113 {
1114 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1115 out_stream->PutCString("Regular expression command creations was cancelled.\n");
1116 out_stream->Flush();
1117 }
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001118 add_regex_cmd->InputReaderDidCancel ();
1119 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001120 break;
1121
1122 case eInputReaderEndOfFile:
1123 reader.SetIsDone (true);
1124 break;
1125
1126 case eInputReaderDone:
Greg Clayton40e48242011-04-20 22:55:21 +00001127 add_regex_cmd->AddRegexCommandToInterpreter();
Greg Claytond12aeab2011-04-20 16:37:46 +00001128 break;
1129 }
1130
1131 return bytes_len;
1132}
1133
1134
1135OptionDefinition
1136CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1137{
Greg Clayton40e48242011-04-20 22:55:21 +00001138{ 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 +00001139{ 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 +00001140{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Greg Claytond12aeab2011-04-20 16:37:46 +00001141};
1142
1143
Enrico Granata6b1596d2011-08-16 23:24:13 +00001144class CommandObjectPythonFunction : public CommandObject
1145{
1146private:
1147 std::string m_function_name;
1148
1149public:
1150
1151 CommandObjectPythonFunction (CommandInterpreter &interpreter,
1152 std::string name,
1153 std::string funct) :
1154 CommandObject (interpreter,
1155 name.c_str(),
1156 (std::string("Run Python function ") + funct).c_str(),
1157 NULL),
1158 m_function_name(funct)
1159 {
Enrico Granatae5e34cb2011-08-17 01:30:04 +00001160 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1161 if (scripter)
1162 {
1163 std::string docstring = scripter->GetDocumentationForItem(funct.c_str());
1164 if (!docstring.empty())
1165 SetHelpLong(docstring);
1166 }
Enrico Granata6b1596d2011-08-16 23:24:13 +00001167 }
1168
1169 virtual
1170 ~CommandObjectPythonFunction ()
1171 {
1172 }
1173
1174 virtual bool
1175 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
1176 {
1177 ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1178
1179 Error error;
1180
1181 if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(),
1182 raw_command_line,
1183 result,
1184 error) == false)
1185 {
1186 result.AppendError(error.AsCString());
1187 result.SetStatus(eReturnStatusFailed);
1188 }
1189 else
1190 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1191
1192 return result.Succeeded();
1193 }
1194
1195 virtual bool
1196 WantsRawCommandString ()
1197 {
1198 return true;
1199 }
1200
1201 bool
1202 Execute (Args& command,
1203 CommandReturnObject &result)
1204 {
1205 std::string cmd_string;
1206 command.GetCommandString(cmd_string);
1207 return ExecuteRawCommandString(cmd_string.c_str(), result);
1208 }
1209
1210 virtual bool
1211 IsRemovable() { return true; }
1212
1213};
1214
1215
1216//-------------------------------------------------------------------------
1217// CommandObjectCommandsScriptAdd
1218//-------------------------------------------------------------------------
1219
1220class CommandObjectCommandsScriptAdd : public CommandObject
1221{
1222private:
1223
1224 class CommandOptions : public Options
1225 {
1226 public:
1227
1228 CommandOptions (CommandInterpreter &interpreter) :
1229 Options (interpreter)
1230 {
1231 }
1232
1233 virtual
1234 ~CommandOptions (){}
1235
1236 virtual Error
1237 SetOptionValue (uint32_t option_idx, const char *option_arg)
1238 {
1239 Error error;
1240 char short_option = (char) m_getopt_table[option_idx].val;
1241
1242 switch (short_option)
1243 {
1244 case 'f':
1245 m_funct_name = std::string(option_arg);
1246 break;
1247 default:
1248 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1249 break;
1250 }
1251
1252 return error;
1253 }
1254
1255 void
1256 OptionParsingStarting ()
1257 {
1258 m_funct_name = "";
1259 }
1260
1261 const OptionDefinition*
1262 GetDefinitions ()
1263 {
1264 return g_option_table;
1265 }
1266
1267 // Options table: Required for subclasses of Options.
1268
1269 static OptionDefinition g_option_table[];
1270
1271 // Instance variables to hold the values for command options.
1272
1273 std::string m_funct_name;
1274 };
1275
1276 CommandOptions m_options;
1277
1278 virtual Options *
1279 GetOptions ()
1280 {
1281 return &m_options;
1282 }
1283
1284 class PythonAliasReader : public InputReaderEZ
1285 {
1286 private:
1287 CommandInterpreter& m_interpreter;
1288 std::string m_cmd_name;
1289 StringList m_user_input;
1290 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
1291 public:
1292 PythonAliasReader(Debugger& debugger,
1293 CommandInterpreter& interpreter,
1294 std::string cmd_name) :
1295 InputReaderEZ(debugger),
1296 m_interpreter(interpreter),
1297 m_cmd_name(cmd_name),
1298 m_user_input()
1299 {}
1300
1301 virtual
1302 ~PythonAliasReader()
1303 {
1304 }
1305
1306 virtual void ActivateHandler(HandlerData& data)
1307 {
1308 StreamSP out_stream = data.GetOutStream();
1309 bool batch_mode = data.GetBatchMode();
1310 if (!batch_mode)
1311 {
1312 out_stream->Printf ("%s\n", g_python_command_instructions);
1313 if (data.reader.GetPrompt())
1314 out_stream->Printf ("%s", data.reader.GetPrompt());
1315 out_stream->Flush();
1316 }
1317 }
1318
1319 virtual void ReactivateHandler(HandlerData& data)
1320 {
1321 StreamSP out_stream = data.GetOutStream();
1322 bool batch_mode = data.GetBatchMode();
1323 if (data.reader.GetPrompt() && !batch_mode)
1324 {
1325 out_stream->Printf ("%s", data.reader.GetPrompt());
1326 out_stream->Flush();
1327 }
1328 }
1329 virtual void GotTokenHandler(HandlerData& data)
1330 {
1331 StreamSP out_stream = data.GetOutStream();
1332 bool batch_mode = data.GetBatchMode();
1333 if (data.bytes && data.bytes_len)
1334 {
1335 m_user_input.AppendString(data.bytes, data.bytes_len);
1336 }
1337 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
1338 {
1339 out_stream->Printf ("%s", data.reader.GetPrompt());
1340 out_stream->Flush();
1341 }
1342 }
1343 virtual void InterruptHandler(HandlerData& data)
1344 {
1345 StreamSP out_stream = data.GetOutStream();
1346 bool batch_mode = data.GetBatchMode();
1347 data.reader.SetIsDone (true);
1348 if (!batch_mode)
1349 {
1350 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
1351 out_stream->Flush();
1352 }
1353 }
1354 virtual void EOFHandler(HandlerData& data)
1355 {
1356 data.reader.SetIsDone (true);
1357 }
1358 virtual void DoneHandler(HandlerData& data)
1359 {
1360 StreamSP out_stream = data.GetOutStream();
1361
1362 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1363 if (!interpreter)
1364 {
1365 out_stream->Printf ("Internal error #1: no script attached.\n");
1366 out_stream->Flush();
1367 return;
1368 }
1369 StringList funct_name_sl;
1370 if (!interpreter->GenerateScriptAliasFunction (m_user_input,
1371 funct_name_sl))
1372 {
1373 out_stream->Printf ("Internal error #2: no script attached.\n");
1374 out_stream->Flush();
1375 return;
1376 }
1377 if (funct_name_sl.GetSize() == 0)
1378 {
1379 out_stream->Printf ("Internal error #3: no script attached.\n");
1380 out_stream->Flush();
1381 return;
1382 }
1383 const char *funct_name = funct_name_sl.GetStringAtIndex(0);
1384 if (!funct_name || !funct_name[0])
1385 {
1386 out_stream->Printf ("Internal error #4: no script attached.\n");
1387 out_stream->Flush();
1388 return;
1389 }
1390
1391 // everything should be fine now, let's add this alias
1392
1393 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
1394 m_cmd_name,
1395 funct_name));
1396
1397 if (!m_interpreter.AddUserCommand(m_cmd_name.c_str(), command_obj_sp, true))
1398 {
1399 out_stream->Printf ("Internal error #5: no script attached.\n");
1400 out_stream->Flush();
1401 return;
1402 }
1403 }
1404 };
1405
1406public:
1407 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1408 CommandObject (interpreter,
1409 "command script add",
1410 "Add a scripted function as an LLDB command.",
1411 NULL),
1412 m_options (interpreter)
1413 {
1414 CommandArgumentEntry arg1;
1415 CommandArgumentData cmd_arg;
1416
1417 // Define the first (and only) variant of this arg.
1418 cmd_arg.arg_type = eArgTypeCommandName;
1419 cmd_arg.arg_repetition = eArgRepeatPlain;
1420
1421 // There is only one variant this argument could be; put it into the argument entry.
1422 arg1.push_back (cmd_arg);
1423
1424 // Push the data for the first argument into the m_arguments vector.
1425 m_arguments.push_back (arg1);
1426 }
1427
1428 ~CommandObjectCommandsScriptAdd ()
1429 {
1430 }
1431
1432 bool
1433 Execute
1434 (
1435 Args& args,
1436 CommandReturnObject &result
1437 )
1438 {
Enrico Granatae5e34cb2011-08-17 01:30:04 +00001439
1440 if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1441 {
1442 result.AppendError ("only scripting language supported for scripted commands is currently Python");
1443 result.SetStatus (eReturnStatusFailed);
1444 return false;
1445 }
1446
Enrico Granata6b1596d2011-08-16 23:24:13 +00001447 size_t argc = args.GetArgumentCount();
1448
1449 if (argc != 1)
1450 {
1451 result.AppendError ("'command script add' requires one argument");
1452 result.SetStatus (eReturnStatusFailed);
1453 return false;
1454 }
1455
1456 std::string cmd_name = args.GetArgumentAtIndex(0);
1457
1458 if (m_options.m_funct_name.empty())
1459 {
1460 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
1461 m_interpreter,
1462 cmd_name));
1463
1464 if (reader_sp)
1465 {
1466
1467 InputReaderEZ::InitializationParameters ipr;
1468
1469 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
1470 if (err.Success())
1471 {
1472 m_interpreter.GetDebugger().PushInputReader (reader_sp);
1473 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1474 }
1475 else
1476 {
1477 result.AppendError (err.AsCString());
1478 result.SetStatus (eReturnStatusFailed);
1479 }
1480 }
1481 else
1482 {
1483 result.AppendError("out of memory");
1484 result.SetStatus (eReturnStatusFailed);
1485 }
1486 }
1487 else
1488 {
1489 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, cmd_name, m_options.m_funct_name));
1490 if (m_interpreter.AddUserCommand(cmd_name.c_str(), new_cmd, true))
1491 {
1492 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1493 }
1494 else
1495 {
1496 result.AppendError("cannot add command");
1497 result.SetStatus (eReturnStatusFailed);
1498 }
1499 }
1500
1501 return result.Succeeded();
1502
1503 }
1504};
1505
1506OptionDefinition
1507CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1508{
1509 { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypeName, "Name of a Python function to use."},
1510 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1511};
1512
1513//-------------------------------------------------------------------------
1514// CommandObjectCommandsScriptList
1515//-------------------------------------------------------------------------
1516
1517class CommandObjectCommandsScriptList : public CommandObject
1518{
1519private:
1520
1521public:
1522 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1523 CommandObject (interpreter,
1524 "command script list",
1525 "List defined scripted commands.",
1526 NULL)
1527 {
1528 }
1529
1530 ~CommandObjectCommandsScriptList ()
1531 {
1532 }
1533
1534 bool
1535 Execute
1536 (
1537 Args& args,
1538 CommandReturnObject &result
1539 )
1540 {
1541
1542 m_interpreter.GetHelp(result,
1543 CommandInterpreter::eCommandTypesUserDef);
1544
1545 result.SetStatus (eReturnStatusSuccessFinishResult);
1546
1547 return true;
1548
1549
1550 }
1551};
1552
1553//-------------------------------------------------------------------------
1554// CommandObjectCommandsScriptClear
1555//-------------------------------------------------------------------------
1556
1557class CommandObjectCommandsScriptClear : public CommandObject
1558{
1559private:
1560
1561public:
1562 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
1563 CommandObject (interpreter,
1564 "command script clear",
1565 "Delete all scripted commands.",
1566 NULL)
1567 {
1568 }
1569
1570 ~CommandObjectCommandsScriptClear ()
1571 {
1572 }
1573
1574 bool
1575 Execute
1576 (
1577 Args& args,
1578 CommandReturnObject &result
1579 )
1580 {
1581
1582 m_interpreter.RemoveAllUser();
1583
1584 result.SetStatus (eReturnStatusSuccessFinishResult);
1585
1586 return true;
1587
1588
1589 }
1590};
1591
1592//-------------------------------------------------------------------------
1593// CommandObjectCommandsScriptDelete
1594//-------------------------------------------------------------------------
1595
1596class CommandObjectCommandsScriptDelete : public CommandObject
1597{
1598private:
1599
1600public:
1601 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
1602 CommandObject (interpreter,
1603 "command script delete",
1604 "Delete a scripted command.",
1605 NULL)
1606 {
1607 CommandArgumentEntry arg1;
1608 CommandArgumentData cmd_arg;
1609
1610 // Define the first (and only) variant of this arg.
1611 cmd_arg.arg_type = eArgTypeCommandName;
1612 cmd_arg.arg_repetition = eArgRepeatPlain;
1613
1614 // There is only one variant this argument could be; put it into the argument entry.
1615 arg1.push_back (cmd_arg);
1616
1617 // Push the data for the first argument into the m_arguments vector.
1618 m_arguments.push_back (arg1);
1619 }
1620
1621 ~CommandObjectCommandsScriptDelete ()
1622 {
1623 }
1624
1625 bool
1626 Execute
1627 (
1628 Args& args,
1629 CommandReturnObject &result
1630 )
1631 {
1632
1633 size_t argc = args.GetArgumentCount();
1634
1635 if (argc != 1)
1636 {
1637 result.AppendError ("'command script delete' requires one argument");
1638 result.SetStatus (eReturnStatusFailed);
1639 return false;
1640 }
1641
1642 const char* cmd_name = args.GetArgumentAtIndex(0);
1643
1644 if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
1645 {
1646 m_interpreter.RemoveUser(cmd_name);
1647 result.SetStatus (eReturnStatusSuccessFinishResult);
1648 }
1649 else
1650 {
1651 result.AppendErrorWithFormat ("command %s not found", cmd_name);
1652 result.SetStatus (eReturnStatusFailed);
1653 }
1654
1655 return result.Succeeded();
1656
1657 }
1658};
1659
1660#pragma mark CommandObjectMultiwordCommandsScript
1661
1662//-------------------------------------------------------------------------
1663// CommandObjectMultiwordCommandsScript
1664//-------------------------------------------------------------------------
1665
1666class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
1667{
1668public:
1669 CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
1670 CommandObjectMultiword (interpreter,
1671 "command script",
1672 "A set of commands for managing or customizing script commands.",
1673 "command script <subcommand> [<subcommand-options>]")
1674 {
1675 LoadSubCommand ("add", CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
1676 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
1677 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
1678 LoadSubCommand ("list", CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
1679 }
1680
1681 ~CommandObjectMultiwordCommandsScript ()
1682 {
1683 }
1684
1685};
1686
1687
Jim Ingham767af882010-07-07 03:36:20 +00001688#pragma mark CommandObjectMultiwordCommands
1689
1690//-------------------------------------------------------------------------
1691// CommandObjectMultiwordCommands
1692//-------------------------------------------------------------------------
1693
1694CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001695 CommandObjectMultiword (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +00001696 "command",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001697 "A set of commands for managing or customizing the debugger commands.",
Greg Clayton40e48242011-04-20 22:55:21 +00001698 "command <subcommand> [<subcommand-options>]")
Jim Ingham767af882010-07-07 03:36:20 +00001699{
Greg Clayton238c0a12010-09-18 01:14:36 +00001700 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1701 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1702 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +00001703 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham6247dbe2011-07-12 03:12:18 +00001704 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
Enrico Granata6b1596d2011-08-16 23:24:13 +00001705 LoadSubCommand ("script", CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +00001706}
1707
1708CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1709{
1710}
1711