1ebc09c36SJim Ingham //===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===//
2ebc09c36SJim Ingham //
3ebc09c36SJim Ingham //                     The LLVM Compiler Infrastructure
4ebc09c36SJim Ingham //
5ebc09c36SJim Ingham // This file is distributed under the University of Illinois Open Source
6ebc09c36SJim Ingham // License. See LICENSE.TXT for details.
7ebc09c36SJim Ingham //
8ebc09c36SJim Ingham //===----------------------------------------------------------------------===//
9ebc09c36SJim Ingham 
10ebc09c36SJim Ingham #include "CommandObjectCommands.h"
11ebc09c36SJim Ingham 
12ebc09c36SJim Ingham // C Includes
13ebc09c36SJim Ingham // C++ Includes
14ebc09c36SJim Ingham // Other libraries and framework includes
15ebc09c36SJim Ingham // Project includes
16ebc09c36SJim Ingham #include "lldb/Interpreter/Args.h"
17ebc09c36SJim Ingham #include "lldb/Core/Debugger.h"
18ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
19ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h"
20ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h"
21ebc09c36SJim Ingham 
22ebc09c36SJim Ingham using namespace lldb;
23ebc09c36SJim Ingham using namespace lldb_private;
24ebc09c36SJim Ingham 
25ebc09c36SJim Ingham const char *k_space_characters = "\t\n\v\f\r ";
26ebc09c36SJim Ingham 
27ebc09c36SJim Ingham //-------------------------------------------------------------------------
28ebc09c36SJim Ingham // CommandObjectCommandsSource
29ebc09c36SJim Ingham //-------------------------------------------------------------------------
30ebc09c36SJim Ingham 
31ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject
32ebc09c36SJim Ingham {
33ebc09c36SJim Ingham public:
34a7015092SGreg Clayton     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
35a7015092SGreg Clayton         CommandObject (interpreter,
36a7015092SGreg Clayton                        "commands source",
37e3d26315SCaroline Tice                        "Read in debugger commands from the file <filename> and execute them.",
38405fe67fSCaroline Tice                        NULL)
39ebc09c36SJim Ingham     {
40405fe67fSCaroline Tice         CommandArgumentEntry arg;
41405fe67fSCaroline Tice         CommandArgumentData file_arg;
42405fe67fSCaroline Tice 
43405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
44405fe67fSCaroline Tice         file_arg.arg_type = eArgTypeFilename;
45405fe67fSCaroline Tice         file_arg.arg_repetition = eArgRepeatPlain;
46405fe67fSCaroline Tice 
47405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
48405fe67fSCaroline Tice         arg.push_back (file_arg);
49405fe67fSCaroline Tice 
50405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
51405fe67fSCaroline Tice         m_arguments.push_back (arg);
52ebc09c36SJim Ingham     }
53ebc09c36SJim Ingham 
54ebc09c36SJim Ingham     ~CommandObjectCommandsSource ()
55ebc09c36SJim Ingham     {
56ebc09c36SJim Ingham     }
57ebc09c36SJim Ingham 
58ebc09c36SJim Ingham     bool
59ebc09c36SJim Ingham     Execute
60ebc09c36SJim Ingham     (
61ebc09c36SJim Ingham         Args& args,
62ebc09c36SJim Ingham         CommandReturnObject &result
63ebc09c36SJim Ingham     )
64ebc09c36SJim Ingham     {
65ebc09c36SJim Ingham         const int argc = args.GetArgumentCount();
66ebc09c36SJim Ingham         if (argc == 1)
67ebc09c36SJim Ingham         {
68ebc09c36SJim Ingham             const char *filename = args.GetArgumentAtIndex(0);
69ebc09c36SJim Ingham             bool success = true;
70ebc09c36SJim Ingham 
71ebc09c36SJim Ingham             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
72ebc09c36SJim Ingham 
731ee3853fSJohnny Chen             FileSpec cmd_file (filename, true);
74ebc09c36SJim Ingham             if (cmd_file.Exists())
75ebc09c36SJim Ingham             {
76ebc09c36SJim Ingham                 STLStringArray commands;
77ebc09c36SJim Ingham                 success = cmd_file.ReadFileLines (commands);
78ebc09c36SJim Ingham 
79ebc09c36SJim Ingham                 STLStringArray::iterator pos = commands.begin();
80ebc09c36SJim Ingham 
81ebc09c36SJim Ingham                 // Trim out any empty lines or lines that start with the comment
82ebc09c36SJim Ingham                 // char '#'
83ebc09c36SJim Ingham                 while (pos != commands.end())
84ebc09c36SJim Ingham                 {
85ebc09c36SJim Ingham                     size_t non_space = pos->find_first_not_of (k_space_characters);
860603aa9dSGreg Clayton                     // Check for empty line or comment line (lines whose first
870603aa9dSGreg Clayton                     // non-space character is a '#')
880603aa9dSGreg Clayton                     if (non_space == std::string::npos || (*pos)[non_space] == '#')
89ebc09c36SJim Ingham                         pos = commands.erase(pos);
90ebc09c36SJim Ingham                     else
91ebc09c36SJim Ingham                         ++pos;
92ebc09c36SJim Ingham                 }
93ebc09c36SJim Ingham 
94ebc09c36SJim Ingham                 if (commands.size() > 0)
95ebc09c36SJim Ingham                 {
96ebc09c36SJim Ingham                     const size_t num_commands = commands.size();
97ebc09c36SJim Ingham                     size_t i;
98ebc09c36SJim Ingham                     for (i = 0; i<num_commands; ++i)
99ebc09c36SJim Ingham                     {
100a7015092SGreg Clayton                         result.GetOutputStream().Printf ("%s %s\n",
101a7015092SGreg Clayton                                                          m_interpreter.GetPrompt(),
102a7015092SGreg Clayton                                                          commands[i].c_str());
103a7015092SGreg Clayton                         if (!m_interpreter.HandleCommand(commands[i].c_str(), false, result))
104ebc09c36SJim Ingham                             break;
105ebc09c36SJim Ingham                     }
106ebc09c36SJim Ingham 
107ebc09c36SJim Ingham                     if (i < num_commands)
108ebc09c36SJim Ingham                     {
109ebc09c36SJim Ingham                         result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n",
110ebc09c36SJim Ingham                                                      filename, commands[i].c_str());
111ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishResult);
112ebc09c36SJim Ingham                     }
113ebc09c36SJim Ingham                     else
114ebc09c36SJim Ingham                     {
115ebc09c36SJim Ingham                         success = true;
116ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusFailed);
117ebc09c36SJim Ingham                     }
118ebc09c36SJim Ingham                 }
119ebc09c36SJim Ingham             }
120ebc09c36SJim Ingham             else
121ebc09c36SJim Ingham             {
122ebc09c36SJim Ingham                 result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename);
123ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusFailed);
124ebc09c36SJim Ingham                 success = false;
125ebc09c36SJim Ingham             }
126ebc09c36SJim Ingham 
127ebc09c36SJim Ingham             if (success)
128ebc09c36SJim Ingham             {
129ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
130ebc09c36SJim Ingham             }
131ebc09c36SJim Ingham         }
132ebc09c36SJim Ingham         else
133ebc09c36SJim Ingham         {
134ebc09c36SJim Ingham             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
135ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
136ebc09c36SJim Ingham         }
137ebc09c36SJim Ingham         return result.Succeeded();
138ebc09c36SJim Ingham 
139ebc09c36SJim Ingham     }
140ebc09c36SJim Ingham };
141ebc09c36SJim Ingham 
142ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
143ebc09c36SJim Ingham //-------------------------------------------------------------------------
144ebc09c36SJim Ingham // CommandObjectCommandsAlias
145ebc09c36SJim Ingham //-------------------------------------------------------------------------
146ebc09c36SJim Ingham 
147ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject
148ebc09c36SJim Ingham {
149ebc09c36SJim Ingham public:
150a7015092SGreg Clayton     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
151a7015092SGreg Clayton         CommandObject (interpreter,
152a7015092SGreg Clayton                        "commands alias",
153e3d26315SCaroline Tice                        "Allow users to define their own debugger command abbreviations.",
154405fe67fSCaroline Tice                        NULL)
155ebc09c36SJim Ingham     {
156ebc09c36SJim Ingham         SetHelpLong(
157ebc09c36SJim Ingham     "'alias' allows the user to create a short-cut or abbreviation for long \n\
158ebc09c36SJim Ingham     commands, multi-word commands, and commands that take particular options. \n\
159ebc09c36SJim Ingham     Below are some simple examples of how one might use the 'alias' command: \n\
16009799af6SCaroline Tice     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
161ebc09c36SJim Ingham                                          // command. \n\
16209799af6SCaroline Tice     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
163ebc09c36SJim Ingham                                          // command.  Since breakpoint commands are two-word \n\
164ebc09c36SJim Ingham                                          // commands, the user will still need to enter the \n\
165ebc09c36SJim Ingham                                          // second word after 'bp', e.g. 'bp enable' or \n\
166ebc09c36SJim Ingham                                          // 'bp delete'. \n\
16709799af6SCaroline Tice     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
168ebc09c36SJim Ingham                                          // two-word command 'breakpoint list'. \n\
169ebc09c36SJim Ingham     \nAn alias can include some options for the command, with the values either \n\
170ebc09c36SJim Ingham     filled in at the time the alias is created, or specified as positional \n\
171ebc09c36SJim Ingham     arguments, to be filled in when the alias is invoked.  The following example \n\
172ebc09c36SJim Ingham     shows how to create aliases with options: \n\
173ebc09c36SJim Ingham     \n\
17409799af6SCaroline Tice     'commands alias bfl breakpoint set -f %1 -l %2' \n\
175ebc09c36SJim Ingham     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
176ebc09c36SJim Ingham     options already part of the alias.  So if the user wants to set a breakpoint \n\
177ebc09c36SJim Ingham     by file and line without explicitly having to use the -f and -l options, the \n\
178ebc09c36SJim Ingham     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
179ebc09c36SJim Ingham     for the actual arguments that will be passed when the alias command is used. \n\
180ebc09c36SJim Ingham     The number in the placeholder refers to the position/order the actual value \n\
181ebc09c36SJim Ingham     occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
182ebc09c36SJim Ingham     will be replaced with the first argument, all the occurrences of '%2' in the \n\
183ebc09c36SJim Ingham     alias will be replaced with the second argument, and so on.  This also allows \n\
184ebc09c36SJim Ingham     actual arguments to be used multiple times within an alias (see 'process \n\
185ebc09c36SJim Ingham     launch' example below).  So in the 'bfl' case, the actual file value will be \n\
186ebc09c36SJim Ingham     filled in with the first argument following 'bfl' and the actual line number \n\
187ebc09c36SJim Ingham     value will be filled in with the second argument.  The user would use this \n\
188ebc09c36SJim Ingham     alias as follows: \n\
18909799af6SCaroline Tice     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
190ebc09c36SJim Ingham     <... some time later ...> \n\
19109799af6SCaroline Tice     (lldb)  bfl my-file.c 137 \n\
192ebc09c36SJim Ingham     \nThis would be the same as if the user had entered \n\
193ebc09c36SJim Ingham     'breakpoint set -f my-file.c -l 137'. \n\
194ebc09c36SJim Ingham     \nAnother example: \n\
19509799af6SCaroline Tice     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
19609799af6SCaroline Tice     (lldb)  pltty /dev/tty0 \n\
197ebc09c36SJim Ingham            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
198ebc09c36SJim Ingham     \nIf the user always wanted to pass the same value to a particular option, the \n\
199ebc09c36SJim Ingham     alias could be defined with that value directly in the alias as a constant, \n\
200ebc09c36SJim Ingham     rather than using a positional placeholder: \n\
2010708e2c2SSean Callanan     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
202ebc09c36SJim Ingham                                                    // 3 of whatever file is indicated. \n");
203ebc09c36SJim Ingham 
204405fe67fSCaroline Tice         CommandArgumentEntry arg1;
205405fe67fSCaroline Tice         CommandArgumentEntry arg2;
206405fe67fSCaroline Tice         CommandArgumentEntry arg3;
207405fe67fSCaroline Tice         CommandArgumentData alias_arg;
208405fe67fSCaroline Tice         CommandArgumentData cmd_arg;
209405fe67fSCaroline Tice         CommandArgumentData options_arg;
210405fe67fSCaroline Tice 
211405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
212405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
213405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
214405fe67fSCaroline Tice 
215405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
216405fe67fSCaroline Tice         arg1.push_back (alias_arg);
217405fe67fSCaroline Tice 
218405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
219405fe67fSCaroline Tice         cmd_arg.arg_type = eArgTypeCommandName;
220405fe67fSCaroline Tice         cmd_arg.arg_repetition = eArgRepeatPlain;
221405fe67fSCaroline Tice 
222405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
223405fe67fSCaroline Tice         arg2.push_back (cmd_arg);
224405fe67fSCaroline Tice 
225405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
226405fe67fSCaroline Tice         options_arg.arg_type = eArgTypeAliasOptions;
227405fe67fSCaroline Tice         options_arg.arg_repetition = eArgRepeatOptional;
228405fe67fSCaroline Tice 
229405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
230405fe67fSCaroline Tice         arg3.push_back (options_arg);
231405fe67fSCaroline Tice 
232405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
233405fe67fSCaroline Tice         m_arguments.push_back (arg1);
234405fe67fSCaroline Tice         m_arguments.push_back (arg2);
235405fe67fSCaroline Tice         m_arguments.push_back (arg3);
236ebc09c36SJim Ingham     }
237ebc09c36SJim Ingham 
238ebc09c36SJim Ingham     ~CommandObjectCommandsAlias ()
239ebc09c36SJim Ingham     {
240ebc09c36SJim Ingham     }
241ebc09c36SJim Ingham 
242*844d2303SCaroline Tice     bool
243*844d2303SCaroline Tice     WantsRawCommandString ()
244*844d2303SCaroline Tice     {
245*844d2303SCaroline Tice         return true;
246*844d2303SCaroline Tice     }
247*844d2303SCaroline Tice 
248*844d2303SCaroline Tice     bool
249*844d2303SCaroline Tice     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
250*844d2303SCaroline Tice     {
251*844d2303SCaroline Tice         Args args (raw_command_line);
252*844d2303SCaroline Tice         std::string raw_command_string (raw_command_line);
253*844d2303SCaroline Tice 
254*844d2303SCaroline Tice         size_t argc = args.GetArgumentCount();
255*844d2303SCaroline Tice 
256*844d2303SCaroline Tice         if (argc < 2)
257*844d2303SCaroline Tice         {
258*844d2303SCaroline Tice             result.AppendError ("'alias' requires at least two arguments");
259*844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
260*844d2303SCaroline Tice             return false;
261*844d2303SCaroline Tice         }
262*844d2303SCaroline Tice 
263*844d2303SCaroline Tice         // Get the alias command.
264*844d2303SCaroline Tice 
265*844d2303SCaroline Tice         const std::string alias_command = args.GetArgumentAtIndex (0);
266*844d2303SCaroline Tice 
267*844d2303SCaroline Tice         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
268*844d2303SCaroline Tice         // does the stripping itself.
269*844d2303SCaroline Tice         size_t pos = raw_command_string.find (alias_command);
270*844d2303SCaroline Tice         if (pos == 0)
271*844d2303SCaroline Tice         {
272*844d2303SCaroline Tice             raw_command_string = raw_command_string.substr (alias_command.size());
273*844d2303SCaroline Tice             pos = raw_command_string.find_first_not_of (' ');
274*844d2303SCaroline Tice             if ((pos != std::string::npos) && (pos > 0))
275*844d2303SCaroline Tice                 raw_command_string = raw_command_string.substr (pos);
276*844d2303SCaroline Tice         }
277*844d2303SCaroline Tice         else
278*844d2303SCaroline Tice         {
279*844d2303SCaroline Tice             result.AppendError ("Error parsing command string.  No alias created.");
280*844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
281*844d2303SCaroline Tice             return false;
282*844d2303SCaroline Tice         }
283*844d2303SCaroline Tice 
284*844d2303SCaroline Tice 
285*844d2303SCaroline Tice         // Verify that the command is alias-able.
286*844d2303SCaroline Tice         if (m_interpreter.CommandExists (alias_command.c_str()))
287*844d2303SCaroline Tice         {
288*844d2303SCaroline Tice             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
289*844d2303SCaroline Tice                                           alias_command.c_str());
290*844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
291*844d2303SCaroline Tice             return false;
292*844d2303SCaroline Tice         }
293*844d2303SCaroline Tice 
294*844d2303SCaroline Tice         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
295*844d2303SCaroline Tice         // raw_command_string is returned with the name of the command object stripped off the front.
296*844d2303SCaroline Tice         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
297*844d2303SCaroline Tice 
298*844d2303SCaroline Tice         if (!cmd_obj)
299*844d2303SCaroline Tice         {
300*844d2303SCaroline Tice             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
301*844d2303SCaroline Tice                                           "  No alias created.", raw_command_string.c_str());
302*844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
303*844d2303SCaroline Tice             return false;
304*844d2303SCaroline Tice         }
305*844d2303SCaroline Tice         else if (!cmd_obj->WantsRawCommandString ())
306*844d2303SCaroline Tice         {
307*844d2303SCaroline Tice             // Note that args was initialized with the original command, and has not been updated to this point.
308*844d2303SCaroline Tice             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
309*844d2303SCaroline Tice             return Execute (args, result);
310*844d2303SCaroline Tice         }
311*844d2303SCaroline Tice         else
312*844d2303SCaroline Tice         {
313*844d2303SCaroline Tice             // Verify & handle any options/arguments passed to the alias command
314*844d2303SCaroline Tice 
315*844d2303SCaroline Tice             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
316*844d2303SCaroline Tice             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
317*844d2303SCaroline Tice 
318*844d2303SCaroline Tice             // Check to see if there's anything left in the input command string.
319*844d2303SCaroline Tice             if (raw_command_string.size() > 0)
320*844d2303SCaroline Tice             {
321*844d2303SCaroline Tice 
322*844d2303SCaroline Tice                 // Check to see if the command being aliased can take any command options.
323*844d2303SCaroline Tice                 Options *options = cmd_obj->GetOptions();
324*844d2303SCaroline Tice                 if (options)
325*844d2303SCaroline Tice                 {
326*844d2303SCaroline Tice                     // See if any options were specified as part of the alias; if so, handle them appropriately
327*844d2303SCaroline Tice                     options->ResetOptionValues ();
328*844d2303SCaroline Tice                     Args tmp_args (raw_command_string.c_str());
329*844d2303SCaroline Tice                     args.Unshift ("dummy_arg");
330*844d2303SCaroline Tice                     args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
331*844d2303SCaroline Tice                     args.Shift ();
332*844d2303SCaroline Tice                     if (result.Succeeded())
333*844d2303SCaroline Tice                         options->VerifyPartialOptions (result);
334*844d2303SCaroline Tice                     if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
335*844d2303SCaroline Tice                     {
336*844d2303SCaroline Tice                         result.AppendError ("Unable to create requested alias.\n");
337*844d2303SCaroline Tice                         return false;
338*844d2303SCaroline Tice                     }
339*844d2303SCaroline Tice                 }
340*844d2303SCaroline Tice                 // Anything remaining must be plain raw input.  Push it in as a single raw input argument.
341*844d2303SCaroline Tice                 if (raw_command_string.size() > 0)
342*844d2303SCaroline Tice                     option_arg_vector->push_back (OptionArgPair ("<argument>",
343*844d2303SCaroline Tice                                                                  OptionArgValue (-1,
344*844d2303SCaroline Tice                                                                                   raw_command_string)));
345*844d2303SCaroline Tice             }
346*844d2303SCaroline Tice 
347*844d2303SCaroline Tice             // Create the alias
348*844d2303SCaroline Tice             if (m_interpreter.AliasExists (alias_command.c_str())
349*844d2303SCaroline Tice                 || m_interpreter.UserCommandExists (alias_command.c_str()))
350*844d2303SCaroline Tice             {
351*844d2303SCaroline Tice                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
352*844d2303SCaroline Tice                 if (temp_option_arg_sp.get())
353*844d2303SCaroline Tice                 {
354*844d2303SCaroline Tice                     if (option_arg_vector->size() == 0)
355*844d2303SCaroline Tice                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
356*844d2303SCaroline Tice                 }
357*844d2303SCaroline Tice                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
358*844d2303SCaroline Tice                                                 alias_command.c_str());
359*844d2303SCaroline Tice             }
360*844d2303SCaroline Tice 
361*844d2303SCaroline Tice             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
362*844d2303SCaroline Tice             m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
363*844d2303SCaroline Tice             if (option_arg_vector->size() > 0)
364*844d2303SCaroline Tice                 m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
365*844d2303SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
366*844d2303SCaroline Tice         }
367*844d2303SCaroline Tice         return result.Succeeded();
368*844d2303SCaroline Tice     }
369ebc09c36SJim Ingham 
370ebc09c36SJim Ingham     bool
371ebc09c36SJim Ingham     Execute
372ebc09c36SJim Ingham     (
373ebc09c36SJim Ingham         Args& args,
374ebc09c36SJim Ingham         CommandReturnObject &result
375ebc09c36SJim Ingham     )
376ebc09c36SJim Ingham     {
377867b185dSCaroline Tice         size_t argc = args.GetArgumentCount();
378ebc09c36SJim Ingham 
379ebc09c36SJim Ingham         if (argc < 2)
380ebc09c36SJim Ingham         {
381ebc09c36SJim Ingham             result.AppendError ("'alias' requires at least two arguments");
382ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
383ebc09c36SJim Ingham             return false;
384ebc09c36SJim Ingham         }
385ebc09c36SJim Ingham 
386ebc09c36SJim Ingham         const std::string alias_command = args.GetArgumentAtIndex(0);
387ebc09c36SJim Ingham         const std::string actual_command = args.GetArgumentAtIndex(1);
388ebc09c36SJim Ingham 
389ebc09c36SJim Ingham         args.Shift();  // Shift the alias command word off the argument vector.
390ebc09c36SJim Ingham         args.Shift();  // Shift the old command word off the argument vector.
391ebc09c36SJim Ingham 
392ebc09c36SJim Ingham         // Verify that the command is alias'able, and get the appropriate command object.
393ebc09c36SJim Ingham 
394a7015092SGreg Clayton         if (m_interpreter.CommandExists (alias_command.c_str()))
395ebc09c36SJim Ingham         {
396ebc09c36SJim Ingham             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
397ebc09c36SJim Ingham                                          alias_command.c_str());
398ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
399ebc09c36SJim Ingham         }
400ebc09c36SJim Ingham         else
401ebc09c36SJim Ingham         {
402a7015092SGreg Clayton              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
403ebc09c36SJim Ingham              CommandObjectSP subcommand_obj_sp;
404ebc09c36SJim Ingham              bool use_subcommand = false;
405ebc09c36SJim Ingham              if (command_obj_sp.get())
406ebc09c36SJim Ingham              {
407ebc09c36SJim Ingham                  CommandObject *cmd_obj = command_obj_sp.get();
408c982c768SGreg Clayton                  CommandObject *sub_cmd_obj = NULL;
409ebc09c36SJim Ingham                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
410ebc09c36SJim Ingham                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
411ebc09c36SJim Ingham 
412*844d2303SCaroline Tice                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
413ebc09c36SJim Ingham                  {
414ebc09c36SJim Ingham                      if (argc >= 3)
415ebc09c36SJim Ingham                      {
416ebc09c36SJim Ingham                          const std::string sub_command = args.GetArgumentAtIndex(0);
417ebc09c36SJim Ingham                          assert (sub_command.length() != 0);
418ebc09c36SJim Ingham                          subcommand_obj_sp =
419ebc09c36SJim Ingham                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
420ebc09c36SJim Ingham                          if (subcommand_obj_sp.get())
421ebc09c36SJim Ingham                          {
422ebc09c36SJim Ingham                              sub_cmd_obj = subcommand_obj_sp.get();
423ebc09c36SJim Ingham                              use_subcommand = true;
424ebc09c36SJim Ingham                              args.Shift();  // Shift the sub_command word off the argument vector.
425*844d2303SCaroline Tice                              cmd_obj = sub_cmd_obj;
426ebc09c36SJim Ingham                          }
427ebc09c36SJim Ingham                          else
428ebc09c36SJim Ingham                          {
429f415eeb4SCaroline Tice                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
430f415eeb4SCaroline Tice                                                           "Unable to create alias.\n",
431f415eeb4SCaroline Tice                                                           sub_command.c_str(), actual_command.c_str());
432ebc09c36SJim Ingham                              result.SetStatus (eReturnStatusFailed);
433ebc09c36SJim Ingham                              return false;
434ebc09c36SJim Ingham                          }
435ebc09c36SJim Ingham                      }
436ebc09c36SJim Ingham                  }
437ebc09c36SJim Ingham 
438ebc09c36SJim Ingham                  // Verify & handle any options/arguments passed to the alias command
439ebc09c36SJim Ingham 
440ebc09c36SJim Ingham                  if (args.GetArgumentCount () > 0)
441ebc09c36SJim Ingham                  {
442ebc09c36SJim Ingham                      if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
443ebc09c36SJim Ingham                          || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
444ebc09c36SJim Ingham                      {
445ebc09c36SJim Ingham                          Options *options;
446ebc09c36SJim Ingham                          if (use_subcommand)
447ebc09c36SJim Ingham                              options = sub_cmd_obj->GetOptions();
448ebc09c36SJim Ingham                          else
449ebc09c36SJim Ingham                              options = cmd_obj->GetOptions();
450ebc09c36SJim Ingham                          options->ResetOptionValues ();
451*844d2303SCaroline Tice                          std::string empty_string;
452ebc09c36SJim Ingham                          args.Unshift ("dummy_arg");
453*844d2303SCaroline Tice                          args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
454ebc09c36SJim Ingham                          args.Shift ();
455ebc09c36SJim Ingham                          if (result.Succeeded())
456ebc09c36SJim Ingham                              options->VerifyPartialOptions (result);
457867b185dSCaroline Tice                          if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
458ebc09c36SJim Ingham                         {
459867b185dSCaroline Tice                             result.AppendError ("Unable to create requested command alias.\n");
460e7941795SCaroline Tice                             return false;
461867b185dSCaroline Tice                         }
462867b185dSCaroline Tice                      }
463867b185dSCaroline Tice 
464867b185dSCaroline Tice                      // Anything remaining in args must be a plain argument.
465867b185dSCaroline Tice 
466867b185dSCaroline Tice                      argc = args.GetArgumentCount();
467c982c768SGreg Clayton                      for (size_t i = 0; i < argc; ++i)
468636d6ed0SCaroline Tice                          if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
469d9d63369SCaroline Tice                              option_arg_vector->push_back
470d9d63369SCaroline Tice                                            (OptionArgPair ("<argument>",
471d9d63369SCaroline Tice                                                            OptionArgValue (-1,
472d9d63369SCaroline Tice                                                                            std::string (args.GetArgumentAtIndex (i)))));
473ebc09c36SJim Ingham                  }
474ebc09c36SJim Ingham 
475ebc09c36SJim Ingham                  // Create the alias.
476ebc09c36SJim Ingham 
477a7015092SGreg Clayton                  if (m_interpreter.AliasExists (alias_command.c_str())
478a7015092SGreg Clayton                      || m_interpreter.UserCommandExists (alias_command.c_str()))
479ebc09c36SJim Ingham                  {
480a7015092SGreg Clayton                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
481ebc09c36SJim Ingham                      if (tmp_option_arg_sp.get())
482ebc09c36SJim Ingham                      {
483ebc09c36SJim Ingham                          if (option_arg_vector->size() == 0)
484a7015092SGreg Clayton                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
485ebc09c36SJim Ingham                      }
486ebc09c36SJim Ingham                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
487ebc09c36SJim Ingham                                                      alias_command.c_str());
488ebc09c36SJim Ingham                  }
489ebc09c36SJim Ingham 
490ebc09c36SJim Ingham                  if (use_subcommand)
491a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
492ebc09c36SJim Ingham                  else
493a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
494ebc09c36SJim Ingham                  if (option_arg_vector->size() > 0)
495a7015092SGreg Clayton                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
496ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
497ebc09c36SJim Ingham              }
498ebc09c36SJim Ingham              else
499ebc09c36SJim Ingham              {
500ebc09c36SJim Ingham                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
501ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusFailed);
502e7941795SCaroline Tice                  return false;
503ebc09c36SJim Ingham              }
504ebc09c36SJim Ingham         }
505ebc09c36SJim Ingham 
506ebc09c36SJim Ingham         return result.Succeeded();
507ebc09c36SJim Ingham     }
508ebc09c36SJim Ingham };
509ebc09c36SJim Ingham 
510ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
511ebc09c36SJim Ingham //-------------------------------------------------------------------------
512ebc09c36SJim Ingham // CommandObjectCommandsUnalias
513ebc09c36SJim Ingham //-------------------------------------------------------------------------
514ebc09c36SJim Ingham 
515ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject
516ebc09c36SJim Ingham {
517ebc09c36SJim Ingham public:
518a7015092SGreg Clayton     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
519a7015092SGreg Clayton         CommandObject (interpreter,
520a7015092SGreg Clayton                        "commands unalias",
52186ddae50SCaroline Tice                        "Allow the user to remove/delete a user-defined command abbreviation.",
522405fe67fSCaroline Tice                        NULL)
523ebc09c36SJim Ingham     {
524405fe67fSCaroline Tice         CommandArgumentEntry arg;
525405fe67fSCaroline Tice         CommandArgumentData alias_arg;
526405fe67fSCaroline Tice 
527405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
528405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
529405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
530405fe67fSCaroline Tice 
531405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
532405fe67fSCaroline Tice         arg.push_back (alias_arg);
533405fe67fSCaroline Tice 
534405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
535405fe67fSCaroline Tice         m_arguments.push_back (arg);
536ebc09c36SJim Ingham     }
537ebc09c36SJim Ingham 
538ebc09c36SJim Ingham     ~CommandObjectCommandsUnalias()
539ebc09c36SJim Ingham     {
540ebc09c36SJim Ingham     }
541ebc09c36SJim Ingham 
542ebc09c36SJim Ingham 
543ebc09c36SJim Ingham     bool
544ebc09c36SJim Ingham     Execute
545ebc09c36SJim Ingham     (
546ebc09c36SJim Ingham         Args& args,
547ebc09c36SJim Ingham         CommandReturnObject &result
548ebc09c36SJim Ingham     )
549ebc09c36SJim Ingham     {
550ebc09c36SJim Ingham         CommandObject::CommandMap::iterator pos;
551ebc09c36SJim Ingham         CommandObject *cmd_obj;
552ebc09c36SJim Ingham 
553ebc09c36SJim Ingham         if (args.GetArgumentCount() != 0)
554ebc09c36SJim Ingham         {
555ebc09c36SJim Ingham             const char *command_name = args.GetArgumentAtIndex(0);
556a7015092SGreg Clayton             cmd_obj = m_interpreter.GetCommandObject(command_name);
557ebc09c36SJim Ingham             if (cmd_obj)
558ebc09c36SJim Ingham             {
559a7015092SGreg Clayton                 if (m_interpreter.CommandExists (command_name))
560ebc09c36SJim Ingham                 {
561ebc09c36SJim Ingham                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
562ebc09c36SJim Ingham                                                   command_name);
563ebc09c36SJim Ingham                     result.SetStatus (eReturnStatusFailed);
564ebc09c36SJim Ingham                 }
565ebc09c36SJim Ingham                 else
566ebc09c36SJim Ingham                 {
567ebc09c36SJim Ingham 
568a7015092SGreg Clayton                     if (m_interpreter.RemoveAlias (command_name) == false)
569ebc09c36SJim Ingham                     {
570a7015092SGreg Clayton                         if (m_interpreter.AliasExists (command_name))
571ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
572ebc09c36SJim Ingham                                                           command_name);
573ebc09c36SJim Ingham                         else
574ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
575ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusFailed);
576ebc09c36SJim Ingham                     }
577ebc09c36SJim Ingham                     else
578ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
579ebc09c36SJim Ingham                 }
580ebc09c36SJim Ingham             }
581ebc09c36SJim Ingham             else
582ebc09c36SJim Ingham             {
583ebc09c36SJim Ingham                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
584ebc09c36SJim Ingham                                               "current list of commands.\n",
585ebc09c36SJim Ingham                                              command_name);
586ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusFailed);
587ebc09c36SJim Ingham             }
588ebc09c36SJim Ingham         }
589ebc09c36SJim Ingham         else
590ebc09c36SJim Ingham         {
591ebc09c36SJim Ingham             result.AppendError ("must call 'unalias' with a valid alias");
592ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
593ebc09c36SJim Ingham         }
594ebc09c36SJim Ingham 
595ebc09c36SJim Ingham         return result.Succeeded();
596ebc09c36SJim Ingham     }
597ebc09c36SJim Ingham };
598ebc09c36SJim Ingham 
599ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
600ebc09c36SJim Ingham 
601ebc09c36SJim Ingham //-------------------------------------------------------------------------
602ebc09c36SJim Ingham // CommandObjectMultiwordCommands
603ebc09c36SJim Ingham //-------------------------------------------------------------------------
604ebc09c36SJim Ingham 
605ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
606a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
607a7015092SGreg Clayton                             "commands",
6083f4c09c1SCaroline Tice                             "A set of commands for managing or customizing the debugger commands.",
609ebc09c36SJim Ingham                             "commands <subcommand> [<subcommand-options>]")
610ebc09c36SJim Ingham {
611a7015092SGreg Clayton     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
612a7015092SGreg Clayton     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
613a7015092SGreg Clayton     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
614ebc09c36SJim Ingham }
615ebc09c36SJim Ingham 
616ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
617ebc09c36SJim Ingham {
618ebc09c36SJim Ingham }
619ebc09c36SJim Ingham 
620