blob: e2358bda6614c7c017936421fab0c98b6eac8f5e [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
25const char *k_space_characters = "\t\n\v\f\r ";
26
27//-------------------------------------------------------------------------
28// CommandObjectCommandsSource
29//-------------------------------------------------------------------------
30
31class CommandObjectCommandsSource : public CommandObject
32{
33public:
Greg Clayton238c0a12010-09-18 01:14:36 +000034 CommandObjectCommandsSource(CommandInterpreter &interpreter) :
35 CommandObject (interpreter,
36 "commands source",
37 "Read in debugger commands from the file <filename> and execute them.",
Caroline Tice43b014a2010-10-04 22:28:36 +000038 NULL)
Jim Ingham767af882010-07-07 03:36:20 +000039 {
Caroline Tice43b014a2010-10-04 22:28:36 +000040 CommandArgumentEntry arg;
41 CommandArgumentData file_arg;
42
43 // Define the first (and only) variant of this arg.
44 file_arg.arg_type = eArgTypeFilename;
45 file_arg.arg_repetition = eArgRepeatPlain;
46
47 // There is only one variant this argument could be; put it into the argument entry.
48 arg.push_back (file_arg);
49
50 // Push the data for the first argument into the m_arguments vector.
51 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +000052 }
53
54 ~CommandObjectCommandsSource ()
55 {
56 }
57
58 bool
59 Execute
60 (
Jim Ingham767af882010-07-07 03:36:20 +000061 Args& args,
62 CommandReturnObject &result
63 )
64 {
65 const int argc = args.GetArgumentCount();
66 if (argc == 1)
67 {
68 const char *filename = args.GetArgumentAtIndex(0);
69 bool success = true;
70
71 result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
72
Johnny Chena83ea882010-10-20 21:40:50 +000073 FileSpec cmd_file (filename, true);
Jim Ingham767af882010-07-07 03:36:20 +000074 if (cmd_file.Exists())
75 {
76 STLStringArray commands;
77 success = cmd_file.ReadFileLines (commands);
78
79 STLStringArray::iterator pos = commands.begin();
80
81 // Trim out any empty lines or lines that start with the comment
82 // char '#'
83 while (pos != commands.end())
84 {
Jim Ingham767af882010-07-07 03:36:20 +000085 size_t non_space = pos->find_first_not_of (k_space_characters);
Greg Claytona830adb2010-10-04 01:05:56 +000086 // Check for empty line or comment line (lines whose first
87 // non-space character is a '#')
88 if (non_space == std::string::npos || (*pos)[non_space] == '#')
Jim Ingham767af882010-07-07 03:36:20 +000089 pos = commands.erase(pos);
90 else
91 ++pos;
92 }
93
94 if (commands.size() > 0)
95 {
96 const size_t num_commands = commands.size();
97 size_t i;
98 for (i = 0; i<num_commands; ++i)
99 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000100 result.GetOutputStream().Printf ("%s %s\n",
101 m_interpreter.GetPrompt(),
102 commands[i].c_str());
103 if (!m_interpreter.HandleCommand(commands[i].c_str(), false, result))
Jim Ingham767af882010-07-07 03:36:20 +0000104 break;
105 }
106
107 if (i < num_commands)
108 {
109 result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n",
110 filename, commands[i].c_str());
111 result.SetStatus (eReturnStatusSuccessFinishResult);
112 }
113 else
114 {
115 success = true;
116 result.SetStatus (eReturnStatusFailed);
117 }
118 }
119 }
120 else
121 {
122 result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename);
123 result.SetStatus (eReturnStatusFailed);
124 success = false;
125 }
126
127 if (success)
128 {
129 result.SetStatus (eReturnStatusSuccessFinishNoResult);
130 }
131 }
132 else
133 {
134 result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
135 result.SetStatus (eReturnStatusFailed);
136 }
137 return result.Succeeded();
138
139 }
140};
141
142#pragma mark CommandObjectCommandsAlias
143//-------------------------------------------------------------------------
144// CommandObjectCommandsAlias
145//-------------------------------------------------------------------------
146
147class CommandObjectCommandsAlias : public CommandObject
148{
149public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000150 CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
151 CommandObject (interpreter,
152 "commands alias",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000153 "Allow users to define their own debugger command abbreviations.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000154 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000155 {
156 SetHelpLong(
157 "'alias' allows the user to create a short-cut or abbreviation for long \n\
158 commands, multi-word commands, and commands that take particular options. \n\
159 Below are some simple examples of how one might use the 'alias' command: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000160 \n 'commands alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
161 // command. \n\
162 'commands alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
163 // command. Since breakpoint commands are two-word \n\
164 // commands, the user will still need to enter the \n\
165 // second word after 'bp', e.g. 'bp enable' or \n\
166 // 'bp delete'. \n\
167 'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
168 // two-word command 'breakpoint list'. \n\
Jim Ingham767af882010-07-07 03:36:20 +0000169 \nAn alias can include some options for the command, with the values either \n\
170 filled in at the time the alias is created, or specified as positional \n\
171 arguments, to be filled in when the alias is invoked. The following example \n\
172 shows how to create aliases with options: \n\
173 \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000174 'commands alias bfl breakpoint set -f %1 -l %2' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000175 \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
176 options already part of the alias. So if the user wants to set a breakpoint \n\
177 by file and line without explicitly having to use the -f and -l options, the \n\
178 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
179 for the actual arguments that will be passed when the alias command is used. \n\
180 The number in the placeholder refers to the position/order the actual value \n\
181 occupies when the alias is used. So all the occurrences of '%1' in the alias \n\
182 will be replaced with the first argument, all the occurrences of '%2' in the \n\
183 alias will be replaced with the second argument, and so on. This also allows \n\
184 actual arguments to be used multiple times within an alias (see 'process \n\
185 launch' example below). So in the 'bfl' case, the actual file value will be \n\
186 filled in with the first argument following 'bfl' and the actual line number \n\
187 value will be filled in with the second argument. The user would use this \n\
188 alias as follows: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000189 \n (lldb) commands alias bfl breakpoint set -f %1 -l %2 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000190 <... some time later ...> \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000191 (lldb) bfl my-file.c 137 \n\
Jim Ingham767af882010-07-07 03:36:20 +0000192 \nThis would be the same as if the user had entered \n\
193 'breakpoint set -f my-file.c -l 137'. \n\
194 \nAnother example: \n\
Caroline Tice31fbb642010-09-08 22:08:58 +0000195 \n (lldb) commands alias pltty process launch -s -o %1 -e %1 \n\
196 (lldb) pltty /dev/tty0 \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000197 // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
Jim Ingham767af882010-07-07 03:36:20 +0000198 \nIf the user always wanted to pass the same value to a particular option, the \n\
199 alias could be defined with that value directly in the alias as a constant, \n\
200 rather than using a positional placeholder: \n\
Sean Callanana3aff732010-08-09 18:50:15 +0000201 \n commands alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
202 // 3 of whatever file is indicated. \n");
Jim Ingham767af882010-07-07 03:36:20 +0000203
Caroline Tice43b014a2010-10-04 22:28:36 +0000204 CommandArgumentEntry arg1;
205 CommandArgumentEntry arg2;
206 CommandArgumentEntry arg3;
207 CommandArgumentData alias_arg;
208 CommandArgumentData cmd_arg;
209 CommandArgumentData options_arg;
210
211 // Define the first (and only) variant of this arg.
212 alias_arg.arg_type = eArgTypeAliasName;
213 alias_arg.arg_repetition = eArgRepeatPlain;
214
215 // There is only one variant this argument could be; put it into the argument entry.
216 arg1.push_back (alias_arg);
217
218 // Define the first (and only) variant of this arg.
219 cmd_arg.arg_type = eArgTypeCommandName;
220 cmd_arg.arg_repetition = eArgRepeatPlain;
221
222 // There is only one variant this argument could be; put it into the argument entry.
223 arg2.push_back (cmd_arg);
224
225 // Define the first (and only) variant of this arg.
226 options_arg.arg_type = eArgTypeAliasOptions;
227 options_arg.arg_repetition = eArgRepeatOptional;
228
229 // There is only one variant this argument could be; put it into the argument entry.
230 arg3.push_back (options_arg);
231
232 // Push the data for the first argument into the m_arguments vector.
233 m_arguments.push_back (arg1);
234 m_arguments.push_back (arg2);
235 m_arguments.push_back (arg3);
Jim Ingham767af882010-07-07 03:36:20 +0000236 }
237
238 ~CommandObjectCommandsAlias ()
239 {
240 }
241
Caroline Ticee0da7a52010-12-09 22:52:49 +0000242 bool
243 WantsRawCommandString ()
244 {
245 return true;
246 }
247
248 bool
249 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
250 {
251 Args args (raw_command_line);
252 std::string raw_command_string (raw_command_line);
253
254 size_t argc = args.GetArgumentCount();
255
256 if (argc < 2)
257 {
258 result.AppendError ("'alias' requires at least two arguments");
259 result.SetStatus (eReturnStatusFailed);
260 return false;
261 }
262
263 // Get the alias command.
264
265 const std::string alias_command = args.GetArgumentAtIndex (0);
266
267 // Strip the new alias name off 'raw_command_string' (leave it on args, which gets passed to 'Execute', which
268 // does the stripping itself.
269 size_t pos = raw_command_string.find (alias_command);
270 if (pos == 0)
271 {
272 raw_command_string = raw_command_string.substr (alias_command.size());
273 pos = raw_command_string.find_first_not_of (' ');
274 if ((pos != std::string::npos) && (pos > 0))
275 raw_command_string = raw_command_string.substr (pos);
276 }
277 else
278 {
279 result.AppendError ("Error parsing command string. No alias created.");
280 result.SetStatus (eReturnStatusFailed);
281 return false;
282 }
283
284
285 // Verify that the command is alias-able.
286 if (m_interpreter.CommandExists (alias_command.c_str()))
287 {
288 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
289 alias_command.c_str());
290 result.SetStatus (eReturnStatusFailed);
291 return false;
292 }
293
294 // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
295 // raw_command_string is returned with the name of the command object stripped off the front.
296 CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
297
298 if (!cmd_obj)
299 {
300 result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
301 " No alias created.", raw_command_string.c_str());
302 result.SetStatus (eReturnStatusFailed);
303 return false;
304 }
305 else if (!cmd_obj->WantsRawCommandString ())
306 {
307 // Note that args was initialized with the original command, and has not been updated to this point.
308 // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
309 return Execute (args, result);
310 }
311 else
312 {
313 // Verify & handle any options/arguments passed to the alias command
314
315 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
316 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
317
318 // Check to see if there's anything left in the input command string.
319 if (raw_command_string.size() > 0)
320 {
321
322 // Check to see if the command being aliased can take any command options.
323 Options *options = cmd_obj->GetOptions();
324 if (options)
325 {
326 // See if any options were specified as part of the alias; if so, handle them appropriately
327 options->ResetOptionValues ();
328 Args tmp_args (raw_command_string.c_str());
329 args.Unshift ("dummy_arg");
330 args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
331 args.Shift ();
332 if (result.Succeeded())
333 options->VerifyPartialOptions (result);
334 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
335 {
336 result.AppendError ("Unable to create requested alias.\n");
337 return false;
338 }
339 }
340 // Anything remaining must be plain raw input. Push it in as a single raw input argument.
341 if (raw_command_string.size() > 0)
342 option_arg_vector->push_back (OptionArgPair ("<argument>",
343 OptionArgValue (-1,
344 raw_command_string)));
345 }
346
347 // Create the alias
348 if (m_interpreter.AliasExists (alias_command.c_str())
349 || m_interpreter.UserCommandExists (alias_command.c_str()))
350 {
351 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
352 if (temp_option_arg_sp.get())
353 {
354 if (option_arg_vector->size() == 0)
355 m_interpreter.RemoveAliasOptions (alias_command.c_str());
356 }
357 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
358 alias_command.c_str());
359 }
360
361 CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
Caroline Tice56d2fc42010-12-14 18:51:39 +0000362 if (cmd_obj_sp)
363 {
364 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
365 if (option_arg_vector->size() > 0)
366 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
367 result.SetStatus (eReturnStatusSuccessFinishNoResult);
368 }
369 else
370 {
371 result.AppendError ("Unable to create requested alias.\n");
372 result.SetStatus (eReturnStatusFailed);
373 }
Caroline Ticee0da7a52010-12-09 22:52:49 +0000374 }
375 return result.Succeeded();
376 }
Jim Ingham767af882010-07-07 03:36:20 +0000377
378 bool
379 Execute
380 (
Jim Ingham767af882010-07-07 03:36:20 +0000381 Args& args,
382 CommandReturnObject &result
383 )
384 {
Caroline Tice8bb61f02010-09-21 23:25:40 +0000385 size_t argc = args.GetArgumentCount();
Jim Ingham767af882010-07-07 03:36:20 +0000386
387 if (argc < 2)
Greg Clayton54e7afa2010-07-09 20:39:50 +0000388 {
Jim Ingham767af882010-07-07 03:36:20 +0000389 result.AppendError ("'alias' requires at least two arguments");
390 result.SetStatus (eReturnStatusFailed);
391 return false;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000392 }
Jim Ingham767af882010-07-07 03:36:20 +0000393
394 const std::string alias_command = args.GetArgumentAtIndex(0);
395 const std::string actual_command = args.GetArgumentAtIndex(1);
396
397 args.Shift(); // Shift the alias command word off the argument vector.
398 args.Shift(); // Shift the old command word off the argument vector.
399
400 // Verify that the command is alias'able, and get the appropriate command object.
401
Greg Clayton238c0a12010-09-18 01:14:36 +0000402 if (m_interpreter.CommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000403 {
404 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
405 alias_command.c_str());
406 result.SetStatus (eReturnStatusFailed);
407 }
408 else
409 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000410 CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
Jim Ingham767af882010-07-07 03:36:20 +0000411 CommandObjectSP subcommand_obj_sp;
412 bool use_subcommand = false;
413 if (command_obj_sp.get())
414 {
415 CommandObject *cmd_obj = command_obj_sp.get();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000416 CommandObject *sub_cmd_obj = NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000417 OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
418 OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
419
Caroline Ticee0da7a52010-12-09 22:52:49 +0000420 while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
Jim Ingham767af882010-07-07 03:36:20 +0000421 {
422 if (argc >= 3)
423 {
424 const std::string sub_command = args.GetArgumentAtIndex(0);
425 assert (sub_command.length() != 0);
426 subcommand_obj_sp =
427 (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
428 if (subcommand_obj_sp.get())
429 {
430 sub_cmd_obj = subcommand_obj_sp.get();
431 use_subcommand = true;
432 args.Shift(); // Shift the sub_command word off the argument vector.
Caroline Ticee0da7a52010-12-09 22:52:49 +0000433 cmd_obj = sub_cmd_obj;
Jim Ingham767af882010-07-07 03:36:20 +0000434 }
435 else
436 {
Caroline Tice5d53b622010-11-02 19:00:04 +0000437 result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'. "
438 "Unable to create alias.\n",
439 sub_command.c_str(), actual_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000440 result.SetStatus (eReturnStatusFailed);
441 return false;
442 }
443 }
444 }
445
446 // Verify & handle any options/arguments passed to the alias command
447
448 if (args.GetArgumentCount () > 0)
449 {
Jim Ingham767af882010-07-07 03:36:20 +0000450 if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
451 || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
452 {
453 Options *options;
454 if (use_subcommand)
455 options = sub_cmd_obj->GetOptions();
456 else
457 options = cmd_obj->GetOptions();
458 options->ResetOptionValues ();
Caroline Ticee0da7a52010-12-09 22:52:49 +0000459 std::string empty_string;
Jim Ingham767af882010-07-07 03:36:20 +0000460 args.Unshift ("dummy_arg");
Caroline Ticee0da7a52010-12-09 22:52:49 +0000461 args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
Jim Ingham767af882010-07-07 03:36:20 +0000462 args.Shift ();
463 if (result.Succeeded())
464 options->VerifyPartialOptions (result);
Caroline Tice8bb61f02010-09-21 23:25:40 +0000465 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
466 {
467 result.AppendError ("Unable to create requested command alias.\n");
Caroline Ticee6866a32010-10-28 23:17:48 +0000468 return false;
Caroline Tice8bb61f02010-09-21 23:25:40 +0000469 }
Jim Ingham767af882010-07-07 03:36:20 +0000470 }
Caroline Tice8bb61f02010-09-21 23:25:40 +0000471
472 // Anything remaining in args must be a plain argument.
473
474 argc = args.GetArgumentCount();
475 for (size_t i = 0; i < argc; ++i)
Caroline Tice44c841d2010-12-07 19:58:26 +0000476 if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
477 option_arg_vector->push_back
478 (OptionArgPair ("<argument>",
479 OptionArgValue (-1,
480 std::string (args.GetArgumentAtIndex (i)))));
Jim Ingham767af882010-07-07 03:36:20 +0000481 }
482
483 // Create the alias.
484
Greg Clayton238c0a12010-09-18 01:14:36 +0000485 if (m_interpreter.AliasExists (alias_command.c_str())
486 || m_interpreter.UserCommandExists (alias_command.c_str()))
Jim Ingham767af882010-07-07 03:36:20 +0000487 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000488 OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
Jim Ingham767af882010-07-07 03:36:20 +0000489 if (tmp_option_arg_sp.get())
490 {
491 if (option_arg_vector->size() == 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000492 m_interpreter.RemoveAliasOptions (alias_command.c_str());
Jim Ingham767af882010-07-07 03:36:20 +0000493 }
494 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
495 alias_command.c_str());
496 }
497
498 if (use_subcommand)
Greg Clayton238c0a12010-09-18 01:14:36 +0000499 m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000500 else
Greg Clayton238c0a12010-09-18 01:14:36 +0000501 m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000502 if (option_arg_vector->size() > 0)
Greg Clayton238c0a12010-09-18 01:14:36 +0000503 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
Jim Ingham767af882010-07-07 03:36:20 +0000504 result.SetStatus (eReturnStatusSuccessFinishNoResult);
505 }
506 else
507 {
508 result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
509 result.SetStatus (eReturnStatusFailed);
Caroline Ticee6866a32010-10-28 23:17:48 +0000510 return false;
Jim Ingham767af882010-07-07 03:36:20 +0000511 }
512 }
513
514 return result.Succeeded();
515 }
516};
517
518#pragma mark CommandObjectCommandsUnalias
519//-------------------------------------------------------------------------
520// CommandObjectCommandsUnalias
521//-------------------------------------------------------------------------
522
523class CommandObjectCommandsUnalias : public CommandObject
524{
525public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000526 CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
527 CommandObject (interpreter,
528 "commands unalias",
Caroline Tice146292c2010-09-12 04:56:10 +0000529 "Allow the user to remove/delete a user-defined command abbreviation.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000530 NULL)
Jim Ingham767af882010-07-07 03:36:20 +0000531 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000532 CommandArgumentEntry arg;
533 CommandArgumentData alias_arg;
534
535 // Define the first (and only) variant of this arg.
536 alias_arg.arg_type = eArgTypeAliasName;
537 alias_arg.arg_repetition = eArgRepeatPlain;
538
539 // There is only one variant this argument could be; put it into the argument entry.
540 arg.push_back (alias_arg);
541
542 // Push the data for the first argument into the m_arguments vector.
543 m_arguments.push_back (arg);
Jim Ingham767af882010-07-07 03:36:20 +0000544 }
545
546 ~CommandObjectCommandsUnalias()
547 {
548 }
549
550
551 bool
552 Execute
553 (
Jim Ingham767af882010-07-07 03:36:20 +0000554 Args& args,
555 CommandReturnObject &result
556 )
557 {
558 CommandObject::CommandMap::iterator pos;
559 CommandObject *cmd_obj;
560
561 if (args.GetArgumentCount() != 0)
562 {
563 const char *command_name = args.GetArgumentAtIndex(0);
Greg Clayton238c0a12010-09-18 01:14:36 +0000564 cmd_obj = m_interpreter.GetCommandObject(command_name);
Jim Ingham767af882010-07-07 03:36:20 +0000565 if (cmd_obj)
566 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000567 if (m_interpreter.CommandExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000568 {
569 result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
570 command_name);
571 result.SetStatus (eReturnStatusFailed);
572 }
573 else
574 {
575
Greg Clayton238c0a12010-09-18 01:14:36 +0000576 if (m_interpreter.RemoveAlias (command_name) == false)
Jim Ingham767af882010-07-07 03:36:20 +0000577 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000578 if (m_interpreter.AliasExists (command_name))
Jim Ingham767af882010-07-07 03:36:20 +0000579 result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
580 command_name);
581 else
582 result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
583 result.SetStatus (eReturnStatusFailed);
584 }
585 else
586 result.SetStatus (eReturnStatusSuccessFinishNoResult);
587 }
588 }
589 else
590 {
591 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
592 "current list of commands.\n",
593 command_name);
594 result.SetStatus (eReturnStatusFailed);
595 }
596 }
597 else
598 {
599 result.AppendError ("must call 'unalias' with a valid alias");
600 result.SetStatus (eReturnStatusFailed);
601 }
602
603 return result.Succeeded();
604 }
605};
606
607#pragma mark CommandObjectMultiwordCommands
608
609//-------------------------------------------------------------------------
610// CommandObjectMultiwordCommands
611//-------------------------------------------------------------------------
612
613CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000614 CommandObjectMultiword (interpreter,
615 "commands",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000616 "A set of commands for managing or customizing the debugger commands.",
Jim Ingham767af882010-07-07 03:36:20 +0000617 "commands <subcommand> [<subcommand-options>]")
618{
Greg Clayton238c0a12010-09-18 01:14:36 +0000619 LoadSubCommand ("source", CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
620 LoadSubCommand ("alias", CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
621 LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
Jim Ingham767af882010-07-07 03:36:20 +0000622}
623
624CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
625{
626}
627