blob: bc04b6bd6e7d1f77af15a9b554ca4e60ce3e4ab7 [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
15// Project includes
Jim Ingham767af882010-07-07 03:36:20 +000016#include "lldb/Core/Debugger.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000017#include "lldb/Core/InputReader.h"
18#include "lldb/Interpreter/Args.h"
Jim Ingham767af882010-07-07 03:36:20 +000019#include "lldb/Interpreter/CommandInterpreter.h"
Greg Claytond12aeab2011-04-20 16:37:46 +000020#include "lldb/Interpreter/CommandObjectRegexCommand.h"
Jim Ingham767af882010-07-07 03:36:20 +000021#include "lldb/Interpreter/CommandReturnObject.h"
22#include "lldb/Interpreter/Options.h"
23
24using namespace lldb;
25using namespace lldb_private;
26
Jim Ingham767af882010-07-07 03:36:20 +000027//-------------------------------------------------------------------------
28// CommandObjectCommandsSource
29//-------------------------------------------------------------------------
30
31class CommandObjectCommandsSource : public CommandObject
32{
Jim Ingham949d5ac2011-02-18 00:54:25 +000033private:
34
35 class CommandOptions : public Options
36 {
37 public:
38
Greg Claytonf15996e2011-04-07 22:46:35 +000039 CommandOptions (CommandInterpreter &interpreter) :
40 Options (interpreter)
41 {
42 }
Jim Ingham949d5ac2011-02-18 00:54:25 +000043
44 virtual
45 ~CommandOptions (){}
46
47 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +000048 SetOptionValue (uint32_t option_idx, const char *option_arg)
Jim Ingham949d5ac2011-02-18 00:54:25 +000049 {
50 Error error;
51 char short_option = (char) m_getopt_table[option_idx].val;
52 bool success;
53
54 switch (short_option)
55 {
56 case 'e':
57 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
58 if (!success)
59 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
60 break;
61 case 'c':
62 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
63 if (!success)
64 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
65 break;
66 default:
67 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
68 break;
69 }
70
71 return error;
72 }
73
74 void
Greg Clayton143fcc32011-04-13 00:18:08 +000075 OptionParsingStarting ()
Jim Ingham949d5ac2011-02-18 00:54:25 +000076 {
Jim Ingham949d5ac2011-02-18 00:54:25 +000077 m_stop_on_error = true;
78 m_stop_on_continue = true;
79 }
80
Greg Claytonb3448432011-03-24 21:19:54 +000081 const OptionDefinition*
Jim Ingham949d5ac2011-02-18 00:54:25 +000082 GetDefinitions ()
83 {
84 return g_option_table;
85 }
86
87 // Options table: Required for subclasses of Options.
88
Greg Claytonb3448432011-03-24 21:19:54 +000089 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +000090
91 // Instance variables to hold the values for command options.
92
93 bool m_stop_on_error;
94 bool m_stop_on_continue;
95 };
96
Jim Ingham949d5ac2011-02-18 00:54:25 +000097 CommandOptions m_options;
98
99 virtual Options *
100 GetOptions ()
101 {
102 return &m_options;
103 }
104
Jim Ingham767af882010-07-07 03:36:20 +0000105public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000106 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
107 CommandObject (interpreter,
108 "commands source",
109 "Read in debugger commands from the file <filename> and execute them.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000110 NULL),
111 m_options (interpreter)
Jim Ingham767af882010-07-07 03:36:20 +0000112 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000113 CommandArgumentEntry arg;
114 CommandArgumentData file_arg;
115
116 // Define the first (and only) variant of this arg.
117 file_arg.arg_type = eArgTypeFilename;
118 file_arg.arg_repetition = eArgRepeatPlain;
119
120 // There is only one variant this argument could be; put it into the argument entry.
121 arg.push_back (file_arg);
122
123 // Push the data for the first argument into the m_arguments vector.
124 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000125 }
126
127 ~CommandObjectCommandsSource ()
128 {
129 }
130
131 bool
132 Execute
133 (
Jim Ingham767af882010-07-07 03:36:20 +0000134 Args& args,
135 CommandReturnObject &result
136 )
137 {
138 const int argc = args.GetArgumentCount();
139 if (argc == 1)
140 {
141 const char *filename = args.GetArgumentAtIndex(0);
Jim Ingham767af882010-07-07 03:36:20 +0000142
143 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
144
Johnny Chena83ea882010-10-20 21:40:50 +0000145 FileSpec cmd_file (filename, true);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000146 ExecutionContext *exe_ctx = NULL; // Just use the default context.
147 bool echo_commands = true;
148 bool print_results = true;
Jim Ingham767af882010-07-07 03:36:20 +0000149
Jim Ingham949d5ac2011-02-18 00:54:25 +0000150 m_interpreter.HandleCommandsFromFile (cmd_file,
151 exe_ctx,
152 m_options.m_stop_on_continue,
153 m_options.m_stop_on_error,
154 echo_commands,
155 print_results,
156 result);
Jim Ingham767af882010-07-07 03:36:20 +0000157 }
158 else
159 {
160 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
161 result.SetStatus (eReturnStatusFailed);
162 }
163 return result.Succeeded();
164
165 }
166};
167
Greg Claytonb3448432011-03-24 21:19:54 +0000168OptionDefinition
Jim Ingham949d5ac2011-02-18 00:54:25 +0000169CommandObjectCommandsSource::CommandOptions::g_option_table[] =
170{
171{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
172{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
173{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
174};
175
Jim Ingham767af882010-07-07 03:36:20 +0000176#pragma mark CommandObjectCommandsAlias
177//-------------------------------------------------------------------------
178// CommandObjectCommandsAlias
179//-------------------------------------------------------------------------
180
181class CommandObjectCommandsAlias : public CommandObject
182{
183public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000184 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
185 CommandObject (interpreter,
186 "commands alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000187 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000188 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000189 {
190 SetHelpLong(
191 "'alias' allows the user to create a short-cut or abbreviation for long \n\
192 commands, multi-word commands, and commands that take particular options. \n\
193 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000194 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
195 // command. \n\
196 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
197 // command. Since breakpoint commands are two-word \n\
198 // commands, the user will still need to enter the \n\
199 // second word after 'bp', e.g. 'bp enable' or \n\
200 // 'bp delete'. \n\
201 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
202 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000203 \nAn alias can include some options for the command, with the values either \n\
204 filled in at the time the alias is created, or specified as positional \n\
205 arguments, to be filled in when the alias is invoked. The following example \n\
206 shows how to create aliases with options: \n\
207 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000208 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000209 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
210 options already part of the alias. So if the user wants to set a breakpoint \n\
211 by file and line without explicitly having to use the -f and -l options, the \n\
212 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
213 for the actual arguments that will be passed when the alias command is used. \n\
214 The number in the placeholder refers to the position/order the actual value \n\
215 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
216 will be replaced with the first argument, all the occurrences of '%2' in the \n\
217 alias will be replaced with the second argument, and so on. This also allows \n\
218 actual arguments to be used multiple times within an alias (see 'process \n\
219 launch' example below). So in the 'bfl' case, the actual file value will be \n\
220 filled in with the first argument following 'bfl' and the actual line number \n\
221 value will be filled in with the second argument. The user would use this \n\
222 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000223 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000224 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000225 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000226 \nThis would be the same as if the user had entered \n\
227 'breakpoint set -f my-file.c -l 137'. \n\
228 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000229 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
230 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000231 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000232 \nIf the user always wanted to pass the same value to a particular option, the \n\
233 alias could be defined with that value directly in the alias as a constant, \n\
234 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000235 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
236 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000237
Caroline Tice43b014a2010-10-04 22:28:36 +0000238 CommandArgumentEntry arg1;
239 CommandArgumentEntry arg2;
240 CommandArgumentEntry arg3;
241 CommandArgumentData alias_arg;
242 CommandArgumentData cmd_arg;
243 CommandArgumentData options_arg;
244
245 // Define the first (and only) variant of this arg.
246 alias_arg.arg_type = eArgTypeAliasName;
247 alias_arg.arg_repetition = eArgRepeatPlain;
248
249 // There is only one variant this argument could be; put it into the argument entry.
250 arg1.push_back (alias_arg);
251
252 // Define the first (and only) variant of this arg.
253 cmd_arg.arg_type = eArgTypeCommandName;
254 cmd_arg.arg_repetition = eArgRepeatPlain;
255
256 // There is only one variant this argument could be; put it into the argument entry.
257 arg2.push_back (cmd_arg);
258
259 // Define the first (and only) variant of this arg.
260 options_arg.arg_type = eArgTypeAliasOptions;
261 options_arg.arg_repetition = eArgRepeatOptional;
262
263 // There is only one variant this argument could be; put it into the argument entry.
264 arg3.push_back (options_arg);
265
266 // Push the data for the first argument into the m_arguments vector.
267 m_arguments.push_back (arg1);
268 m_arguments.push_back (arg2);
269 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000270 }
271
272 ~CommandObjectCommandsAlias ()
273 {
274 }
275
Caroline Ticee0da7a52010-12-09 22:52:49 +0000276 bool
277 WantsRawCommandString ()
278 {
279 return true;
280 }
281
282 bool
283 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
284 {
285 Args args (raw_command_line);
286 std::string raw_command_string (raw_command_line);
287
288 size_t argc = args.GetArgumentCount();
289
290 if (argc < 2)
291 {
292 result.AppendError ("'alias' requires at least two arguments");
293 result.SetStatus (eReturnStatusFailed);
294 return false;
295 }
296
297 // Get the alias command.
298
299 const std::string alias_command = args.GetArgumentAtIndex (0);
300
301 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
302 // does the stripping itself.
303 size_t pos = raw_command_string.find (alias_command);
304 if (pos == 0)
305 {
306 raw_command_string = raw_command_string.substr (alias_command.size());
307 pos = raw_command_string.find_first_not_of (' ');
308 if ((pos != std::string::npos) && (pos > 0))
309 raw_command_string = raw_command_string.substr (pos);
310 }
311 else
312 {
313 result.AppendError ("Error parsing command string. No alias created.");
314 result.SetStatus (eReturnStatusFailed);
315 return false;
316 }
317
318
319 // Verify that the command is alias-able.
320 if (m_interpreter.CommandExists (alias_command.c_str()))
321 {
322 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
323 alias_command.c_str());
324 result.SetStatus (eReturnStatusFailed);
325 return false;
326 }
327
328 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
329 // raw_command_string is returned with the name of the command object stripped off the front.
330 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
331
332 if (!cmd_obj)
333 {
334 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
335 " No alias created.", raw_command_string.c_str());
336 result.SetStatus (eReturnStatusFailed);
337 return false;
338 }
339 else if (!cmd_obj->WantsRawCommandString ())
340 {
341 // Note that args was initialized with the original command, and has not been updated to this point.
342 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
343 return Execute (args, result);
344 }
345 else
346 {
347 // Verify & handle any options/arguments passed to the alias command
348
349 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
350 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
351
352 // Check to see if there's anything left in the input command string.
353 if (raw_command_string.size() > 0)
354 {
355
356 // Check to see if the command being aliased can take any command options.
357 Options *options = cmd_obj->GetOptions();
358 if (options)
359 {
360 // See if any options were specified as part of the alias; if so, handle them appropriately
Greg Clayton143fcc32011-04-13 00:18:08 +0000361 options->NotifyOptionParsingStarting ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000362 Args tmp_args (raw_command_string.c_str());
363 args.Unshift ("dummy_arg");
364 args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
365 args.Shift ();
366 if (result.Succeeded())
367 options->VerifyPartialOptions (result);
368 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
369 {
370 result.AppendError ("Unable to create requested alias.\n");
371 return false;
372 }
373 }
374 // Anything remaining must be plain raw input. Push it in as a single raw input argument.
375 if (raw_command_string.size() > 0)
376 option_arg_vector->push_back (OptionArgPair ("<argument>",
377 OptionArgValue (-1,
378 raw_command_string)));
379 }
380
381 // Create the alias
382 if (m_interpreter.AliasExists (alias_command.c_str())
383 || m_interpreter.UserCommandExists (alias_command.c_str()))
384 {
385 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
386 if (temp_option_arg_sp.get())
387 {
388 if (option_arg_vector->size() == 0)
389 m_interpreter.RemoveAliasOptions (alias_command.c_str());
390 }
391 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
392 alias_command.c_str());
393 }
394
395 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
Caroline Tice56d2fc42010-12-14 18:51:39 +0000396 if (cmd_obj_sp)
397 {
398 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
399 if (option_arg_vector->size() > 0)
400 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
401 result.SetStatus (eReturnStatusSuccessFinishNoResult);
402 }
403 else
404 {
405 result.AppendError ("Unable to create requested alias.\n");
406 result.SetStatus (eReturnStatusFailed);
407 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000408 }
409 return result.Succeeded();
410 }
Jim Ingham767af882010-07-07 03:36:20 +0000411
412 bool
413 Execute
414 (
Jim Ingham767af882010-07-07 03:36:20 +0000415 Args& args,
416 CommandReturnObject &result
417 )
418 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000419 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000420
421 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000422 {
Jim Ingham767af882010-07-07 03:36:20 +0000423 result.AppendError ("'alias' requires at least two arguments");
424 result.SetStatus (eReturnStatusFailed);
425 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000426 }
Jim Ingham767af882010-07-07 03:36:20 +0000427
428 const std::string alias_command = args.GetArgumentAtIndex(0);
429 const std::string actual_command = args.GetArgumentAtIndex(1);
430
431 args.Shift(); // Shift the alias command word off the argument vector.
432 args.Shift(); // Shift the old command word off the argument vector.
433
434 // Verify that the command is alias'able, and get the appropriate command object.
435
Greg Clayton238c0a12010-09-18 01:14:36 +0000436 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000437 {
438 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
439 alias_command.c_str());
440 result.SetStatus (eReturnStatusFailed);
441 }
442 else
443 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000444 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000445 CommandObjectSP subcommand_obj_sp;
446 bool use_subcommand = false;
447 if (command_obj_sp.get())
448 {
449 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000450 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000451 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
452 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
453
Caroline Ticee0da7a52010-12-09 22:52:49 +0000454 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000455 {
456 if (argc >= 3)
457 {
458 const std::string sub_command = args.GetArgumentAtIndex(0);
459 assert (sub_command.length() != 0);
460 subcommand_obj_sp =
461 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
462 if (subcommand_obj_sp.get())
463 {
464 sub_cmd_obj = subcommand_obj_sp.get();
465 use_subcommand = true;
466 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000467 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000468 }
469 else
470 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000471 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
472 "Unable to create alias.\n",
473 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000474 result.SetStatus (eReturnStatusFailed);
475 return false;
476 }
477 }
478 }
479
480 // Verify & handle any options/arguments passed to the alias command
481
482 if (args.GetArgumentCount () > 0)
483 {
Jim Ingham767af882010-07-07 03:36:20 +0000484 if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
485 || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
486 {
487 Options *options;
488 if (use_subcommand)
489 options = sub_cmd_obj->GetOptions();
490 else
491 options = cmd_obj->GetOptions();
Greg Clayton143fcc32011-04-13 00:18:08 +0000492 options->NotifyOptionParsingStarting ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000493 std::string empty_string;
Jim Ingham767af882010-07-07 03:36:20 +0000494 args.Unshift ("dummy_arg");
Caroline Ticee0da7a52010-12-09 22:52:49 +0000495 args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
Jim Ingham767af882010-07-07 03:36:20 +0000496 args.Shift ();
497 if (result.Succeeded())
498 options->VerifyPartialOptions (result);
Caroline Tice8bb61f02010-09-21 23:25:40 +0000499 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
500 {
501 result.AppendError ("Unable to create requested command alias.\n");
Caroline Ticee6866a32010-10-28 23:17:48 +0000502 return false;
Caroline Tice8bb61f02010-09-21 23:25:40 +0000503 }
Jim Ingham767af882010-07-07 03:36:20 +0000504 }
Caroline Tice8bb61f02010-09-21 23:25:40 +0000505
506 // Anything remaining in args must be a plain argument.
507
508 argc = args.GetArgumentCount();
509 for (size_t i = 0; i < argc; ++i)
Caroline Tice44c841d2010-12-07 19:58:26 +0000510 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
511 option_arg_vector->push_back
512 (OptionArgPair ("<argument>",
513 OptionArgValue (-1,
514 std::string (args.GetArgumentAtIndex (i)))));
Jim Ingham767af882010-07-07 03:36:20 +0000515 }
516
517 // Create the alias.
518
Greg Clayton238c0a12010-09-18 01:14:36 +0000519 if (m_interpreter.AliasExists (alias_command.c_str())
520 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000521 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000522 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000523 if (tmp_option_arg_sp.get())
524 {
525 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000526 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000527 }
528 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
529 alias_command.c_str());
530 }
531
532 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000533 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000534 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000535 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000536 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000537 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000538 result.SetStatus (eReturnStatusSuccessFinishNoResult);
539 }
540 else
541 {
542 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
543 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000544 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000545 }
546 }
547
548 return result.Succeeded();
549 }
550};
551
552#pragma mark CommandObjectCommandsUnalias
553//-------------------------------------------------------------------------
554// CommandObjectCommandsUnalias
555//-------------------------------------------------------------------------
556
557class CommandObjectCommandsUnalias : public CommandObject
558{
559public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000560 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
561 CommandObject (interpreter,
562 "commands unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000563 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000564 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000565 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000566 CommandArgumentEntry arg;
567 CommandArgumentData alias_arg;
568
569 // Define the first (and only) variant of this arg.
570 alias_arg.arg_type = eArgTypeAliasName;
571 alias_arg.arg_repetition = eArgRepeatPlain;
572
573 // There is only one variant this argument could be; put it into the argument entry.
574 arg.push_back (alias_arg);
575
576 // Push the data for the first argument into the m_arguments vector.
577 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000578 }
579
580 ~CommandObjectCommandsUnalias()
581 {
582 }
583
584
585 bool
586 Execute
587 (
Jim Ingham767af882010-07-07 03:36:20 +0000588 Args& args,
589 CommandReturnObject &result
590 )
591 {
592 CommandObject::CommandMap::iterator pos;
593 CommandObject *cmd_obj;
594
595 if (args.GetArgumentCount() != 0)
596 {
597 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000598 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000599 if (cmd_obj)
600 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000601 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000602 {
603 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
604 command_name);
605 result.SetStatus (eReturnStatusFailed);
606 }
607 else
608 {
609
Greg Clayton238c0a12010-09-18 01:14:36 +0000610 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000611 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000612 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000613 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
614 command_name);
615 else
616 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
617 result.SetStatus (eReturnStatusFailed);
618 }
619 else
620 result.SetStatus (eReturnStatusSuccessFinishNoResult);
621 }
622 }
623 else
624 {
625 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
626 "current list of commands.\n",
627 command_name);
628 result.SetStatus (eReturnStatusFailed);
629 }
630 }
631 else
632 {
633 result.AppendError ("must call 'unalias' with a valid alias");
634 result.SetStatus (eReturnStatusFailed);
635 }
636
637 return result.Succeeded();
638 }
639};
640
Greg Claytond12aeab2011-04-20 16:37:46 +0000641#pragma mark CommandObjectCommandsAddRegex
642//-------------------------------------------------------------------------
643// CommandObjectCommandsAddRegex
644//-------------------------------------------------------------------------
645
646class CommandObjectCommandsAddRegex : public CommandObject
647{
648public:
649 CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
650 CommandObject (interpreter,
651 "commands regex",
652 "Allow the user to create a regular expression command.",
653 NULL),
654 m_options (interpreter)
655 {
656 }
657
658 ~CommandObjectCommandsAddRegex()
659 {
660 }
661
662
663 bool
664 Execute (Args& args, CommandReturnObject &result)
665 {
666 if (args.GetArgumentCount() == 1)
667 {
668 const char *name = args.GetArgumentAtIndex(0);
669 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
670 m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
671 name,
672 m_options.GetHelp (),
673 m_options.GetSyntax (),
674 10));
675 if (reader_sp)
676 {
677 Error err (reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
678 this, // baton
679 eInputReaderGranularityLine, // token size, to pass to callback function
680 "DONE", // end token
681 "> ", // prompt
682 true)); // echo input
683 if (err.Success())
684 {
685 m_interpreter.GetDebugger().PushInputReader (reader_sp);
686 result.SetStatus (eReturnStatusSuccessFinishNoResult);
687 }
688 else
689 {
690 result.AppendError (err.AsCString());
691 result.SetStatus (eReturnStatusFailed);
692 }
693 }
694 }
695 else
696 {
697 result.AppendError ("invalid arguments.\n");
698 result.SetStatus (eReturnStatusFailed);
699 }
700 return result.Succeeded();
701 }
702
703 bool
704 AppendRegexAndSubstitution (const char *regex, const char *subst)
705 {
706 if (m_regex_cmd_ap.get())
707 {
708 m_regex_cmd_ap->AddRegexCommand (regex, subst);
709 return true;
710 }
711 return false;
712 }
713
714 void
715 InputReaderIsDone()
716 {
717 if (m_regex_cmd_ap.get())
718 {
719 if (m_regex_cmd_ap->HasRegexEntries())
720 {
721 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
722 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
723 }
724 }
725 }
726
727 static size_t
728 InputReaderCallback (void *baton,
729 InputReader &reader,
730 lldb::InputReaderAction notification,
731 const char *bytes,
732 size_t bytes_len);
733private:
734 std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
735
736 class CommandOptions : public Options
737 {
738 public:
739
740 CommandOptions (CommandInterpreter &interpreter) :
741 Options (interpreter)
742 {
743 }
744
745 virtual
746 ~CommandOptions (){}
747
748 virtual Error
749 SetOptionValue (uint32_t option_idx, const char *option_arg)
750 {
751 Error error;
752 char short_option = (char) m_getopt_table[option_idx].val;
753
754 switch (short_option)
755 {
756 case 'h':
757 m_help.assign (option_arg);
758 break;
759 case 's':
760 m_syntax.assign (option_arg);
761 break;
762
763 default:
764 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
765 break;
766 }
767
768 return error;
769 }
770
771 void
772 OptionParsingStarting ()
773 {
774 m_help.clear();
775 m_syntax.clear();
776 }
777
778 const OptionDefinition*
779 GetDefinitions ()
780 {
781 return g_option_table;
782 }
783
784 // Options table: Required for subclasses of Options.
785
786 static OptionDefinition g_option_table[];
787
788 const char *
789 GetHelp ()
790 {
791 if (m_help.empty())
792 return NULL;
793 return m_help.c_str();
794 }
795 const char *
796 GetSyntax ()
797 {
798 if (m_syntax.empty())
799 return NULL;
800 return m_syntax.c_str();
801 }
802 // Instance variables to hold the values for command options.
803 protected:
804 std::string m_help;
805 std::string m_syntax;
806 };
807
808 CommandOptions m_options;
809
810 virtual Options *
811 GetOptions ()
812 {
813 return &m_options;
814 }
815
816};
817
818size_t
819CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
820 InputReader &reader,
821 lldb::InputReaderAction notification,
822 const char *bytes,
823 size_t bytes_len)
824{
825 CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
826
827 switch (notification)
828 {
829 case eInputReaderActivate:
830 reader.GetDebugger().GetOutputStream().Printf("%s\n", "Enter multiple regular expressions in the form s/find/replace/ then terminate with an empty line:");
831 break;
832 case eInputReaderReactivate:
833 break;
834
835 case eInputReaderDeactivate:
836 break;
837
838 case eInputReaderGotToken:
839 if (bytes_len == 0)
840 reader.SetIsDone(true);
841 else if (bytes)
842 {
843 std::string regex_sed (bytes, bytes_len);
844 bool success = regex_sed.size() > 3 && regex_sed[0] == 's';
845 if (success)
846 {
847 const size_t first_separator_char_pos = 1;
848 const char separator_char = regex_sed[first_separator_char_pos];
849 const size_t third_separator_char_pos = regex_sed.rfind (separator_char);
850
851 if (third_separator_char_pos != regex_sed.size() - 1)
852 success = false; // Didn't end with regex separator char
853 else
854 {
855 const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
856 if (second_separator_char_pos == std::string::npos)
857 success = false; // Didn't find second regex separator char
858 else
859 {
860 if (second_separator_char_pos <= 3)
861 success = false; // Empty regex is invalid ("s///")
862 else
863 {
864 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
865 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
866 if (regex.empty() || subst.empty())
867 success= false;
868 else
869 {
870 add_regex_cmd->AppendRegexAndSubstitution(regex.c_str(), subst.c_str());
871 }
872 }
873 }
874 }
875 }
876 if (!success)
877 {
878 reader.GetDebugger().GetOutputStream().PutCString("Regular expressions should be in the form s/<regex>/<subst>/.\n");
879 }
880 }
881 break;
882
883 case eInputReaderInterrupt:
884 reader.SetIsDone (true);
885 reader.GetDebugger().GetOutputStream().PutCString("Regular expression command creations was cancelled.\n");
886 break;
887
888 case eInputReaderEndOfFile:
889 reader.SetIsDone (true);
890 break;
891
892 case eInputReaderDone:
893 add_regex_cmd->InputReaderIsDone();
894 break;
895 }
896
897 return bytes_len;
898}
899
900
901OptionDefinition
902CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
903{
904{ LLDB_OPT_SET_1, false, "help", 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
905{ LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
906{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
907};
908
909
Jim Ingham767af882010-07-07 03:36:20 +0000910#pragma mark CommandObjectMultiwordCommands
911
912//-------------------------------------------------------------------------
913// CommandObjectMultiwordCommands
914//-------------------------------------------------------------------------
915
916CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000917 CommandObjectMultiword (interpreter,
918 "commands",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000919 "A set of commands for managing or customizing the debugger commands.",
Jim Ingham767af882010-07-07 03:36:20 +0000920 "commands <subcommand> [<subcommand-options>]")
921{
Greg Clayton238c0a12010-09-18 01:14:36 +0000922 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
923 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
924 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Greg Claytond12aeab2011-04-20 16:37:46 +0000925 LoadSubCommand ("regex", CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +0000926}
927
928CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
929{
930}
931