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