blob: 09ac12b726ad641b0a03a29a4f33560e1ad5afcf [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
Enrico Granatac2a28252011-08-16 16:49:25 +000018#include "CommandObjectPythonFunction.h"
Jim Ingham767af882010-07-07 03:36:20 +000019#include "lldb/Core/Debugger.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000020#include "lldb/Core/InputReader.h"
Enrico Granatac2a28252011-08-16 16:49:25 +000021#include "lldb/Core/InputReaderEZ.h"
22#include "lldb/Core/StringList.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000023#include "lldb/Interpreter/Args.h"
Jim Ingham767af882010-07-07 03:36:20 +000024#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000025#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Jim Ingham767af882010-07-07 03:36:20 +000026#include "lldb/Interpreter/CommandReturnObject.h"
27#include "lldb/Interpreter/Options.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
Jim Ingham767af882010-07-07 03:36:20 +000032//-------------------------------------------------------------------------
33// CommandObjectCommandsSource
34//-------------------------------------------------------------------------
35
Jim Ingham6247dbe2011-07-12 03:12:18 +000036class CommandObjectCommandsHistory : public CommandObject
37{
38private:
39
40 class CommandOptions : public Options
41 {
42 public:
43
44 CommandOptions (CommandInterpreter &interpreter) :
45 Options (interpreter)
46 {
47 }
48
49 virtual
50 ~CommandOptions (){}
51
52 virtual Error
53 SetOptionValue (uint32_t option_idx, const char *option_arg)
54 {
55 Error error;
56 char short_option = (char) m_getopt_table[option_idx].val;
57 bool success;
58
59 switch (short_option)
60 {
61 case 'c':
62 m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
63 if (!success)
64 error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
65 if (m_end_idx != 0)
66 m_end_idx--;
67 m_start_idx = 0;
68 break;
69 case 'e':
70 m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
71 if (!success)
72 error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
73 break;
74 case 's':
75 m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
76 if (!success)
77 error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
78 break;
79 default:
80 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
81 break;
82 }
83
84 return error;
85 }
86
87 void
88 OptionParsingStarting ()
89 {
90 m_start_idx = 0;
91 m_end_idx = UINT_MAX;
92 }
93
94 const OptionDefinition*
95 GetDefinitions ()
96 {
97 return g_option_table;
98 }
99
100 // Options table: Required for subclasses of Options.
101
102 static OptionDefinition g_option_table[];
103
104 // Instance variables to hold the values for command options.
105
106 uint32_t m_start_idx;
107 uint32_t m_end_idx;
108 };
109
110 CommandOptions m_options;
111
112 virtual Options *
113 GetOptions ()
114 {
115 return &m_options;
116 }
117
118public:
119 CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
120 CommandObject (interpreter,
121 "command history",
122 "Dump the history of commands in this session.",
123 NULL),
124 m_options (interpreter)
125 {
126 }
127
128 ~CommandObjectCommandsHistory ()
129 {
130 }
131
132 bool
133 Execute
134 (
135 Args& args,
136 CommandReturnObject &result
137 )
138 {
139
140 m_interpreter.DumpHistory (result.GetOutputStream(),
141 m_options.m_start_idx,
142 m_options.m_end_idx);
143 return result.Succeeded();
144
145 }
146};
147
148OptionDefinition
149CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
150{
151{ LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger, "How many history commands to print."},
152{ LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands."},
153{ LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands."},
154{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
155};
156
157
158//-------------------------------------------------------------------------
159// CommandObjectCommandsSource
160//-------------------------------------------------------------------------
161
Jim Ingham767af882010-07-07 03:36:20 +0000162class CommandObjectCommandsSource : public CommandObject
163{
Jim Ingham949d5ac2011-02-18 00:54:25 +0000164private:
165
166 class CommandOptions : public Options
167 {
168 public:
169
Greg Claytonf15996e2011-04-07 22:46:35 +0000170 CommandOptions (CommandInterpreter &interpreter) :
171 Options (interpreter)
172 {
173 }
Jim Ingham949d5ac2011-02-18 00:54:25 +0000174
175 virtual
176 ~CommandOptions (){}
177
178 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000179 SetOptionValue (uint32_t option_idx, const char *option_arg)
Jim Ingham949d5ac2011-02-18 00:54:25 +0000180 {
181 Error error;
182 char short_option = (char) m_getopt_table[option_idx].val;
183 bool success;
184
185 switch (short_option)
186 {
187 case 'e':
188 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
189 if (!success)
190 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
191 break;
192 case 'c':
193 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
194 if (!success)
195 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
196 break;
197 default:
198 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
199 break;
200 }
201
202 return error;
203 }
204
205 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000206 OptionParsingStarting ()
Jim Ingham949d5ac2011-02-18 00:54:25 +0000207 {
Jim Ingham949d5ac2011-02-18 00:54:25 +0000208 m_stop_on_error = true;
209 m_stop_on_continue = true;
210 }
211
Greg Claytonb3448432011-03-24 21:19:54 +0000212 const OptionDefinition*
Jim Ingham949d5ac2011-02-18 00:54:25 +0000213 GetDefinitions ()
214 {
215 return g_option_table;
216 }
217
218 // Options table: Required for subclasses of Options.
219
Greg Claytonb3448432011-03-24 21:19:54 +0000220 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +0000221
222 // Instance variables to hold the values for command options.
223
224 bool m_stop_on_error;
225 bool m_stop_on_continue;
226 };
227
Jim Ingham949d5ac2011-02-18 00:54:25 +0000228 CommandOptions m_options;
229
230 virtual Options *
231 GetOptions ()
232 {
233 return &m_options;
234 }
235
Jim Ingham767af882010-07-07 03:36:20 +0000236public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000237 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
238 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000239 "command source",
Greg Clayton238c0a12010-09-18 01:14:36 +0000240 "Read in debugger commands from the file <filename> and execute them.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000241 NULL),
242 m_options (interpreter)
Jim Ingham767af882010-07-07 03:36:20 +0000243 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000244 CommandArgumentEntry arg;
245 CommandArgumentData file_arg;
246
247 // Define the first (and only) variant of this arg.
248 file_arg.arg_type = eArgTypeFilename;
249 file_arg.arg_repetition = eArgRepeatPlain;
250
251 // There is only one variant this argument could be; put it into the argument entry.
252 arg.push_back (file_arg);
253
254 // Push the data for the first argument into the m_arguments vector.
255 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000256 }
257
258 ~CommandObjectCommandsSource ()
259 {
260 }
261
262 bool
263 Execute
264 (
Jim Ingham767af882010-07-07 03:36:20 +0000265 Args& args,
266 CommandReturnObject &result
267 )
268 {
269 const int argc = args.GetArgumentCount();
270 if (argc == 1)
271 {
272 const char *filename = args.GetArgumentAtIndex(0);
Jim Ingham767af882010-07-07 03:36:20 +0000273
274 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
275
Johnny Chena83ea882010-10-20 21:40:50 +0000276 FileSpec cmd_file (filename, true);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000277 ExecutionContext *exe_ctx = NULL; // Just use the default context.
278 bool echo_commands = true;
279 bool print_results = true;
Jim Ingham767af882010-07-07 03:36:20 +0000280
Jim Ingham949d5ac2011-02-18 00:54:25 +0000281 m_interpreter.HandleCommandsFromFile (cmd_file,
282 exe_ctx,
283 m_options.m_stop_on_continue,
284 m_options.m_stop_on_error,
285 echo_commands,
286 print_results,
287 result);
Jim Ingham767af882010-07-07 03:36:20 +0000288 }
289 else
290 {
291 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
292 result.SetStatus (eReturnStatusFailed);
293 }
294 return result.Succeeded();
295
296 }
297};
298
Greg Claytonb3448432011-03-24 21:19:54 +0000299OptionDefinition
Jim Ingham949d5ac2011-02-18 00:54:25 +0000300CommandObjectCommandsSource::CommandOptions::g_option_table[] =
301{
302{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
303{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
304{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
305};
306
Jim Ingham767af882010-07-07 03:36:20 +0000307#pragma mark CommandObjectCommandsAlias
308//-------------------------------------------------------------------------
309// CommandObjectCommandsAlias
310//-------------------------------------------------------------------------
311
Enrico Granatac2a28252011-08-16 16:49:25 +0000312static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
313 "You must define a Python function with this signature:\n"
314 "def my_command_impl(debugger, args, stream, dict):";
315
316
Jim Ingham767af882010-07-07 03:36:20 +0000317class CommandObjectCommandsAlias : public CommandObject
318{
Enrico Granatac2a28252011-08-16 16:49:25 +0000319
320 class PythonAliasReader : public InputReaderEZ
321 {
322 private:
323 CommandInterpreter& m_interpreter;
324 std::string m_cmd_name;
325 StringList m_user_input;
326 DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
327 public:
328 PythonAliasReader(Debugger& debugger,
329 CommandInterpreter& interpreter,
330 std::string cmd_name) :
331 InputReaderEZ(debugger),
332 m_interpreter(interpreter),
333 m_cmd_name(cmd_name),
334 m_user_input()
335 {}
336
337 virtual
338 ~PythonAliasReader()
339 {
340 }
341
342 virtual void ActivateHandler(HandlerData& data)
343 {
344 StreamSP out_stream = data.GetOutStream();
345 bool batch_mode = data.GetBatchMode();
346 if (!batch_mode)
347 {
348 out_stream->Printf ("%s\n", g_python_command_instructions);
349 if (data.reader.GetPrompt())
350 out_stream->Printf ("%s", data.reader.GetPrompt());
351 out_stream->Flush();
352 }
353 }
354
355 virtual void ReactivateHandler(HandlerData& data)
356 {
357 StreamSP out_stream = data.GetOutStream();
358 bool batch_mode = data.GetBatchMode();
359 if (data.reader.GetPrompt() && !batch_mode)
360 {
361 out_stream->Printf ("%s", data.reader.GetPrompt());
362 out_stream->Flush();
363 }
364 }
365 virtual void GotTokenHandler(HandlerData& data)
366 {
367 StreamSP out_stream = data.GetOutStream();
368 bool batch_mode = data.GetBatchMode();
369 if (data.bytes && data.bytes_len)
370 {
371 m_user_input.AppendString(data.bytes, data.bytes_len);
372 }
373 if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
374 {
375 out_stream->Printf ("%s", data.reader.GetPrompt());
376 out_stream->Flush();
377 }
378 }
379 virtual void InterruptHandler(HandlerData& data)
380 {
381 StreamSP out_stream = data.GetOutStream();
382 bool batch_mode = data.GetBatchMode();
383 data.reader.SetIsDone (true);
384 if (!batch_mode)
385 {
386 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
387 out_stream->Flush();
388 }
389 }
390 virtual void EOFHandler(HandlerData& data)
391 {
392 data.reader.SetIsDone (true);
393 }
394 virtual void DoneHandler(HandlerData& data)
395 {
396 StreamSP out_stream = data.GetOutStream();
397
398 ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
399 if (!interpreter)
400 {
401 out_stream->Printf ("Internal error #1: no script attached.\n");
402 out_stream->Flush();
403 return;
404 }
405 StringList funct_name_sl;
406 if (!interpreter->GenerateScriptAliasFunction (m_user_input,
407 funct_name_sl))
408 {
409 out_stream->Printf ("Internal error #2: no script attached.\n");
410 out_stream->Flush();
411 return;
412 }
413 if (funct_name_sl.GetSize() == 0)
414 {
415 out_stream->Printf ("Internal error #3: no script attached.\n");
416 out_stream->Flush();
417 return;
418 }
419 const char *funct_name = funct_name_sl.GetStringAtIndex(0);
420 if (!funct_name || !funct_name[0])
421 {
422 out_stream->Printf ("Internal error #4: no script attached.\n");
423 out_stream->Flush();
424 return;
425 }
426
427 // everything should be fine now, let's add this alias
428
429 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
430 m_cmd_name,
431 funct_name));
432
433 m_interpreter.AddAlias(m_cmd_name.c_str(), command_obj_sp);
434 }
435 };
436
Jim Ingham767af882010-07-07 03:36:20 +0000437public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000438 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
439 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000440 "command alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000441 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000442 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000443 {
444 SetHelpLong(
445 "'alias' allows the user to create a short-cut or abbreviation for long \n\
446 commands, multi-word commands, and commands that take particular options. \n\
447 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000448 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
449 // command. \n\
450 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
451 // command. Since breakpoint commands are two-word \n\
452 // commands, the user will still need to enter the \n\
453 // second word after 'bp', e.g. 'bp enable' or \n\
454 // 'bp delete'. \n\
455 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
456 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000457 \nAn alias can include some options for the command, with the values either \n\
458 filled in at the time the alias is created, or specified as positional \n\
459 arguments, to be filled in when the alias is invoked. The following example \n\
460 shows how to create aliases with options: \n\
461 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000462 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000463 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
464 options already part of the alias. So if the user wants to set a breakpoint \n\
465 by file and line without explicitly having to use the -f and -l options, the \n\
466 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
467 for the actual arguments that will be passed when the alias command is used. \n\
468 The number in the placeholder refers to the position/order the actual value \n\
469 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
470 will be replaced with the first argument, all the occurrences of '%2' in the \n\
471 alias will be replaced with the second argument, and so on. This also allows \n\
472 actual arguments to be used multiple times within an alias (see 'process \n\
473 launch' example below). So in the 'bfl' case, the actual file value will be \n\
474 filled in with the first argument following 'bfl' and the actual line number \n\
475 value will be filled in with the second argument. The user would use this \n\
476 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000477 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000478 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000479 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000480 \nThis would be the same as if the user had entered \n\
481 'breakpoint set -f my-file.c -l 137'. \n\
482 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000483 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
484 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000485 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000486 \nIf the user always wanted to pass the same value to a particular option, the \n\
487 alias could be defined with that value directly in the alias as a constant, \n\
488 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000489 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
490 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000491
Caroline Tice43b014a2010-10-04 22:28:36 +0000492 CommandArgumentEntry arg1;
493 CommandArgumentEntry arg2;
494 CommandArgumentEntry arg3;
495 CommandArgumentData alias_arg;
496 CommandArgumentData cmd_arg;
497 CommandArgumentData options_arg;
498
499 // Define the first (and only) variant of this arg.
500 alias_arg.arg_type = eArgTypeAliasName;
501 alias_arg.arg_repetition = eArgRepeatPlain;
502
503 // There is only one variant this argument could be; put it into the argument entry.
504 arg1.push_back (alias_arg);
505
506 // Define the first (and only) variant of this arg.
507 cmd_arg.arg_type = eArgTypeCommandName;
508 cmd_arg.arg_repetition = eArgRepeatPlain;
509
510 // There is only one variant this argument could be; put it into the argument entry.
511 arg2.push_back (cmd_arg);
512
513 // Define the first (and only) variant of this arg.
514 options_arg.arg_type = eArgTypeAliasOptions;
515 options_arg.arg_repetition = eArgRepeatOptional;
516
517 // There is only one variant this argument could be; put it into the argument entry.
518 arg3.push_back (options_arg);
519
520 // Push the data for the first argument into the m_arguments vector.
521 m_arguments.push_back (arg1);
522 m_arguments.push_back (arg2);
523 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000524 }
525
526 ~CommandObjectCommandsAlias ()
527 {
528 }
529
Caroline Ticee0da7a52010-12-09 22:52:49 +0000530 bool
531 WantsRawCommandString ()
532 {
533 return true;
534 }
535
536 bool
537 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
538 {
539 Args args (raw_command_line);
540 std::string raw_command_string (raw_command_line);
541
542 size_t argc = args.GetArgumentCount();
543
544 if (argc < 2)
545 {
546 result.AppendError ("'alias' requires at least two arguments");
547 result.SetStatus (eReturnStatusFailed);
548 return false;
549 }
550
551 // Get the alias command.
552
553 const std::string alias_command = args.GetArgumentAtIndex (0);
Enrico Granatac2a28252011-08-16 16:49:25 +0000554
555 if (
556 (strcmp("--python",alias_command.c_str()) == 0) ||
557 (strcmp("-P",alias_command.c_str()) == 0)
558 )
559 {
560
561 if (argc < 3)
562 {
563 // this is a definition of the form
564 // command alias --python foo_cmd
565 // and the user will type foo_cmd_impl by hand
566 std::string cmd_name = args.GetArgumentAtIndex(1);
567 // Verify that the command is alias-able.
568 if (m_interpreter.CommandExists (cmd_name.c_str()))
569 {
570 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
571 cmd_name.c_str());
572 result.SetStatus (eReturnStatusFailed);
573 return false;
574 }
575 if (m_interpreter.AliasExists (cmd_name.c_str())
576 || m_interpreter.UserCommandExists (cmd_name.c_str()))
577 {
578 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
579 cmd_name.c_str());
580 }
581
582
583 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
584 m_interpreter,
585 cmd_name));
586
587 if (reader_sp)
588 {
589
590 InputReaderEZ::InitializationParameters ipr;
591
592 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt(" ")));
593 if (err.Success())
594 {
595 m_interpreter.GetDebugger().PushInputReader (reader_sp);
596 result.SetStatus (eReturnStatusSuccessFinishNoResult);
597 }
598 else
599 {
600 result.AppendError (err.AsCString());
601 result.SetStatus (eReturnStatusFailed);
602 }
603 }
604 else
605 {
606 result.AppendError("out of memory");
607 result.SetStatus (eReturnStatusFailed);
608 }
609
610 result.SetStatus (eReturnStatusSuccessFinishNoResult);
611 return result.Succeeded();
612 }
613 else
614 {
615 // this is a definition of the form
616 // command alias --python foo_cmd funct_impl_foo
617 std::string cmd_name = args.GetArgumentAtIndex(1);
618 std::string funct_name = args.GetArgumentAtIndex(2);
619
620 // Verify that the command is alias-able.
621 if (m_interpreter.CommandExists (cmd_name.c_str()))
622 {
623 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
624 cmd_name.c_str());
625 result.SetStatus (eReturnStatusFailed);
626 return false;
627 }
628
629 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
630 cmd_name,
631 funct_name));
632
633 if (m_interpreter.AliasExists (cmd_name.c_str())
634 || m_interpreter.UserCommandExists (cmd_name.c_str()))
635 {
636 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
637 cmd_name.c_str());
638 }
639
640 m_interpreter.AddAlias(cmd_name.c_str(), command_obj_sp);
641
642 result.SetStatus (eReturnStatusSuccessFinishNoResult);
643 return result.Succeeded();
644 }
645 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000646
647 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
648 // does the stripping itself.
649 size_t pos = raw_command_string.find (alias_command);
650 if (pos == 0)
651 {
652 raw_command_string = raw_command_string.substr (alias_command.size());
653 pos = raw_command_string.find_first_not_of (' ');
654 if ((pos != std::string::npos) && (pos > 0))
655 raw_command_string = raw_command_string.substr (pos);
656 }
657 else
658 {
659 result.AppendError ("Error parsing command string. No alias created.");
660 result.SetStatus (eReturnStatusFailed);
661 return false;
662 }
663
664
665 // Verify that the command is alias-able.
666 if (m_interpreter.CommandExists (alias_command.c_str()))
667 {
668 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
669 alias_command.c_str());
670 result.SetStatus (eReturnStatusFailed);
671 return false;
672 }
673
674 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
675 // raw_command_string is returned with the name of the command object stripped off the front.
676 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
677
678 if (!cmd_obj)
679 {
680 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
681 " No alias created.", raw_command_string.c_str());
682 result.SetStatus (eReturnStatusFailed);
683 return false;
684 }
685 else if (!cmd_obj->WantsRawCommandString ())
686 {
687 // Note that args was initialized with the original command, and has not been updated to this point.
688 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
689 return Execute (args, result);
690 }
691 else
692 {
693 // Verify & handle any options/arguments passed to the alias command
694
695 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
696 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
697
Caroline Tice5ddbe212011-05-06 21:37:15 +0000698 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
699
700 if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
Caroline Ticee0da7a52010-12-09 22:52:49 +0000701 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000702 result.AppendError ("Unable to create requested alias.\n");
703 result.SetStatus (eReturnStatusFailed);
704 return false;
Caroline Ticee0da7a52010-12-09 22:52:49 +0000705 }
706
707 // Create the alias
708 if (m_interpreter.AliasExists (alias_command.c_str())
709 || m_interpreter.UserCommandExists (alias_command.c_str()))
710 {
711 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
712 if (temp_option_arg_sp.get())
713 {
714 if (option_arg_vector->size() == 0)
715 m_interpreter.RemoveAliasOptions (alias_command.c_str());
716 }
717 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
718 alias_command.c_str());
719 }
720
Caroline Tice56d2fc42010-12-14 18:51:39 +0000721 if (cmd_obj_sp)
722 {
723 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
724 if (option_arg_vector->size() > 0)
725 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
726 result.SetStatus (eReturnStatusSuccessFinishNoResult);
727 }
728 else
729 {
730 result.AppendError ("Unable to create requested alias.\n");
731 result.SetStatus (eReturnStatusFailed);
732 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000733 }
734 return result.Succeeded();
735 }
Jim Ingham767af882010-07-07 03:36:20 +0000736
737 bool
738 Execute
739 (
Jim Ingham767af882010-07-07 03:36:20 +0000740 Args& args,
741 CommandReturnObject &result
742 )
743 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000744 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000745
746 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000747 {
Jim Ingham767af882010-07-07 03:36:20 +0000748 result.AppendError ("'alias' requires at least two arguments");
749 result.SetStatus (eReturnStatusFailed);
750 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000751 }
Jim Ingham767af882010-07-07 03:36:20 +0000752
753 const std::string alias_command = args.GetArgumentAtIndex(0);
754 const std::string actual_command = args.GetArgumentAtIndex(1);
755
756 args.Shift(); // Shift the alias command word off the argument vector.
757 args.Shift(); // Shift the old command word off the argument vector.
758
759 // Verify that the command is alias'able, and get the appropriate command object.
760
Greg Clayton238c0a12010-09-18 01:14:36 +0000761 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000762 {
763 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
764 alias_command.c_str());
765 result.SetStatus (eReturnStatusFailed);
766 }
767 else
768 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000769 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000770 CommandObjectSP subcommand_obj_sp;
771 bool use_subcommand = false;
772 if (command_obj_sp.get())
773 {
774 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000775 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000776 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
777 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
778
Caroline Ticee0da7a52010-12-09 22:52:49 +0000779 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000780 {
781 if (argc >= 3)
782 {
783 const std::string sub_command = args.GetArgumentAtIndex(0);
784 assert (sub_command.length() != 0);
785 subcommand_obj_sp =
786 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
787 if (subcommand_obj_sp.get())
788 {
789 sub_cmd_obj = subcommand_obj_sp.get();
790 use_subcommand = true;
791 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000792 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000793 }
794 else
795 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000796 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
797 "Unable to create alias.\n",
798 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000799 result.SetStatus (eReturnStatusFailed);
800 return false;
801 }
802 }
803 }
804
805 // Verify & handle any options/arguments passed to the alias command
806
807 if (args.GetArgumentCount () > 0)
808 {
Caroline Tice5ddbe212011-05-06 21:37:15 +0000809 CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
810 if (use_subcommand)
811 tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
812
813 std::string args_string;
814 args.GetCommandString (args_string);
815
816 if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
817 {
818 result.AppendError ("Unable to create requested alias.\n");
819 result.SetStatus (eReturnStatusFailed);
820 return false;
821 }
Jim Ingham767af882010-07-07 03:36:20 +0000822 }
823
824 // Create the alias.
825
Greg Clayton238c0a12010-09-18 01:14:36 +0000826 if (m_interpreter.AliasExists (alias_command.c_str())
827 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000828 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000829 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000830 if (tmp_option_arg_sp.get())
831 {
832 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000833 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000834 }
835 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
836 alias_command.c_str());
837 }
838
839 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000840 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000841 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000842 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000843 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000844 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000845 result.SetStatus (eReturnStatusSuccessFinishNoResult);
846 }
847 else
848 {
849 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
850 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000851 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000852 }
853 }
854
855 return result.Succeeded();
856 }
857};
858
859#pragma mark CommandObjectCommandsUnalias
860//-------------------------------------------------------------------------
861// CommandObjectCommandsUnalias
862//-------------------------------------------------------------------------
863
864class CommandObjectCommandsUnalias : public CommandObject
865{
866public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000867 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
868 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000869 "command unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000870 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000871 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000872 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000873 CommandArgumentEntry arg;
874 CommandArgumentData alias_arg;
875
876 // Define the first (and only) variant of this arg.
877 alias_arg.arg_type = eArgTypeAliasName;
878 alias_arg.arg_repetition = eArgRepeatPlain;
879
880 // There is only one variant this argument could be; put it into the argument entry.
881 arg.push_back (alias_arg);
882
883 // Push the data for the first argument into the m_arguments vector.
884 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000885 }
886
887 ~CommandObjectCommandsUnalias()
888 {
889 }
890
891
892 bool
893 Execute
894 (
Jim Ingham767af882010-07-07 03:36:20 +0000895 Args& args,
896 CommandReturnObject &result
897 )
898 {
899 CommandObject::CommandMap::iterator pos;
900 CommandObject *cmd_obj;
901
902 if (args.GetArgumentCount() != 0)
903 {
904 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000905 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000906 if (cmd_obj)
907 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000908 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000909 {
910 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
911 command_name);
912 result.SetStatus (eReturnStatusFailed);
913 }
914 else
915 {
916
Greg Clayton238c0a12010-09-18 01:14:36 +0000917 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000918 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000919 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000920 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
921 command_name);
922 else
923 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
924 result.SetStatus (eReturnStatusFailed);
925 }
926 else
927 result.SetStatus (eReturnStatusSuccessFinishNoResult);
928 }
929 }
930 else
931 {
932 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
933 "current list of commands.\n",
934 command_name);
935 result.SetStatus (eReturnStatusFailed);
936 }
937 }
938 else
939 {
940 result.AppendError ("must call 'unalias' with a valid alias");
941 result.SetStatus (eReturnStatusFailed);
942 }
943
944 return result.Succeeded();
945 }
946};
947
Greg Claytond12aeab2011-04-20 16:37:46 +0000948#pragma mark CommandObjectCommandsAddRegex
949//-------------------------------------------------------------------------
950// CommandObjectCommandsAddRegex
951//-------------------------------------------------------------------------
952
953class CommandObjectCommandsAddRegex : public CommandObject
954{
955public:
956 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
957 CommandObject (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +0000958 "command regex",
Greg Claytond12aeab2011-04-20 16:37:46 +0000959 "Allow the user to create a regular expression command.",
Greg Clayton40e48242011-04-20 22:55:21 +0000960 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
Greg Claytond12aeab2011-04-20 16:37:46 +0000961 m_options (interpreter)
962 {
Greg Clayton40e48242011-04-20 22:55:21 +0000963 SetHelpLong(
964"This command allows the user to create powerful regular expression commands\n"
965"with substitutions. The regular expressions and substitutions are specified\n"
966"using the regular exression substitution format of:\n"
967"\n"
968" s/<regex>/<subst>/\n"
969"\n"
970"<regex> is a regular expression that can use parenthesis to capture regular\n"
971"expression input and substitute the captured matches in the output using %1\n"
972"for the first match, %2 for the second, and so on.\n"
973"\n"
974"The regular expressions can all be specified on the command line if more than\n"
975"one argument is provided. If just the command name is provided on the command\n"
976"line, then the regular expressions and substitutions can be entered on separate\n"
977" lines, followed by an empty line to terminate the command definition.\n"
978"\n"
979"EXAMPLES\n"
980"\n"
981"The following example with define a regular expression command named 'f' that\n"
982"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
983"a number follows 'f':\n"
984"(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
985 );
Greg Claytond12aeab2011-04-20 16:37:46 +0000986 }
987
988 ~CommandObjectCommandsAddRegex()
989 {
990 }
991
992
993 bool
994 Execute (Args& args, CommandReturnObject &result)
995 {
Greg Clayton40e48242011-04-20 22:55:21 +0000996 const size_t argc = args.GetArgumentCount();
997 if (argc == 0)
Greg Claytond12aeab2011-04-20 16:37:46 +0000998 {
Greg Clayton40e48242011-04-20 22:55:21 +0000999 result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1000 result.SetStatus (eReturnStatusFailed);
1001 }
1002 else
1003 {
1004 Error error;
Greg Claytond12aeab2011-04-20 16:37:46 +00001005 const char *name = args.GetArgumentAtIndex(0);
Greg Claytond12aeab2011-04-20 16:37:46 +00001006 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
1007 name,
1008 m_options.GetHelp (),
1009 m_options.GetSyntax (),
1010 10));
Greg Clayton40e48242011-04-20 22:55:21 +00001011
1012 if (argc == 1)
Greg Claytond12aeab2011-04-20 16:37:46 +00001013 {
Greg Clayton40e48242011-04-20 22:55:21 +00001014 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
1015 if (reader_sp)
1016 {
1017 error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
Greg Claytond12aeab2011-04-20 16:37:46 +00001018 this, // baton
1019 eInputReaderGranularityLine, // token size, to pass to callback function
Greg Clayton40e48242011-04-20 22:55:21 +00001020 NULL, // end token
Greg Claytond12aeab2011-04-20 16:37:46 +00001021 "> ", // prompt
Greg Clayton40e48242011-04-20 22:55:21 +00001022 true); // echo input
1023 if (error.Success())
1024 {
1025 m_interpreter.GetDebugger().PushInputReader (reader_sp);
1026 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1027 return true;
1028 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001029 }
1030 }
Greg Clayton40e48242011-04-20 22:55:21 +00001031 else
1032 {
1033 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
1034 {
1035 llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
1036 error = AppendRegexSubstitution (arg_strref);
1037 if (error.Fail())
1038 break;
1039 }
1040
1041 if (error.Success())
1042 {
1043 AddRegexCommandToInterpreter();
1044 }
1045 }
1046 if (error.Fail())
1047 {
1048 result.AppendError (error.AsCString());
1049 result.SetStatus (eReturnStatusFailed);
1050 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001051 }
Greg Clayton40e48242011-04-20 22:55:21 +00001052
Greg Claytond12aeab2011-04-20 16:37:46 +00001053 return result.Succeeded();
1054 }
1055
Greg Clayton40e48242011-04-20 22:55:21 +00001056 Error
1057 AppendRegexSubstitution (const llvm::StringRef &regex_sed)
Greg Claytond12aeab2011-04-20 16:37:46 +00001058 {
Greg Clayton40e48242011-04-20 22:55:21 +00001059 Error error;
1060
1061 if (m_regex_cmd_ap.get() == NULL)
Greg Claytond12aeab2011-04-20 16:37:46 +00001062 {
Greg Clayton40e48242011-04-20 22:55:21 +00001063 error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
1064 (int)regex_sed.size(),
1065 regex_sed.data());
1066 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +00001067 }
Greg Clayton40e48242011-04-20 22:55:21 +00001068
1069 size_t regex_sed_size = regex_sed.size();
1070
1071 if (regex_sed_size <= 1)
1072 {
1073 error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
1074 (int)regex_sed.size(),
1075 regex_sed.data());
1076 return error;
1077 }
1078
1079 if (regex_sed[0] != 's')
1080 {
1081 error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
1082 (int)regex_sed.size(),
1083 regex_sed.data());
1084 return error;
1085 }
1086 const size_t first_separator_char_pos = 1;
1087 // use the char that follows 's' as the regex separator character
1088 // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1089 const char separator_char = regex_sed[first_separator_char_pos];
1090 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
1091
1092 if (second_separator_char_pos == std::string::npos)
1093 {
1094 error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
1095 separator_char,
1096 (int)(regex_sed.size() - first_separator_char_pos - 1),
1097 regex_sed.data() + (first_separator_char_pos + 1));
1098 return error;
1099 }
1100
1101 const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
1102
1103 if (third_separator_char_pos == std::string::npos)
1104 {
1105 error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
1106 separator_char,
1107 (int)(regex_sed.size() - second_separator_char_pos - 1),
1108 regex_sed.data() + (second_separator_char_pos + 1));
1109 return error;
1110 }
1111
1112 if (third_separator_char_pos != regex_sed_size - 1)
1113 {
1114 // Make sure that everything that follows the last regex
1115 // separator char
1116 if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
1117 {
1118 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
1119 (int)third_separator_char_pos + 1,
1120 regex_sed.data(),
1121 (int)(regex_sed.size() - third_separator_char_pos - 1),
1122 regex_sed.data() + (third_separator_char_pos + 1));
1123 return error;
1124 }
1125
1126 }
1127 else if (first_separator_char_pos + 1 == second_separator_char_pos)
1128 {
1129 error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1130 separator_char,
1131 separator_char,
1132 separator_char,
1133 (int)regex_sed.size(),
1134 regex_sed.data());
1135 return error;
1136 }
1137 else if (second_separator_char_pos + 1 == third_separator_char_pos)
1138 {
1139 error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1140 separator_char,
1141 separator_char,
1142 separator_char,
1143 (int)regex_sed.size(),
1144 regex_sed.data());
1145 return error;
1146 }
1147 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
1148 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
1149 m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
1150 subst.c_str());
1151 return error;
Greg Claytond12aeab2011-04-20 16:37:46 +00001152 }
1153
1154 void
Greg Clayton40e48242011-04-20 22:55:21 +00001155 AddRegexCommandToInterpreter()
Greg Claytond12aeab2011-04-20 16:37:46 +00001156 {
1157 if (m_regex_cmd_ap.get())
1158 {
1159 if (m_regex_cmd_ap->HasRegexEntries())
1160 {
1161 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1162 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1163 }
1164 }
1165 }
1166
Greg Clayton40e48242011-04-20 22:55:21 +00001167 void
1168 InputReaderDidCancel()
1169 {
1170 m_regex_cmd_ap.reset();
1171 }
1172
Greg Claytond12aeab2011-04-20 16:37:46 +00001173 static size_t
1174 InputReaderCallback (void *baton,
1175 InputReader &reader,
1176 lldb::InputReaderAction notification,
1177 const char *bytes,
1178 size_t bytes_len);
1179private:
1180 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1181
1182 class CommandOptions : public Options
1183 {
1184 public:
1185
1186 CommandOptions (CommandInterpreter &interpreter) :
1187 Options (interpreter)
1188 {
1189 }
1190
1191 virtual
1192 ~CommandOptions (){}
1193
1194 virtual Error
1195 SetOptionValue (uint32_t option_idx, const char *option_arg)
1196 {
1197 Error error;
1198 char short_option = (char) m_getopt_table[option_idx].val;
1199
1200 switch (short_option)
1201 {
1202 case 'h':
1203 m_help.assign (option_arg);
1204 break;
1205 case 's':
1206 m_syntax.assign (option_arg);
1207 break;
1208
1209 default:
1210 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1211 break;
1212 }
1213
1214 return error;
1215 }
1216
1217 void
1218 OptionParsingStarting ()
1219 {
1220 m_help.clear();
1221 m_syntax.clear();
1222 }
1223
1224 const OptionDefinition*
1225 GetDefinitions ()
1226 {
1227 return g_option_table;
1228 }
1229
1230 // Options table: Required for subclasses of Options.
1231
1232 static OptionDefinition g_option_table[];
1233
1234 const char *
1235 GetHelp ()
1236 {
1237 if (m_help.empty())
1238 return NULL;
1239 return m_help.c_str();
1240 }
1241 const char *
1242 GetSyntax ()
1243 {
1244 if (m_syntax.empty())
1245 return NULL;
1246 return m_syntax.c_str();
1247 }
1248 // Instance variables to hold the values for command options.
1249 protected:
1250 std::string m_help;
1251 std::string m_syntax;
1252 };
1253
1254 CommandOptions m_options;
1255
1256 virtual Options *
1257 GetOptions ()
1258 {
1259 return &m_options;
1260 }
1261
1262};
1263
1264size_t
1265CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1266 InputReader &reader,
1267 lldb::InputReaderAction notification,
1268 const char *bytes,
1269 size_t bytes_len)
1270{
1271 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
Caroline Tice892fadd2011-06-16 16:27:19 +00001272 bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
Greg Claytond12aeab2011-04-20 16:37:46 +00001273
1274 switch (notification)
1275 {
1276 case eInputReaderActivate:
Caroline Tice892fadd2011-06-16 16:27:19 +00001277 if (!batch_mode)
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001278 {
1279 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1280 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1281 out_stream->Flush();
1282 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001283 break;
1284 case eInputReaderReactivate:
1285 break;
1286
1287 case eInputReaderDeactivate:
1288 break;
Caroline Tice4a348082011-05-02 20:41:46 +00001289
1290 case eInputReaderAsynchronousOutputWritten:
1291 break;
1292
Greg Claytond12aeab2011-04-20 16:37:46 +00001293 case eInputReaderGotToken:
Greg Clayton40e48242011-04-20 22:55:21 +00001294 while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1295 --bytes_len;
Greg Claytond12aeab2011-04-20 16:37:46 +00001296 if (bytes_len == 0)
1297 reader.SetIsDone(true);
1298 else if (bytes)
1299 {
Greg Clayton40e48242011-04-20 22:55:21 +00001300 llvm::StringRef bytes_strref (bytes, bytes_len);
1301 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1302 if (error.Fail())
Greg Claytond12aeab2011-04-20 16:37:46 +00001303 {
Caroline Tice892fadd2011-06-16 16:27:19 +00001304 if (!batch_mode)
1305 {
1306 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1307 out_stream->Printf("error: %s\n", error.AsCString());
1308 out_stream->Flush();
1309 }
Greg Clayton40e48242011-04-20 22:55:21 +00001310 add_regex_cmd->InputReaderDidCancel ();
1311 reader.SetIsDone (true);
Greg Claytond12aeab2011-04-20 16:37:46 +00001312 }
1313 }
1314 break;
1315
1316 case eInputReaderInterrupt:
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001317 {
1318 reader.SetIsDone (true);
Caroline Tice892fadd2011-06-16 16:27:19 +00001319 if (!batch_mode)
1320 {
1321 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1322 out_stream->PutCString("Regular expression command creations was cancelled.\n");
1323 out_stream->Flush();
1324 }
Caroline Tice2b5e4e62011-06-15 19:35:17 +00001325 add_regex_cmd->InputReaderDidCancel ();
1326 }
Greg Claytond12aeab2011-04-20 16:37:46 +00001327 break;
1328
1329 case eInputReaderEndOfFile:
1330 reader.SetIsDone (true);
1331 break;
1332
1333 case eInputReaderDone:
Greg Clayton40e48242011-04-20 22:55:21 +00001334 add_regex_cmd->AddRegexCommandToInterpreter();
Greg Claytond12aeab2011-04-20 16:37:46 +00001335 break;
1336 }
1337
1338 return bytes_len;
1339}
1340
1341
1342OptionDefinition
1343CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1344{
Greg Clayton40e48242011-04-20 22:55:21 +00001345{ 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 +00001346{ 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 +00001347{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Greg Claytond12aeab2011-04-20 16:37:46 +00001348};
1349
1350
Jim Ingham767af882010-07-07 03:36:20 +00001351#pragma mark CommandObjectMultiwordCommands
1352
1353//-------------------------------------------------------------------------
1354// CommandObjectMultiwordCommands
1355//-------------------------------------------------------------------------
1356
1357CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001358 CommandObjectMultiword (interpreter,
Greg Clayton40e48242011-04-20 22:55:21 +00001359 "command",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001360 "A set of commands for managing or customizing the debugger commands.",
Greg Clayton40e48242011-04-20 22:55:21 +00001361 "command <subcommand> [<subcommand-options>]")
Jim Ingham767af882010-07-07 03:36:20 +00001362{
Greg Clayton238c0a12010-09-18 01:14:36 +00001363 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1364 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1365 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +00001366 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham6247dbe2011-07-12 03:12:18 +00001367 LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +00001368}
1369
1370CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1371{
1372}
1373