blob: b3a974b538e973590c8f1e9f139a6ffde4aa6a97 [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
16#include "lldb/Interpreter/Args.h"
17#include "lldb/Core/Debugger.h"
18#include "lldb/Interpreter/CommandInterpreter.h"
19#include "lldb/Interpreter/CommandReturnObject.h"
20#include "lldb/Interpreter/Options.h"
21
22using namespace lldb;
23using namespace lldb_private;
24
Jim Ingham767af882010-07-07 03:36:20 +000025//-------------------------------------------------------------------------
26// CommandObjectCommandsSource
27//-------------------------------------------------------------------------
28
29class CommandObjectCommandsSource : public CommandObject
30{
Jim Ingham949d5ac2011-02-18 00:54:25 +000031private:
32
33 class CommandOptions : public Options
34 {
35 public:
36
37 CommandOptions (){}
38
39 virtual
40 ~CommandOptions (){}
41
42 virtual Error
43 SetOptionValue (int option_idx, const char *option_arg)
44 {
45 Error error;
46 char short_option = (char) m_getopt_table[option_idx].val;
47 bool success;
48
49 switch (short_option)
50 {
51 case 'e':
52 m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
53 if (!success)
54 error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
55 break;
56 case 'c':
57 m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
58 if (!success)
59 error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
60 break;
61 default:
62 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
63 break;
64 }
65
66 return error;
67 }
68
69 void
70 ResetOptionValues ()
71 {
Jim Ingham949d5ac2011-02-18 00:54:25 +000072 m_stop_on_error = true;
73 m_stop_on_continue = true;
74 }
75
Greg Claytonb3448432011-03-24 21:19:54 +000076 const OptionDefinition*
Jim Ingham949d5ac2011-02-18 00:54:25 +000077 GetDefinitions ()
78 {
79 return g_option_table;
80 }
81
82 // Options table: Required for subclasses of Options.
83
Greg Claytonb3448432011-03-24 21:19:54 +000084 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +000085
86 // Instance variables to hold the values for command options.
87
88 bool m_stop_on_error;
89 bool m_stop_on_continue;
90 };
91
92 // Options table: Required for subclasses of Options.
93
Greg Claytonb3448432011-03-24 21:19:54 +000094 static OptionDefinition g_option_table[];
Jim Ingham949d5ac2011-02-18 00:54:25 +000095
96 CommandOptions m_options;
97
98 virtual Options *
99 GetOptions ()
100 {
101 return &m_options;
102 }
103
Jim Ingham767af882010-07-07 03:36:20 +0000104public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000105 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
106 CommandObject (interpreter,
107 "commands source",
108 "Read in debugger commands from the file <filename> and execute them.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000109 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000110 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000111 CommandArgumentEntry arg;
112 CommandArgumentData file_arg;
113
114 // Define the first (and only) variant of this arg.
115 file_arg.arg_type = eArgTypeFilename;
116 file_arg.arg_repetition = eArgRepeatPlain;
117
118 // There is only one variant this argument could be; put it into the argument entry.
119 arg.push_back (file_arg);
120
121 // Push the data for the first argument into the m_arguments vector.
122 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000123 }
124
125 ~CommandObjectCommandsSource ()
126 {
127 }
128
129 bool
130 Execute
131 (
Jim Ingham767af882010-07-07 03:36:20 +0000132 Args& args,
133 CommandReturnObject &result
134 )
135 {
136 const int argc = args.GetArgumentCount();
137 if (argc == 1)
138 {
139 const char *filename = args.GetArgumentAtIndex(0);
Jim Ingham767af882010-07-07 03:36:20 +0000140
141 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
142
Johnny Chena83ea882010-10-20 21:40:50 +0000143 FileSpec cmd_file (filename, true);
Jim Ingham949d5ac2011-02-18 00:54:25 +0000144 ExecutionContext *exe_ctx = NULL; // Just use the default context.
145 bool echo_commands = true;
146 bool print_results = true;
Jim Ingham767af882010-07-07 03:36:20 +0000147
Jim Ingham949d5ac2011-02-18 00:54:25 +0000148 m_interpreter.HandleCommandsFromFile (cmd_file,
149 exe_ctx,
150 m_options.m_stop_on_continue,
151 m_options.m_stop_on_error,
152 echo_commands,
153 print_results,
154 result);
Jim Ingham767af882010-07-07 03:36:20 +0000155 }
156 else
157 {
158 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
159 result.SetStatus (eReturnStatusFailed);
160 }
161 return result.Succeeded();
162
163 }
164};
165
Greg Claytonb3448432011-03-24 21:19:54 +0000166OptionDefinition
Jim Ingham949d5ac2011-02-18 00:54:25 +0000167CommandObjectCommandsSource::CommandOptions::g_option_table[] =
168{
169{ LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on error."},
170{ LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
171{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
172};
173
Jim Ingham767af882010-07-07 03:36:20 +0000174#pragma mark CommandObjectCommandsAlias
175//-------------------------------------------------------------------------
176// CommandObjectCommandsAlias
177//-------------------------------------------------------------------------
178
179class CommandObjectCommandsAlias : public CommandObject
180{
181public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000182 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
183 CommandObject (interpreter,
184 "commands alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000185 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000186 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000187 {
188 SetHelpLong(
189 "'alias' allows the user to create a short-cut or abbreviation for long \n\
190 commands, multi-word commands, and commands that take particular options. \n\
191 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000192 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
193 // command. \n\
194 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
195 // command. Since breakpoint commands are two-word \n\
196 // commands, the user will still need to enter the \n\
197 // second word after 'bp', e.g. 'bp enable' or \n\
198 // 'bp delete'. \n\
199 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
200 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000201 \nAn alias can include some options for the command, with the values either \n\
202 filled in at the time the alias is created, or specified as positional \n\
203 arguments, to be filled in when the alias is invoked. The following example \n\
204 shows how to create aliases with options: \n\
205 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000206 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000207 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
208 options already part of the alias. So if the user wants to set a breakpoint \n\
209 by file and line without explicitly having to use the -f and -l options, the \n\
210 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
211 for the actual arguments that will be passed when the alias command is used. \n\
212 The number in the placeholder refers to the position/order the actual value \n\
213 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
214 will be replaced with the first argument, all the occurrences of '%2' in the \n\
215 alias will be replaced with the second argument, and so on. This also allows \n\
216 actual arguments to be used multiple times within an alias (see 'process \n\
217 launch' example below). So in the 'bfl' case, the actual file value will be \n\
218 filled in with the first argument following 'bfl' and the actual line number \n\
219 value will be filled in with the second argument. The user would use this \n\
220 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000221 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000222 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000223 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000224 \nThis would be the same as if the user had entered \n\
225 'breakpoint set -f my-file.c -l 137'. \n\
226 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000227 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
228 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000229 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000230 \nIf the user always wanted to pass the same value to a particular option, the \n\
231 alias could be defined with that value directly in the alias as a constant, \n\
232 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000233 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
234 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000235
Caroline Tice43b014a2010-10-04 22:28:36 +0000236 CommandArgumentEntry arg1;
237 CommandArgumentEntry arg2;
238 CommandArgumentEntry arg3;
239 CommandArgumentData alias_arg;
240 CommandArgumentData cmd_arg;
241 CommandArgumentData options_arg;
242
243 // Define the first (and only) variant of this arg.
244 alias_arg.arg_type = eArgTypeAliasName;
245 alias_arg.arg_repetition = eArgRepeatPlain;
246
247 // There is only one variant this argument could be; put it into the argument entry.
248 arg1.push_back (alias_arg);
249
250 // Define the first (and only) variant of this arg.
251 cmd_arg.arg_type = eArgTypeCommandName;
252 cmd_arg.arg_repetition = eArgRepeatPlain;
253
254 // There is only one variant this argument could be; put it into the argument entry.
255 arg2.push_back (cmd_arg);
256
257 // Define the first (and only) variant of this arg.
258 options_arg.arg_type = eArgTypeAliasOptions;
259 options_arg.arg_repetition = eArgRepeatOptional;
260
261 // There is only one variant this argument could be; put it into the argument entry.
262 arg3.push_back (options_arg);
263
264 // Push the data for the first argument into the m_arguments vector.
265 m_arguments.push_back (arg1);
266 m_arguments.push_back (arg2);
267 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000268 }
269
270 ~CommandObjectCommandsAlias ()
271 {
272 }
273
Caroline Ticee0da7a52010-12-09 22:52:49 +0000274 bool
275 WantsRawCommandString ()
276 {
277 return true;
278 }
279
280 bool
281 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
282 {
283 Args args (raw_command_line);
284 std::string raw_command_string (raw_command_line);
285
286 size_t argc = args.GetArgumentCount();
287
288 if (argc < 2)
289 {
290 result.AppendError ("'alias' requires at least two arguments");
291 result.SetStatus (eReturnStatusFailed);
292 return false;
293 }
294
295 // Get the alias command.
296
297 const std::string alias_command = args.GetArgumentAtIndex (0);
298
299 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
300 // does the stripping itself.
301 size_t pos = raw_command_string.find (alias_command);
302 if (pos == 0)
303 {
304 raw_command_string = raw_command_string.substr (alias_command.size());
305 pos = raw_command_string.find_first_not_of (' ');
306 if ((pos != std::string::npos) && (pos > 0))
307 raw_command_string = raw_command_string.substr (pos);
308 }
309 else
310 {
311 result.AppendError ("Error parsing command string. No alias created.");
312 result.SetStatus (eReturnStatusFailed);
313 return false;
314 }
315
316
317 // Verify that the command is alias-able.
318 if (m_interpreter.CommandExists (alias_command.c_str()))
319 {
320 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
321 alias_command.c_str());
322 result.SetStatus (eReturnStatusFailed);
323 return false;
324 }
325
326 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
327 // raw_command_string is returned with the name of the command object stripped off the front.
328 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
329
330 if (!cmd_obj)
331 {
332 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
333 " No alias created.", raw_command_string.c_str());
334 result.SetStatus (eReturnStatusFailed);
335 return false;
336 }
337 else if (!cmd_obj->WantsRawCommandString ())
338 {
339 // Note that args was initialized with the original command, and has not been updated to this point.
340 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
341 return Execute (args, result);
342 }
343 else
344 {
345 // Verify & handle any options/arguments passed to the alias command
346
347 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
348 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
349
350 // Check to see if there's anything left in the input command string.
351 if (raw_command_string.size() > 0)
352 {
353
354 // Check to see if the command being aliased can take any command options.
355 Options *options = cmd_obj->GetOptions();
356 if (options)
357 {
358 // See if any options were specified as part of the alias; if so, handle them appropriately
Greg Clayton24bc5d92011-03-30 18:16:51 +0000359 options->Reset ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000360 Args tmp_args (raw_command_string.c_str());
361 args.Unshift ("dummy_arg");
362 args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
363 args.Shift ();
364 if (result.Succeeded())
365 options->VerifyPartialOptions (result);
366 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
367 {
368 result.AppendError ("Unable to create requested alias.\n");
369 return false;
370 }
371 }
372 // Anything remaining must be plain raw input. Push it in as a single raw input argument.
373 if (raw_command_string.size() > 0)
374 option_arg_vector->push_back (OptionArgPair ("<argument>",
375 OptionArgValue (-1,
376 raw_command_string)));
377 }
378
379 // Create the alias
380 if (m_interpreter.AliasExists (alias_command.c_str())
381 || m_interpreter.UserCommandExists (alias_command.c_str()))
382 {
383 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
384 if (temp_option_arg_sp.get())
385 {
386 if (option_arg_vector->size() == 0)
387 m_interpreter.RemoveAliasOptions (alias_command.c_str());
388 }
389 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
390 alias_command.c_str());
391 }
392
393 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
Caroline Tice56d2fc42010-12-14 18:51:39 +0000394 if (cmd_obj_sp)
395 {
396 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
397 if (option_arg_vector->size() > 0)
398 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
399 result.SetStatus (eReturnStatusSuccessFinishNoResult);
400 }
401 else
402 {
403 result.AppendError ("Unable to create requested alias.\n");
404 result.SetStatus (eReturnStatusFailed);
405 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000406 }
407 return result.Succeeded();
408 }
Jim Ingham767af882010-07-07 03:36:20 +0000409
410 bool
411 Execute
412 (
Jim Ingham767af882010-07-07 03:36:20 +0000413 Args& args,
414 CommandReturnObject &result
415 )
416 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000417 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000418
419 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000420 {
Jim Ingham767af882010-07-07 03:36:20 +0000421 result.AppendError ("'alias' requires at least two arguments");
422 result.SetStatus (eReturnStatusFailed);
423 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000424 }
Jim Ingham767af882010-07-07 03:36:20 +0000425
426 const std::string alias_command = args.GetArgumentAtIndex(0);
427 const std::string actual_command = args.GetArgumentAtIndex(1);
428
429 args.Shift(); // Shift the alias command word off the argument vector.
430 args.Shift(); // Shift the old command word off the argument vector.
431
432 // Verify that the command is alias'able, and get the appropriate command object.
433
Greg Clayton238c0a12010-09-18 01:14:36 +0000434 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000435 {
436 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
437 alias_command.c_str());
438 result.SetStatus (eReturnStatusFailed);
439 }
440 else
441 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000442 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000443 CommandObjectSP subcommand_obj_sp;
444 bool use_subcommand = false;
445 if (command_obj_sp.get())
446 {
447 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000448 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000449 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
450 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
451
Caroline Ticee0da7a52010-12-09 22:52:49 +0000452 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000453 {
454 if (argc >= 3)
455 {
456 const std::string sub_command = args.GetArgumentAtIndex(0);
457 assert (sub_command.length() != 0);
458 subcommand_obj_sp =
459 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
460 if (subcommand_obj_sp.get())
461 {
462 sub_cmd_obj = subcommand_obj_sp.get();
463 use_subcommand = true;
464 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000465 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000466 }
467 else
468 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000469 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
470 "Unable to create alias.\n",
471 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000472 result.SetStatus (eReturnStatusFailed);
473 return false;
474 }
475 }
476 }
477
478 // Verify & handle any options/arguments passed to the alias command
479
480 if (args.GetArgumentCount () > 0)
481 {
Jim Ingham767af882010-07-07 03:36:20 +0000482 if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
483 || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
484 {
485 Options *options;
486 if (use_subcommand)
487 options = sub_cmd_obj->GetOptions();
488 else
489 options = cmd_obj->GetOptions();
Greg Clayton24bc5d92011-03-30 18:16:51 +0000490 options->Reset ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000491 std::string empty_string;
Jim Ingham767af882010-07-07 03:36:20 +0000492 args.Unshift ("dummy_arg");
Caroline Ticee0da7a52010-12-09 22:52:49 +0000493 args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
Jim Ingham767af882010-07-07 03:36:20 +0000494 args.Shift ();
495 if (result.Succeeded())
496 options->VerifyPartialOptions (result);
Caroline Tice8bb61f02010-09-21 23:25:40 +0000497 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
498 {
499 result.AppendError ("Unable to create requested command alias.\n");
Caroline Ticee6866a32010-10-28 23:17:48 +0000500 return false;
Caroline Tice8bb61f02010-09-21 23:25:40 +0000501 }
Jim Ingham767af882010-07-07 03:36:20 +0000502 }
Caroline Tice8bb61f02010-09-21 23:25:40 +0000503
504 // Anything remaining in args must be a plain argument.
505
506 argc = args.GetArgumentCount();
507 for (size_t i = 0; i < argc; ++i)
Caroline Tice44c841d2010-12-07 19:58:26 +0000508 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
509 option_arg_vector->push_back
510 (OptionArgPair ("<argument>",
511 OptionArgValue (-1,
512 std::string (args.GetArgumentAtIndex (i)))));
Jim Ingham767af882010-07-07 03:36:20 +0000513 }
514
515 // Create the alias.
516
Greg Clayton238c0a12010-09-18 01:14:36 +0000517 if (m_interpreter.AliasExists (alias_command.c_str())
518 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000519 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000520 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000521 if (tmp_option_arg_sp.get())
522 {
523 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000524 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000525 }
526 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
527 alias_command.c_str());
528 }
529
530 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000531 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000532 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000533 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000534 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000535 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000536 result.SetStatus (eReturnStatusSuccessFinishNoResult);
537 }
538 else
539 {
540 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
541 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000542 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000543 }
544 }
545
546 return result.Succeeded();
547 }
548};
549
550#pragma mark CommandObjectCommandsUnalias
551//-------------------------------------------------------------------------
552// CommandObjectCommandsUnalias
553//-------------------------------------------------------------------------
554
555class CommandObjectCommandsUnalias : public CommandObject
556{
557public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000558 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
559 CommandObject (interpreter,
560 "commands unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000561 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000562 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000563 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000564 CommandArgumentEntry arg;
565 CommandArgumentData alias_arg;
566
567 // Define the first (and only) variant of this arg.
568 alias_arg.arg_type = eArgTypeAliasName;
569 alias_arg.arg_repetition = eArgRepeatPlain;
570
571 // There is only one variant this argument could be; put it into the argument entry.
572 arg.push_back (alias_arg);
573
574 // Push the data for the first argument into the m_arguments vector.
575 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000576 }
577
578 ~CommandObjectCommandsUnalias()
579 {
580 }
581
582
583 bool
584 Execute
585 (
Jim Ingham767af882010-07-07 03:36:20 +0000586 Args& args,
587 CommandReturnObject &result
588 )
589 {
590 CommandObject::CommandMap::iterator pos;
591 CommandObject *cmd_obj;
592
593 if (args.GetArgumentCount() != 0)
594 {
595 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000596 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000597 if (cmd_obj)
598 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000599 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000600 {
601 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
602 command_name);
603 result.SetStatus (eReturnStatusFailed);
604 }
605 else
606 {
607
Greg Clayton238c0a12010-09-18 01:14:36 +0000608 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000609 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000610 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000611 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
612 command_name);
613 else
614 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
615 result.SetStatus (eReturnStatusFailed);
616 }
617 else
618 result.SetStatus (eReturnStatusSuccessFinishNoResult);
619 }
620 }
621 else
622 {
623 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
624 "current list of commands.\n",
625 command_name);
626 result.SetStatus (eReturnStatusFailed);
627 }
628 }
629 else
630 {
631 result.AppendError ("must call 'unalias' with a valid alias");
632 result.SetStatus (eReturnStatusFailed);
633 }
634
635 return result.Succeeded();
636 }
637};
638
639#pragma mark CommandObjectMultiwordCommands
640
641//-------------------------------------------------------------------------
642// CommandObjectMultiwordCommands
643//-------------------------------------------------------------------------
644
645CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000646 CommandObjectMultiword (interpreter,
647 "commands",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000648 "A set of commands for managing or customizing the debugger commands.",
Jim Ingham767af882010-07-07 03:36:20 +0000649 "commands <subcommand> [<subcommand-options>]")
650{
Greg Clayton238c0a12010-09-18 01:14:36 +0000651 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
652 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
653 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +0000654}
655
656CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
657{
658}
659