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 //-------------------------------------------------------------------------
26ebc09c36SJim Ingham // CommandObjectCommandsSource
27ebc09c36SJim Ingham //-------------------------------------------------------------------------
28ebc09c36SJim Ingham 
29ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject
30ebc09c36SJim Ingham {
31e16c50a1SJim Ingham private:
32e16c50a1SJim Ingham 
33e16c50a1SJim Ingham     class CommandOptions : public Options
34e16c50a1SJim Ingham     {
35e16c50a1SJim Ingham     public:
36e16c50a1SJim Ingham 
37*eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
38*eb0103f2SGreg Clayton             Options (interpreter)
39*eb0103f2SGreg Clayton         {
40*eb0103f2SGreg Clayton         }
41e16c50a1SJim Ingham 
42e16c50a1SJim Ingham         virtual
43e16c50a1SJim Ingham         ~CommandOptions (){}
44e16c50a1SJim Ingham 
45e16c50a1SJim Ingham         virtual Error
46e16c50a1SJim Ingham         SetOptionValue (int option_idx, const char *option_arg)
47e16c50a1SJim Ingham         {
48e16c50a1SJim Ingham             Error error;
49e16c50a1SJim Ingham             char short_option = (char) m_getopt_table[option_idx].val;
50e16c50a1SJim Ingham             bool success;
51e16c50a1SJim Ingham 
52e16c50a1SJim Ingham             switch (short_option)
53e16c50a1SJim Ingham             {
54e16c50a1SJim Ingham                 case 'e':
55e16c50a1SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
56e16c50a1SJim Ingham                     if (!success)
57e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
58e16c50a1SJim Ingham                     break;
59e16c50a1SJim Ingham                 case 'c':
60e16c50a1SJim Ingham                     m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
61e16c50a1SJim Ingham                     if (!success)
62e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
63e16c50a1SJim Ingham                     break;
64e16c50a1SJim Ingham                 default:
65e16c50a1SJim Ingham                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
66e16c50a1SJim Ingham                     break;
67e16c50a1SJim Ingham             }
68e16c50a1SJim Ingham 
69e16c50a1SJim Ingham             return error;
70e16c50a1SJim Ingham         }
71e16c50a1SJim Ingham 
72e16c50a1SJim Ingham         void
73e16c50a1SJim Ingham         ResetOptionValues ()
74e16c50a1SJim Ingham         {
75e16c50a1SJim Ingham             m_stop_on_error = true;
76e16c50a1SJim Ingham             m_stop_on_continue = true;
77e16c50a1SJim Ingham         }
78e16c50a1SJim Ingham 
79e0d378b3SGreg Clayton         const OptionDefinition*
80e16c50a1SJim Ingham         GetDefinitions ()
81e16c50a1SJim Ingham         {
82e16c50a1SJim Ingham             return g_option_table;
83e16c50a1SJim Ingham         }
84e16c50a1SJim Ingham 
85e16c50a1SJim Ingham         // Options table: Required for subclasses of Options.
86e16c50a1SJim Ingham 
87e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
88e16c50a1SJim Ingham 
89e16c50a1SJim Ingham         // Instance variables to hold the values for command options.
90e16c50a1SJim Ingham 
91e16c50a1SJim Ingham         bool m_stop_on_error;
92e16c50a1SJim Ingham         bool m_stop_on_continue;
93e16c50a1SJim Ingham     };
94e16c50a1SJim Ingham 
95e16c50a1SJim Ingham     // Options table: Required for subclasses of Options.
96e16c50a1SJim Ingham 
97e0d378b3SGreg Clayton     static OptionDefinition g_option_table[];
98e16c50a1SJim Ingham 
99e16c50a1SJim Ingham     CommandOptions m_options;
100e16c50a1SJim Ingham 
101e16c50a1SJim Ingham     virtual Options *
102e16c50a1SJim Ingham     GetOptions ()
103e16c50a1SJim Ingham     {
104e16c50a1SJim Ingham         return &m_options;
105e16c50a1SJim Ingham     }
106e16c50a1SJim Ingham 
107ebc09c36SJim Ingham public:
108a7015092SGreg Clayton     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
109a7015092SGreg Clayton         CommandObject (interpreter,
110a7015092SGreg Clayton                        "commands source",
111e3d26315SCaroline Tice                        "Read in debugger commands from the file <filename> and execute them.",
112*eb0103f2SGreg Clayton                        NULL),
113*eb0103f2SGreg Clayton         m_options (interpreter)
114ebc09c36SJim Ingham     {
115405fe67fSCaroline Tice         CommandArgumentEntry arg;
116405fe67fSCaroline Tice         CommandArgumentData file_arg;
117405fe67fSCaroline Tice 
118405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
119405fe67fSCaroline Tice         file_arg.arg_type = eArgTypeFilename;
120405fe67fSCaroline Tice         file_arg.arg_repetition = eArgRepeatPlain;
121405fe67fSCaroline Tice 
122405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
123405fe67fSCaroline Tice         arg.push_back (file_arg);
124405fe67fSCaroline Tice 
125405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
126405fe67fSCaroline Tice         m_arguments.push_back (arg);
127ebc09c36SJim Ingham     }
128ebc09c36SJim Ingham 
129ebc09c36SJim Ingham     ~CommandObjectCommandsSource ()
130ebc09c36SJim Ingham     {
131ebc09c36SJim Ingham     }
132ebc09c36SJim Ingham 
133ebc09c36SJim Ingham     bool
134ebc09c36SJim Ingham     Execute
135ebc09c36SJim Ingham     (
136ebc09c36SJim Ingham         Args& args,
137ebc09c36SJim Ingham         CommandReturnObject &result
138ebc09c36SJim Ingham     )
139ebc09c36SJim Ingham     {
140ebc09c36SJim Ingham         const int argc = args.GetArgumentCount();
141ebc09c36SJim Ingham         if (argc == 1)
142ebc09c36SJim Ingham         {
143ebc09c36SJim Ingham             const char *filename = args.GetArgumentAtIndex(0);
144ebc09c36SJim Ingham 
145ebc09c36SJim Ingham             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
146ebc09c36SJim Ingham 
1471ee3853fSJohnny Chen             FileSpec cmd_file (filename, true);
148e16c50a1SJim Ingham             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
149e16c50a1SJim Ingham             bool echo_commands    = true;
150e16c50a1SJim Ingham             bool print_results    = true;
151ebc09c36SJim Ingham 
152e16c50a1SJim Ingham             m_interpreter.HandleCommandsFromFile (cmd_file,
153e16c50a1SJim Ingham                                                   exe_ctx,
154e16c50a1SJim Ingham                                                   m_options.m_stop_on_continue,
155e16c50a1SJim Ingham                                                   m_options.m_stop_on_error,
156e16c50a1SJim Ingham                                                   echo_commands,
157e16c50a1SJim Ingham                                                   print_results,
158e16c50a1SJim Ingham                                                   result);
159ebc09c36SJim Ingham         }
160ebc09c36SJim Ingham         else
161ebc09c36SJim Ingham         {
162ebc09c36SJim Ingham             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
163ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
164ebc09c36SJim Ingham         }
165ebc09c36SJim Ingham         return result.Succeeded();
166ebc09c36SJim Ingham 
167ebc09c36SJim Ingham     }
168ebc09c36SJim Ingham };
169ebc09c36SJim Ingham 
170e0d378b3SGreg Clayton OptionDefinition
171e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] =
172e16c50a1SJim Ingham {
173e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
174e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
175e16c50a1SJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
176e16c50a1SJim Ingham };
177e16c50a1SJim Ingham 
178ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
179ebc09c36SJim Ingham //-------------------------------------------------------------------------
180ebc09c36SJim Ingham // CommandObjectCommandsAlias
181ebc09c36SJim Ingham //-------------------------------------------------------------------------
182ebc09c36SJim Ingham 
183ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject
184ebc09c36SJim Ingham {
185ebc09c36SJim Ingham public:
186a7015092SGreg Clayton     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
187a7015092SGreg Clayton         CommandObject (interpreter,
188a7015092SGreg Clayton                        "commands alias",
189e3d26315SCaroline Tice                        "Allow users to define their own debugger command abbreviations.",
190405fe67fSCaroline Tice                        NULL)
191ebc09c36SJim Ingham     {
192ebc09c36SJim Ingham         SetHelpLong(
193ebc09c36SJim Ingham     "'alias' allows the user to create a short-cut or abbreviation for long \n\
194ebc09c36SJim Ingham     commands, multi-word commands, and commands that take particular options. \n\
195ebc09c36SJim Ingham     Below are some simple examples of how one might use the 'alias' command: \n\
19609799af6SCaroline Tice     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
197ebc09c36SJim Ingham                                          // command. \n\
19809799af6SCaroline Tice     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
199ebc09c36SJim Ingham                                          // command.  Since breakpoint commands are two-word \n\
200ebc09c36SJim Ingham                                          // commands, the user will still need to enter the \n\
201ebc09c36SJim Ingham                                          // second word after 'bp', e.g. 'bp enable' or \n\
202ebc09c36SJim Ingham                                          // 'bp delete'. \n\
20309799af6SCaroline Tice     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
204ebc09c36SJim Ingham                                          // two-word command 'breakpoint list'. \n\
205ebc09c36SJim Ingham     \nAn alias can include some options for the command, with the values either \n\
206ebc09c36SJim Ingham     filled in at the time the alias is created, or specified as positional \n\
207ebc09c36SJim Ingham     arguments, to be filled in when the alias is invoked.  The following example \n\
208ebc09c36SJim Ingham     shows how to create aliases with options: \n\
209ebc09c36SJim Ingham     \n\
21009799af6SCaroline Tice     'commands alias bfl breakpoint set -f %1 -l %2' \n\
211ebc09c36SJim Ingham     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
212ebc09c36SJim Ingham     options already part of the alias.  So if the user wants to set a breakpoint \n\
213ebc09c36SJim Ingham     by file and line without explicitly having to use the -f and -l options, the \n\
214ebc09c36SJim Ingham     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
215ebc09c36SJim Ingham     for the actual arguments that will be passed when the alias command is used. \n\
216ebc09c36SJim Ingham     The number in the placeholder refers to the position/order the actual value \n\
217ebc09c36SJim Ingham     occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
218ebc09c36SJim Ingham     will be replaced with the first argument, all the occurrences of '%2' in the \n\
219ebc09c36SJim Ingham     alias will be replaced with the second argument, and so on.  This also allows \n\
220ebc09c36SJim Ingham     actual arguments to be used multiple times within an alias (see 'process \n\
221ebc09c36SJim Ingham     launch' example below).  So in the 'bfl' case, the actual file value will be \n\
222ebc09c36SJim Ingham     filled in with the first argument following 'bfl' and the actual line number \n\
223ebc09c36SJim Ingham     value will be filled in with the second argument.  The user would use this \n\
224ebc09c36SJim Ingham     alias as follows: \n\
22509799af6SCaroline Tice     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
226ebc09c36SJim Ingham     <... some time later ...> \n\
22709799af6SCaroline Tice     (lldb)  bfl my-file.c 137 \n\
228ebc09c36SJim Ingham     \nThis would be the same as if the user had entered \n\
229ebc09c36SJim Ingham     'breakpoint set -f my-file.c -l 137'. \n\
230ebc09c36SJim Ingham     \nAnother example: \n\
23109799af6SCaroline Tice     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
23209799af6SCaroline Tice     (lldb)  pltty /dev/tty0 \n\
233ebc09c36SJim Ingham            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
234ebc09c36SJim Ingham     \nIf the user always wanted to pass the same value to a particular option, the \n\
235ebc09c36SJim Ingham     alias could be defined with that value directly in the alias as a constant, \n\
236ebc09c36SJim Ingham     rather than using a positional placeholder: \n\
2370708e2c2SSean Callanan     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
238ebc09c36SJim Ingham                                                    // 3 of whatever file is indicated. \n");
239ebc09c36SJim Ingham 
240405fe67fSCaroline Tice         CommandArgumentEntry arg1;
241405fe67fSCaroline Tice         CommandArgumentEntry arg2;
242405fe67fSCaroline Tice         CommandArgumentEntry arg3;
243405fe67fSCaroline Tice         CommandArgumentData alias_arg;
244405fe67fSCaroline Tice         CommandArgumentData cmd_arg;
245405fe67fSCaroline Tice         CommandArgumentData options_arg;
246405fe67fSCaroline Tice 
247405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
248405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
249405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
250405fe67fSCaroline Tice 
251405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
252405fe67fSCaroline Tice         arg1.push_back (alias_arg);
253405fe67fSCaroline Tice 
254405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
255405fe67fSCaroline Tice         cmd_arg.arg_type = eArgTypeCommandName;
256405fe67fSCaroline Tice         cmd_arg.arg_repetition = eArgRepeatPlain;
257405fe67fSCaroline Tice 
258405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
259405fe67fSCaroline Tice         arg2.push_back (cmd_arg);
260405fe67fSCaroline Tice 
261405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
262405fe67fSCaroline Tice         options_arg.arg_type = eArgTypeAliasOptions;
263405fe67fSCaroline Tice         options_arg.arg_repetition = eArgRepeatOptional;
264405fe67fSCaroline Tice 
265405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
266405fe67fSCaroline Tice         arg3.push_back (options_arg);
267405fe67fSCaroline Tice 
268405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
269405fe67fSCaroline Tice         m_arguments.push_back (arg1);
270405fe67fSCaroline Tice         m_arguments.push_back (arg2);
271405fe67fSCaroline Tice         m_arguments.push_back (arg3);
272ebc09c36SJim Ingham     }
273ebc09c36SJim Ingham 
274ebc09c36SJim Ingham     ~CommandObjectCommandsAlias ()
275ebc09c36SJim Ingham     {
276ebc09c36SJim Ingham     }
277ebc09c36SJim Ingham 
278844d2303SCaroline Tice     bool
279844d2303SCaroline Tice     WantsRawCommandString ()
280844d2303SCaroline Tice     {
281844d2303SCaroline Tice         return true;
282844d2303SCaroline Tice     }
283844d2303SCaroline Tice 
284844d2303SCaroline Tice     bool
285844d2303SCaroline Tice     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
286844d2303SCaroline Tice     {
287844d2303SCaroline Tice         Args args (raw_command_line);
288844d2303SCaroline Tice         std::string raw_command_string (raw_command_line);
289844d2303SCaroline Tice 
290844d2303SCaroline Tice         size_t argc = args.GetArgumentCount();
291844d2303SCaroline Tice 
292844d2303SCaroline Tice         if (argc < 2)
293844d2303SCaroline Tice         {
294844d2303SCaroline Tice             result.AppendError ("'alias' requires at least two arguments");
295844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
296844d2303SCaroline Tice             return false;
297844d2303SCaroline Tice         }
298844d2303SCaroline Tice 
299844d2303SCaroline Tice         // Get the alias command.
300844d2303SCaroline Tice 
301844d2303SCaroline Tice         const std::string alias_command = args.GetArgumentAtIndex (0);
302844d2303SCaroline Tice 
303844d2303SCaroline Tice         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
304844d2303SCaroline Tice         // does the stripping itself.
305844d2303SCaroline Tice         size_t pos = raw_command_string.find (alias_command);
306844d2303SCaroline Tice         if (pos == 0)
307844d2303SCaroline Tice         {
308844d2303SCaroline Tice             raw_command_string = raw_command_string.substr (alias_command.size());
309844d2303SCaroline Tice             pos = raw_command_string.find_first_not_of (' ');
310844d2303SCaroline Tice             if ((pos != std::string::npos) && (pos > 0))
311844d2303SCaroline Tice                 raw_command_string = raw_command_string.substr (pos);
312844d2303SCaroline Tice         }
313844d2303SCaroline Tice         else
314844d2303SCaroline Tice         {
315844d2303SCaroline Tice             result.AppendError ("Error parsing command string.  No alias created.");
316844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
317844d2303SCaroline Tice             return false;
318844d2303SCaroline Tice         }
319844d2303SCaroline Tice 
320844d2303SCaroline Tice 
321844d2303SCaroline Tice         // Verify that the command is alias-able.
322844d2303SCaroline Tice         if (m_interpreter.CommandExists (alias_command.c_str()))
323844d2303SCaroline Tice         {
324844d2303SCaroline Tice             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
325844d2303SCaroline Tice                                           alias_command.c_str());
326844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
327844d2303SCaroline Tice             return false;
328844d2303SCaroline Tice         }
329844d2303SCaroline Tice 
330844d2303SCaroline Tice         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
331844d2303SCaroline Tice         // raw_command_string is returned with the name of the command object stripped off the front.
332844d2303SCaroline Tice         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
333844d2303SCaroline Tice 
334844d2303SCaroline Tice         if (!cmd_obj)
335844d2303SCaroline Tice         {
336844d2303SCaroline Tice             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
337844d2303SCaroline Tice                                           "  No alias created.", raw_command_string.c_str());
338844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
339844d2303SCaroline Tice             return false;
340844d2303SCaroline Tice         }
341844d2303SCaroline Tice         else if (!cmd_obj->WantsRawCommandString ())
342844d2303SCaroline Tice         {
343844d2303SCaroline Tice             // Note that args was initialized with the original command, and has not been updated to this point.
344844d2303SCaroline Tice             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
345844d2303SCaroline Tice             return Execute (args, result);
346844d2303SCaroline Tice         }
347844d2303SCaroline Tice         else
348844d2303SCaroline Tice         {
349844d2303SCaroline Tice             // Verify & handle any options/arguments passed to the alias command
350844d2303SCaroline Tice 
351844d2303SCaroline Tice             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
352844d2303SCaroline Tice             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
353844d2303SCaroline Tice 
354844d2303SCaroline Tice             // Check to see if there's anything left in the input command string.
355844d2303SCaroline Tice             if (raw_command_string.size() > 0)
356844d2303SCaroline Tice             {
357844d2303SCaroline Tice 
358844d2303SCaroline Tice                 // Check to see if the command being aliased can take any command options.
359844d2303SCaroline Tice                 Options *options = cmd_obj->GetOptions();
360844d2303SCaroline Tice                 if (options)
361844d2303SCaroline Tice                 {
362844d2303SCaroline Tice                     // See if any options were specified as part of the alias; if so, handle them appropriately
36332e0a750SGreg Clayton                     options->Reset ();
364844d2303SCaroline Tice                     Args tmp_args (raw_command_string.c_str());
365844d2303SCaroline Tice                     args.Unshift ("dummy_arg");
366844d2303SCaroline Tice                     args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
367844d2303SCaroline Tice                     args.Shift ();
368844d2303SCaroline Tice                     if (result.Succeeded())
369844d2303SCaroline Tice                         options->VerifyPartialOptions (result);
370844d2303SCaroline Tice                     if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
371844d2303SCaroline Tice                     {
372844d2303SCaroline Tice                         result.AppendError ("Unable to create requested alias.\n");
373844d2303SCaroline Tice                         return false;
374844d2303SCaroline Tice                     }
375844d2303SCaroline Tice                 }
376844d2303SCaroline Tice                 // Anything remaining must be plain raw input.  Push it in as a single raw input argument.
377844d2303SCaroline Tice                 if (raw_command_string.size() > 0)
378844d2303SCaroline Tice                     option_arg_vector->push_back (OptionArgPair ("<argument>",
379844d2303SCaroline Tice                                                                  OptionArgValue (-1,
380844d2303SCaroline Tice                                                                                   raw_command_string)));
381844d2303SCaroline Tice             }
382844d2303SCaroline Tice 
383844d2303SCaroline Tice             // Create the alias
384844d2303SCaroline Tice             if (m_interpreter.AliasExists (alias_command.c_str())
385844d2303SCaroline Tice                 || m_interpreter.UserCommandExists (alias_command.c_str()))
386844d2303SCaroline Tice             {
387844d2303SCaroline Tice                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
388844d2303SCaroline Tice                 if (temp_option_arg_sp.get())
389844d2303SCaroline Tice                 {
390844d2303SCaroline Tice                     if (option_arg_vector->size() == 0)
391844d2303SCaroline Tice                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
392844d2303SCaroline Tice                 }
393844d2303SCaroline Tice                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
394844d2303SCaroline Tice                                                 alias_command.c_str());
395844d2303SCaroline Tice             }
396844d2303SCaroline Tice 
397844d2303SCaroline Tice             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
398472362e6SCaroline Tice             if (cmd_obj_sp)
399472362e6SCaroline Tice             {
400844d2303SCaroline Tice                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
401844d2303SCaroline Tice                 if (option_arg_vector->size() > 0)
402844d2303SCaroline Tice                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
403844d2303SCaroline Tice                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
404844d2303SCaroline Tice             }
405472362e6SCaroline Tice             else
406472362e6SCaroline Tice             {
407472362e6SCaroline Tice                 result.AppendError ("Unable to create requested alias.\n");
408472362e6SCaroline Tice                 result.SetStatus (eReturnStatusFailed);
409472362e6SCaroline Tice             }
410472362e6SCaroline Tice         }
411844d2303SCaroline Tice         return result.Succeeded();
412844d2303SCaroline Tice     }
413ebc09c36SJim Ingham 
414ebc09c36SJim Ingham     bool
415ebc09c36SJim Ingham     Execute
416ebc09c36SJim Ingham     (
417ebc09c36SJim Ingham         Args& args,
418ebc09c36SJim Ingham         CommandReturnObject &result
419ebc09c36SJim Ingham     )
420ebc09c36SJim Ingham     {
421867b185dSCaroline Tice         size_t argc = args.GetArgumentCount();
422ebc09c36SJim Ingham 
423ebc09c36SJim Ingham         if (argc < 2)
424ebc09c36SJim Ingham         {
425ebc09c36SJim Ingham             result.AppendError ("'alias' requires at least two arguments");
426ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
427ebc09c36SJim Ingham             return false;
428ebc09c36SJim Ingham         }
429ebc09c36SJim Ingham 
430ebc09c36SJim Ingham         const std::string alias_command = args.GetArgumentAtIndex(0);
431ebc09c36SJim Ingham         const std::string actual_command = args.GetArgumentAtIndex(1);
432ebc09c36SJim Ingham 
433ebc09c36SJim Ingham         args.Shift();  // Shift the alias command word off the argument vector.
434ebc09c36SJim Ingham         args.Shift();  // Shift the old command word off the argument vector.
435ebc09c36SJim Ingham 
436ebc09c36SJim Ingham         // Verify that the command is alias'able, and get the appropriate command object.
437ebc09c36SJim Ingham 
438a7015092SGreg Clayton         if (m_interpreter.CommandExists (alias_command.c_str()))
439ebc09c36SJim Ingham         {
440ebc09c36SJim Ingham             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
441ebc09c36SJim Ingham                                          alias_command.c_str());
442ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
443ebc09c36SJim Ingham         }
444ebc09c36SJim Ingham         else
445ebc09c36SJim Ingham         {
446a7015092SGreg Clayton              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
447ebc09c36SJim Ingham              CommandObjectSP subcommand_obj_sp;
448ebc09c36SJim Ingham              bool use_subcommand = false;
449ebc09c36SJim Ingham              if (command_obj_sp.get())
450ebc09c36SJim Ingham              {
451ebc09c36SJim Ingham                  CommandObject *cmd_obj = command_obj_sp.get();
452c982c768SGreg Clayton                  CommandObject *sub_cmd_obj = NULL;
453ebc09c36SJim Ingham                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
454ebc09c36SJim Ingham                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
455ebc09c36SJim Ingham 
456844d2303SCaroline Tice                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
457ebc09c36SJim Ingham                  {
458ebc09c36SJim Ingham                      if (argc >= 3)
459ebc09c36SJim Ingham                      {
460ebc09c36SJim Ingham                          const std::string sub_command = args.GetArgumentAtIndex(0);
461ebc09c36SJim Ingham                          assert (sub_command.length() != 0);
462ebc09c36SJim Ingham                          subcommand_obj_sp =
463ebc09c36SJim Ingham                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
464ebc09c36SJim Ingham                          if (subcommand_obj_sp.get())
465ebc09c36SJim Ingham                          {
466ebc09c36SJim Ingham                              sub_cmd_obj = subcommand_obj_sp.get();
467ebc09c36SJim Ingham                              use_subcommand = true;
468ebc09c36SJim Ingham                              args.Shift();  // Shift the sub_command word off the argument vector.
469844d2303SCaroline Tice                              cmd_obj = sub_cmd_obj;
470ebc09c36SJim Ingham                          }
471ebc09c36SJim Ingham                          else
472ebc09c36SJim Ingham                          {
473f415eeb4SCaroline Tice                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
474f415eeb4SCaroline Tice                                                           "Unable to create alias.\n",
475f415eeb4SCaroline Tice                                                           sub_command.c_str(), actual_command.c_str());
476ebc09c36SJim Ingham                              result.SetStatus (eReturnStatusFailed);
477ebc09c36SJim Ingham                              return false;
478ebc09c36SJim Ingham                          }
479ebc09c36SJim Ingham                      }
480ebc09c36SJim Ingham                  }
481ebc09c36SJim Ingham 
482ebc09c36SJim Ingham                  // Verify & handle any options/arguments passed to the alias command
483ebc09c36SJim Ingham 
484ebc09c36SJim Ingham                  if (args.GetArgumentCount () > 0)
485ebc09c36SJim Ingham                  {
486ebc09c36SJim Ingham                      if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
487ebc09c36SJim Ingham                          || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
488ebc09c36SJim Ingham                      {
489ebc09c36SJim Ingham                          Options *options;
490ebc09c36SJim Ingham                          if (use_subcommand)
491ebc09c36SJim Ingham                              options = sub_cmd_obj->GetOptions();
492ebc09c36SJim Ingham                          else
493ebc09c36SJim Ingham                              options = cmd_obj->GetOptions();
49432e0a750SGreg Clayton                          options->Reset ();
495844d2303SCaroline Tice                          std::string empty_string;
496ebc09c36SJim Ingham                          args.Unshift ("dummy_arg");
497844d2303SCaroline Tice                          args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
498ebc09c36SJim Ingham                          args.Shift ();
499ebc09c36SJim Ingham                          if (result.Succeeded())
500ebc09c36SJim Ingham                              options->VerifyPartialOptions (result);
501867b185dSCaroline Tice                          if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
502ebc09c36SJim Ingham                         {
503867b185dSCaroline Tice                             result.AppendError ("Unable to create requested command alias.\n");
504e7941795SCaroline Tice                             return false;
505867b185dSCaroline Tice                         }
506867b185dSCaroline Tice                      }
507867b185dSCaroline Tice 
508867b185dSCaroline Tice                      // Anything remaining in args must be a plain argument.
509867b185dSCaroline Tice 
510867b185dSCaroline Tice                      argc = args.GetArgumentCount();
511c982c768SGreg Clayton                      for (size_t i = 0; i < argc; ++i)
512636d6ed0SCaroline Tice                          if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
513d9d63369SCaroline Tice                              option_arg_vector->push_back
514d9d63369SCaroline Tice                                            (OptionArgPair ("<argument>",
515d9d63369SCaroline Tice                                                            OptionArgValue (-1,
516d9d63369SCaroline Tice                                                                            std::string (args.GetArgumentAtIndex (i)))));
517ebc09c36SJim Ingham                  }
518ebc09c36SJim Ingham 
519ebc09c36SJim Ingham                  // Create the alias.
520ebc09c36SJim Ingham 
521a7015092SGreg Clayton                  if (m_interpreter.AliasExists (alias_command.c_str())
522a7015092SGreg Clayton                      || m_interpreter.UserCommandExists (alias_command.c_str()))
523ebc09c36SJim Ingham                  {
524a7015092SGreg Clayton                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
525ebc09c36SJim Ingham                      if (tmp_option_arg_sp.get())
526ebc09c36SJim Ingham                      {
527ebc09c36SJim Ingham                          if (option_arg_vector->size() == 0)
528a7015092SGreg Clayton                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
529ebc09c36SJim Ingham                      }
530ebc09c36SJim Ingham                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
531ebc09c36SJim Ingham                                                      alias_command.c_str());
532ebc09c36SJim Ingham                  }
533ebc09c36SJim Ingham 
534ebc09c36SJim Ingham                  if (use_subcommand)
535a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
536ebc09c36SJim Ingham                  else
537a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
538ebc09c36SJim Ingham                  if (option_arg_vector->size() > 0)
539a7015092SGreg Clayton                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
540ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
541ebc09c36SJim Ingham              }
542ebc09c36SJim Ingham              else
543ebc09c36SJim Ingham              {
544ebc09c36SJim Ingham                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
545ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusFailed);
546e7941795SCaroline Tice                  return false;
547ebc09c36SJim Ingham              }
548ebc09c36SJim Ingham         }
549ebc09c36SJim Ingham 
550ebc09c36SJim Ingham         return result.Succeeded();
551ebc09c36SJim Ingham     }
552ebc09c36SJim Ingham };
553ebc09c36SJim Ingham 
554ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
555ebc09c36SJim Ingham //-------------------------------------------------------------------------
556ebc09c36SJim Ingham // CommandObjectCommandsUnalias
557ebc09c36SJim Ingham //-------------------------------------------------------------------------
558ebc09c36SJim Ingham 
559ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject
560ebc09c36SJim Ingham {
561ebc09c36SJim Ingham public:
562a7015092SGreg Clayton     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
563a7015092SGreg Clayton         CommandObject (interpreter,
564a7015092SGreg Clayton                        "commands unalias",
56586ddae50SCaroline Tice                        "Allow the user to remove/delete a user-defined command abbreviation.",
566405fe67fSCaroline Tice                        NULL)
567ebc09c36SJim Ingham     {
568405fe67fSCaroline Tice         CommandArgumentEntry arg;
569405fe67fSCaroline Tice         CommandArgumentData alias_arg;
570405fe67fSCaroline Tice 
571405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
572405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
573405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
574405fe67fSCaroline Tice 
575405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
576405fe67fSCaroline Tice         arg.push_back (alias_arg);
577405fe67fSCaroline Tice 
578405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
579405fe67fSCaroline Tice         m_arguments.push_back (arg);
580ebc09c36SJim Ingham     }
581ebc09c36SJim Ingham 
582ebc09c36SJim Ingham     ~CommandObjectCommandsUnalias()
583ebc09c36SJim Ingham     {
584ebc09c36SJim Ingham     }
585ebc09c36SJim Ingham 
586ebc09c36SJim Ingham 
587ebc09c36SJim Ingham     bool
588ebc09c36SJim Ingham     Execute
589ebc09c36SJim Ingham     (
590ebc09c36SJim Ingham         Args& args,
591ebc09c36SJim Ingham         CommandReturnObject &result
592ebc09c36SJim Ingham     )
593ebc09c36SJim Ingham     {
594ebc09c36SJim Ingham         CommandObject::CommandMap::iterator pos;
595ebc09c36SJim Ingham         CommandObject *cmd_obj;
596ebc09c36SJim Ingham 
597ebc09c36SJim Ingham         if (args.GetArgumentCount() != 0)
598ebc09c36SJim Ingham         {
599ebc09c36SJim Ingham             const char *command_name = args.GetArgumentAtIndex(0);
600a7015092SGreg Clayton             cmd_obj = m_interpreter.GetCommandObject(command_name);
601ebc09c36SJim Ingham             if (cmd_obj)
602ebc09c36SJim Ingham             {
603a7015092SGreg Clayton                 if (m_interpreter.CommandExists (command_name))
604ebc09c36SJim Ingham                 {
605ebc09c36SJim Ingham                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
606ebc09c36SJim Ingham                                                   command_name);
607ebc09c36SJim Ingham                     result.SetStatus (eReturnStatusFailed);
608ebc09c36SJim Ingham                 }
609ebc09c36SJim Ingham                 else
610ebc09c36SJim Ingham                 {
611ebc09c36SJim Ingham 
612a7015092SGreg Clayton                     if (m_interpreter.RemoveAlias (command_name) == false)
613ebc09c36SJim Ingham                     {
614a7015092SGreg Clayton                         if (m_interpreter.AliasExists (command_name))
615ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
616ebc09c36SJim Ingham                                                           command_name);
617ebc09c36SJim Ingham                         else
618ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
619ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusFailed);
620ebc09c36SJim Ingham                     }
621ebc09c36SJim Ingham                     else
622ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
623ebc09c36SJim Ingham                 }
624ebc09c36SJim Ingham             }
625ebc09c36SJim Ingham             else
626ebc09c36SJim Ingham             {
627ebc09c36SJim Ingham                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
628ebc09c36SJim Ingham                                               "current list of commands.\n",
629ebc09c36SJim Ingham                                              command_name);
630ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusFailed);
631ebc09c36SJim Ingham             }
632ebc09c36SJim Ingham         }
633ebc09c36SJim Ingham         else
634ebc09c36SJim Ingham         {
635ebc09c36SJim Ingham             result.AppendError ("must call 'unalias' with a valid alias");
636ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
637ebc09c36SJim Ingham         }
638ebc09c36SJim Ingham 
639ebc09c36SJim Ingham         return result.Succeeded();
640ebc09c36SJim Ingham     }
641ebc09c36SJim Ingham };
642ebc09c36SJim Ingham 
643ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
644ebc09c36SJim Ingham 
645ebc09c36SJim Ingham //-------------------------------------------------------------------------
646ebc09c36SJim Ingham // CommandObjectMultiwordCommands
647ebc09c36SJim Ingham //-------------------------------------------------------------------------
648ebc09c36SJim Ingham 
649ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
650a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
651a7015092SGreg Clayton                             "commands",
6523f4c09c1SCaroline Tice                             "A set of commands for managing or customizing the debugger commands.",
653ebc09c36SJim Ingham                             "commands <subcommand> [<subcommand-options>]")
654ebc09c36SJim Ingham {
655a7015092SGreg Clayton     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
656a7015092SGreg Clayton     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
657a7015092SGreg Clayton     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
658ebc09c36SJim Ingham }
659ebc09c36SJim Ingham 
660ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
661ebc09c36SJim Ingham {
662ebc09c36SJim Ingham }
663ebc09c36SJim Ingham 
664