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/Core/Debugger.h"
17*de164aaaSGreg Clayton #include "lldb/Core/InputReader.h"
18*de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h"
19ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
20*de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h"
21ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h"
22ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h"
23ebc09c36SJim Ingham 
24ebc09c36SJim Ingham using namespace lldb;
25ebc09c36SJim Ingham using namespace lldb_private;
26ebc09c36SJim Ingham 
27ebc09c36SJim Ingham //-------------------------------------------------------------------------
28ebc09c36SJim Ingham // CommandObjectCommandsSource
29ebc09c36SJim Ingham //-------------------------------------------------------------------------
30ebc09c36SJim Ingham 
31ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject
32ebc09c36SJim Ingham {
33e16c50a1SJim Ingham private:
34e16c50a1SJim Ingham 
35e16c50a1SJim Ingham     class CommandOptions : public Options
36e16c50a1SJim Ingham     {
37e16c50a1SJim Ingham     public:
38e16c50a1SJim Ingham 
39eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
40eb0103f2SGreg Clayton             Options (interpreter)
41eb0103f2SGreg Clayton         {
42eb0103f2SGreg Clayton         }
43e16c50a1SJim Ingham 
44e16c50a1SJim Ingham         virtual
45e16c50a1SJim Ingham         ~CommandOptions (){}
46e16c50a1SJim Ingham 
47e16c50a1SJim Ingham         virtual Error
48f6b8b581SGreg Clayton         SetOptionValue (uint32_t option_idx, const char *option_arg)
49e16c50a1SJim Ingham         {
50e16c50a1SJim Ingham             Error error;
51e16c50a1SJim Ingham             char short_option = (char) m_getopt_table[option_idx].val;
52e16c50a1SJim Ingham             bool success;
53e16c50a1SJim Ingham 
54e16c50a1SJim Ingham             switch (short_option)
55e16c50a1SJim Ingham             {
56e16c50a1SJim Ingham                 case 'e':
57e16c50a1SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
58e16c50a1SJim Ingham                     if (!success)
59e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
60e16c50a1SJim Ingham                     break;
61e16c50a1SJim Ingham                 case 'c':
62e16c50a1SJim Ingham                     m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
63e16c50a1SJim Ingham                     if (!success)
64e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
65e16c50a1SJim Ingham                     break;
66e16c50a1SJim Ingham                 default:
67e16c50a1SJim Ingham                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
68e16c50a1SJim Ingham                     break;
69e16c50a1SJim Ingham             }
70e16c50a1SJim Ingham 
71e16c50a1SJim Ingham             return error;
72e16c50a1SJim Ingham         }
73e16c50a1SJim Ingham 
74e16c50a1SJim Ingham         void
75f6b8b581SGreg Clayton         OptionParsingStarting ()
76e16c50a1SJim Ingham         {
77e16c50a1SJim Ingham             m_stop_on_error = true;
78e16c50a1SJim Ingham             m_stop_on_continue = true;
79e16c50a1SJim Ingham         }
80e16c50a1SJim Ingham 
81e0d378b3SGreg Clayton         const OptionDefinition*
82e16c50a1SJim Ingham         GetDefinitions ()
83e16c50a1SJim Ingham         {
84e16c50a1SJim Ingham             return g_option_table;
85e16c50a1SJim Ingham         }
86e16c50a1SJim Ingham 
87e16c50a1SJim Ingham         // Options table: Required for subclasses of Options.
88e16c50a1SJim Ingham 
89e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
90e16c50a1SJim Ingham 
91e16c50a1SJim Ingham         // Instance variables to hold the values for command options.
92e16c50a1SJim Ingham 
93e16c50a1SJim Ingham         bool m_stop_on_error;
94e16c50a1SJim Ingham         bool m_stop_on_continue;
95e16c50a1SJim Ingham     };
96e16c50a1SJim Ingham 
97e16c50a1SJim Ingham     CommandOptions m_options;
98e16c50a1SJim Ingham 
99e16c50a1SJim Ingham     virtual Options *
100e16c50a1SJim Ingham     GetOptions ()
101e16c50a1SJim Ingham     {
102e16c50a1SJim Ingham         return &m_options;
103e16c50a1SJim Ingham     }
104e16c50a1SJim Ingham 
105ebc09c36SJim Ingham public:
106a7015092SGreg Clayton     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
107a7015092SGreg Clayton         CommandObject (interpreter,
108a7015092SGreg Clayton                        "commands source",
109e3d26315SCaroline Tice                        "Read in debugger commands from the file <filename> and execute them.",
110eb0103f2SGreg Clayton                        NULL),
111eb0103f2SGreg Clayton         m_options (interpreter)
112ebc09c36SJim Ingham     {
113405fe67fSCaroline Tice         CommandArgumentEntry arg;
114405fe67fSCaroline Tice         CommandArgumentData file_arg;
115405fe67fSCaroline Tice 
116405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
117405fe67fSCaroline Tice         file_arg.arg_type = eArgTypeFilename;
118405fe67fSCaroline Tice         file_arg.arg_repetition = eArgRepeatPlain;
119405fe67fSCaroline Tice 
120405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
121405fe67fSCaroline Tice         arg.push_back (file_arg);
122405fe67fSCaroline Tice 
123405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
124405fe67fSCaroline Tice         m_arguments.push_back (arg);
125ebc09c36SJim Ingham     }
126ebc09c36SJim Ingham 
127ebc09c36SJim Ingham     ~CommandObjectCommandsSource ()
128ebc09c36SJim Ingham     {
129ebc09c36SJim Ingham     }
130ebc09c36SJim Ingham 
131ebc09c36SJim Ingham     bool
132ebc09c36SJim Ingham     Execute
133ebc09c36SJim Ingham     (
134ebc09c36SJim Ingham         Args& args,
135ebc09c36SJim Ingham         CommandReturnObject &result
136ebc09c36SJim Ingham     )
137ebc09c36SJim Ingham     {
138ebc09c36SJim Ingham         const int argc = args.GetArgumentCount();
139ebc09c36SJim Ingham         if (argc == 1)
140ebc09c36SJim Ingham         {
141ebc09c36SJim Ingham             const char *filename = args.GetArgumentAtIndex(0);
142ebc09c36SJim Ingham 
143ebc09c36SJim Ingham             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
144ebc09c36SJim Ingham 
1451ee3853fSJohnny Chen             FileSpec cmd_file (filename, true);
146e16c50a1SJim Ingham             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
147e16c50a1SJim Ingham             bool echo_commands    = true;
148e16c50a1SJim Ingham             bool print_results    = true;
149ebc09c36SJim Ingham 
150e16c50a1SJim Ingham             m_interpreter.HandleCommandsFromFile (cmd_file,
151e16c50a1SJim Ingham                                                   exe_ctx,
152e16c50a1SJim Ingham                                                   m_options.m_stop_on_continue,
153e16c50a1SJim Ingham                                                   m_options.m_stop_on_error,
154e16c50a1SJim Ingham                                                   echo_commands,
155e16c50a1SJim Ingham                                                   print_results,
156e16c50a1SJim Ingham                                                   result);
157ebc09c36SJim Ingham         }
158ebc09c36SJim Ingham         else
159ebc09c36SJim Ingham         {
160ebc09c36SJim Ingham             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
161ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
162ebc09c36SJim Ingham         }
163ebc09c36SJim Ingham         return result.Succeeded();
164ebc09c36SJim Ingham 
165ebc09c36SJim Ingham     }
166ebc09c36SJim Ingham };
167ebc09c36SJim Ingham 
168e0d378b3SGreg Clayton OptionDefinition
169e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] =
170e16c50a1SJim Ingham {
171e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
172e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
173e16c50a1SJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
174e16c50a1SJim Ingham };
175e16c50a1SJim Ingham 
176ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
177ebc09c36SJim Ingham //-------------------------------------------------------------------------
178ebc09c36SJim Ingham // CommandObjectCommandsAlias
179ebc09c36SJim Ingham //-------------------------------------------------------------------------
180ebc09c36SJim Ingham 
181ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject
182ebc09c36SJim Ingham {
183ebc09c36SJim Ingham public:
184a7015092SGreg Clayton     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
185a7015092SGreg Clayton         CommandObject (interpreter,
186a7015092SGreg Clayton                        "commands alias",
187e3d26315SCaroline Tice                        "Allow users to define their own debugger command abbreviations.",
188405fe67fSCaroline Tice                        NULL)
189ebc09c36SJim Ingham     {
190ebc09c36SJim Ingham         SetHelpLong(
191ebc09c36SJim Ingham     "'alias' allows the user to create a short-cut or abbreviation for long \n\
192ebc09c36SJim Ingham     commands, multi-word commands, and commands that take particular options. \n\
193ebc09c36SJim Ingham     Below are some simple examples of how one might use the 'alias' command: \n\
19409799af6SCaroline Tice     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
195ebc09c36SJim Ingham                                          // command. \n\
19609799af6SCaroline Tice     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
197ebc09c36SJim Ingham                                          // command.  Since breakpoint commands are two-word \n\
198ebc09c36SJim Ingham                                          // commands, the user will still need to enter the \n\
199ebc09c36SJim Ingham                                          // second word after 'bp', e.g. 'bp enable' or \n\
200ebc09c36SJim Ingham                                          // 'bp delete'. \n\
20109799af6SCaroline Tice     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
202ebc09c36SJim Ingham                                          // two-word command 'breakpoint list'. \n\
203ebc09c36SJim Ingham     \nAn alias can include some options for the command, with the values either \n\
204ebc09c36SJim Ingham     filled in at the time the alias is created, or specified as positional \n\
205ebc09c36SJim Ingham     arguments, to be filled in when the alias is invoked.  The following example \n\
206ebc09c36SJim Ingham     shows how to create aliases with options: \n\
207ebc09c36SJim Ingham     \n\
20809799af6SCaroline Tice     'commands alias bfl breakpoint set -f %1 -l %2' \n\
209ebc09c36SJim Ingham     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
210ebc09c36SJim Ingham     options already part of the alias.  So if the user wants to set a breakpoint \n\
211ebc09c36SJim Ingham     by file and line without explicitly having to use the -f and -l options, the \n\
212ebc09c36SJim Ingham     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
213ebc09c36SJim Ingham     for the actual arguments that will be passed when the alias command is used. \n\
214ebc09c36SJim Ingham     The number in the placeholder refers to the position/order the actual value \n\
215ebc09c36SJim Ingham     occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
216ebc09c36SJim Ingham     will be replaced with the first argument, all the occurrences of '%2' in the \n\
217ebc09c36SJim Ingham     alias will be replaced with the second argument, and so on.  This also allows \n\
218ebc09c36SJim Ingham     actual arguments to be used multiple times within an alias (see 'process \n\
219ebc09c36SJim Ingham     launch' example below).  So in the 'bfl' case, the actual file value will be \n\
220ebc09c36SJim Ingham     filled in with the first argument following 'bfl' and the actual line number \n\
221ebc09c36SJim Ingham     value will be filled in with the second argument.  The user would use this \n\
222ebc09c36SJim Ingham     alias as follows: \n\
22309799af6SCaroline Tice     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
224ebc09c36SJim Ingham     <... some time later ...> \n\
22509799af6SCaroline Tice     (lldb)  bfl my-file.c 137 \n\
226ebc09c36SJim Ingham     \nThis would be the same as if the user had entered \n\
227ebc09c36SJim Ingham     'breakpoint set -f my-file.c -l 137'. \n\
228ebc09c36SJim Ingham     \nAnother example: \n\
22909799af6SCaroline Tice     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
23009799af6SCaroline Tice     (lldb)  pltty /dev/tty0 \n\
231ebc09c36SJim Ingham            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
232ebc09c36SJim Ingham     \nIf the user always wanted to pass the same value to a particular option, the \n\
233ebc09c36SJim Ingham     alias could be defined with that value directly in the alias as a constant, \n\
234ebc09c36SJim Ingham     rather than using a positional placeholder: \n\
2350708e2c2SSean Callanan     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
236ebc09c36SJim Ingham                                                    // 3 of whatever file is indicated. \n");
237ebc09c36SJim Ingham 
238405fe67fSCaroline Tice         CommandArgumentEntry arg1;
239405fe67fSCaroline Tice         CommandArgumentEntry arg2;
240405fe67fSCaroline Tice         CommandArgumentEntry arg3;
241405fe67fSCaroline Tice         CommandArgumentData alias_arg;
242405fe67fSCaroline Tice         CommandArgumentData cmd_arg;
243405fe67fSCaroline Tice         CommandArgumentData options_arg;
244405fe67fSCaroline Tice 
245405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
246405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
247405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
248405fe67fSCaroline Tice 
249405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
250405fe67fSCaroline Tice         arg1.push_back (alias_arg);
251405fe67fSCaroline Tice 
252405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
253405fe67fSCaroline Tice         cmd_arg.arg_type = eArgTypeCommandName;
254405fe67fSCaroline Tice         cmd_arg.arg_repetition = eArgRepeatPlain;
255405fe67fSCaroline Tice 
256405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
257405fe67fSCaroline Tice         arg2.push_back (cmd_arg);
258405fe67fSCaroline Tice 
259405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
260405fe67fSCaroline Tice         options_arg.arg_type = eArgTypeAliasOptions;
261405fe67fSCaroline Tice         options_arg.arg_repetition = eArgRepeatOptional;
262405fe67fSCaroline Tice 
263405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
264405fe67fSCaroline Tice         arg3.push_back (options_arg);
265405fe67fSCaroline Tice 
266405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
267405fe67fSCaroline Tice         m_arguments.push_back (arg1);
268405fe67fSCaroline Tice         m_arguments.push_back (arg2);
269405fe67fSCaroline Tice         m_arguments.push_back (arg3);
270ebc09c36SJim Ingham     }
271ebc09c36SJim Ingham 
272ebc09c36SJim Ingham     ~CommandObjectCommandsAlias ()
273ebc09c36SJim Ingham     {
274ebc09c36SJim Ingham     }
275ebc09c36SJim Ingham 
276844d2303SCaroline Tice     bool
277844d2303SCaroline Tice     WantsRawCommandString ()
278844d2303SCaroline Tice     {
279844d2303SCaroline Tice         return true;
280844d2303SCaroline Tice     }
281844d2303SCaroline Tice 
282844d2303SCaroline Tice     bool
283844d2303SCaroline Tice     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
284844d2303SCaroline Tice     {
285844d2303SCaroline Tice         Args args (raw_command_line);
286844d2303SCaroline Tice         std::string raw_command_string (raw_command_line);
287844d2303SCaroline Tice 
288844d2303SCaroline Tice         size_t argc = args.GetArgumentCount();
289844d2303SCaroline Tice 
290844d2303SCaroline Tice         if (argc < 2)
291844d2303SCaroline Tice         {
292844d2303SCaroline Tice             result.AppendError ("'alias' requires at least two arguments");
293844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
294844d2303SCaroline Tice             return false;
295844d2303SCaroline Tice         }
296844d2303SCaroline Tice 
297844d2303SCaroline Tice         // Get the alias command.
298844d2303SCaroline Tice 
299844d2303SCaroline Tice         const std::string alias_command = args.GetArgumentAtIndex (0);
300844d2303SCaroline Tice 
301844d2303SCaroline Tice         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
302844d2303SCaroline Tice         // does the stripping itself.
303844d2303SCaroline Tice         size_t pos = raw_command_string.find (alias_command);
304844d2303SCaroline Tice         if (pos == 0)
305844d2303SCaroline Tice         {
306844d2303SCaroline Tice             raw_command_string = raw_command_string.substr (alias_command.size());
307844d2303SCaroline Tice             pos = raw_command_string.find_first_not_of (' ');
308844d2303SCaroline Tice             if ((pos != std::string::npos) && (pos > 0))
309844d2303SCaroline Tice                 raw_command_string = raw_command_string.substr (pos);
310844d2303SCaroline Tice         }
311844d2303SCaroline Tice         else
312844d2303SCaroline Tice         {
313844d2303SCaroline Tice             result.AppendError ("Error parsing command string.  No alias created.");
314844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
315844d2303SCaroline Tice             return false;
316844d2303SCaroline Tice         }
317844d2303SCaroline Tice 
318844d2303SCaroline Tice 
319844d2303SCaroline Tice         // Verify that the command is alias-able.
320844d2303SCaroline Tice         if (m_interpreter.CommandExists (alias_command.c_str()))
321844d2303SCaroline Tice         {
322844d2303SCaroline Tice             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
323844d2303SCaroline Tice                                           alias_command.c_str());
324844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
325844d2303SCaroline Tice             return false;
326844d2303SCaroline Tice         }
327844d2303SCaroline Tice 
328844d2303SCaroline Tice         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
329844d2303SCaroline Tice         // raw_command_string is returned with the name of the command object stripped off the front.
330844d2303SCaroline Tice         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
331844d2303SCaroline Tice 
332844d2303SCaroline Tice         if (!cmd_obj)
333844d2303SCaroline Tice         {
334844d2303SCaroline Tice             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
335844d2303SCaroline Tice                                           "  No alias created.", raw_command_string.c_str());
336844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
337844d2303SCaroline Tice             return false;
338844d2303SCaroline Tice         }
339844d2303SCaroline Tice         else if (!cmd_obj->WantsRawCommandString ())
340844d2303SCaroline Tice         {
341844d2303SCaroline Tice             // Note that args was initialized with the original command, and has not been updated to this point.
342844d2303SCaroline Tice             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
343844d2303SCaroline Tice             return Execute (args, result);
344844d2303SCaroline Tice         }
345844d2303SCaroline Tice         else
346844d2303SCaroline Tice         {
347844d2303SCaroline Tice             // Verify & handle any options/arguments passed to the alias command
348844d2303SCaroline Tice 
349844d2303SCaroline Tice             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
350844d2303SCaroline Tice             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
351844d2303SCaroline Tice 
352844d2303SCaroline Tice             // Check to see if there's anything left in the input command string.
353844d2303SCaroline Tice             if (raw_command_string.size() > 0)
354844d2303SCaroline Tice             {
355844d2303SCaroline Tice 
356844d2303SCaroline Tice                 // Check to see if the command being aliased can take any command options.
357844d2303SCaroline Tice                 Options *options = cmd_obj->GetOptions();
358844d2303SCaroline Tice                 if (options)
359844d2303SCaroline Tice                 {
360844d2303SCaroline Tice                     // See if any options were specified as part of the alias; if so, handle them appropriately
361f6b8b581SGreg Clayton                     options->NotifyOptionParsingStarting ();
362844d2303SCaroline Tice                     Args tmp_args (raw_command_string.c_str());
363844d2303SCaroline Tice                     args.Unshift ("dummy_arg");
364844d2303SCaroline Tice                     args.ParseAliasOptions (*options, result, option_arg_vector, raw_command_string);
365844d2303SCaroline Tice                     args.Shift ();
366844d2303SCaroline Tice                     if (result.Succeeded())
367844d2303SCaroline Tice                         options->VerifyPartialOptions (result);
368844d2303SCaroline Tice                     if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
369844d2303SCaroline Tice                     {
370844d2303SCaroline Tice                         result.AppendError ("Unable to create requested alias.\n");
371844d2303SCaroline Tice                         return false;
372844d2303SCaroline Tice                     }
373844d2303SCaroline Tice                 }
374844d2303SCaroline Tice                 // Anything remaining must be plain raw input.  Push it in as a single raw input argument.
375844d2303SCaroline Tice                 if (raw_command_string.size() > 0)
376844d2303SCaroline Tice                     option_arg_vector->push_back (OptionArgPair ("<argument>",
377844d2303SCaroline Tice                                                                  OptionArgValue (-1,
378844d2303SCaroline Tice                                                                                   raw_command_string)));
379844d2303SCaroline Tice             }
380844d2303SCaroline Tice 
381844d2303SCaroline Tice             // Create the alias
382844d2303SCaroline Tice             if (m_interpreter.AliasExists (alias_command.c_str())
383844d2303SCaroline Tice                 || m_interpreter.UserCommandExists (alias_command.c_str()))
384844d2303SCaroline Tice             {
385844d2303SCaroline Tice                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
386844d2303SCaroline Tice                 if (temp_option_arg_sp.get())
387844d2303SCaroline Tice                 {
388844d2303SCaroline Tice                     if (option_arg_vector->size() == 0)
389844d2303SCaroline Tice                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
390844d2303SCaroline Tice                 }
391844d2303SCaroline Tice                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
392844d2303SCaroline Tice                                                 alias_command.c_str());
393844d2303SCaroline Tice             }
394844d2303SCaroline Tice 
395844d2303SCaroline Tice             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
396472362e6SCaroline Tice             if (cmd_obj_sp)
397472362e6SCaroline Tice             {
398844d2303SCaroline Tice                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
399844d2303SCaroline Tice                 if (option_arg_vector->size() > 0)
400844d2303SCaroline Tice                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
401844d2303SCaroline Tice                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
402844d2303SCaroline Tice             }
403472362e6SCaroline Tice             else
404472362e6SCaroline Tice             {
405472362e6SCaroline Tice                 result.AppendError ("Unable to create requested alias.\n");
406472362e6SCaroline Tice                 result.SetStatus (eReturnStatusFailed);
407472362e6SCaroline Tice             }
408472362e6SCaroline Tice         }
409844d2303SCaroline Tice         return result.Succeeded();
410844d2303SCaroline Tice     }
411ebc09c36SJim Ingham 
412ebc09c36SJim Ingham     bool
413ebc09c36SJim Ingham     Execute
414ebc09c36SJim Ingham     (
415ebc09c36SJim Ingham         Args& args,
416ebc09c36SJim Ingham         CommandReturnObject &result
417ebc09c36SJim Ingham     )
418ebc09c36SJim Ingham     {
419867b185dSCaroline Tice         size_t argc = args.GetArgumentCount();
420ebc09c36SJim Ingham 
421ebc09c36SJim Ingham         if (argc < 2)
422ebc09c36SJim Ingham         {
423ebc09c36SJim Ingham             result.AppendError ("'alias' requires at least two arguments");
424ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
425ebc09c36SJim Ingham             return false;
426ebc09c36SJim Ingham         }
427ebc09c36SJim Ingham 
428ebc09c36SJim Ingham         const std::string alias_command = args.GetArgumentAtIndex(0);
429ebc09c36SJim Ingham         const std::string actual_command = args.GetArgumentAtIndex(1);
430ebc09c36SJim Ingham 
431ebc09c36SJim Ingham         args.Shift();  // Shift the alias command word off the argument vector.
432ebc09c36SJim Ingham         args.Shift();  // Shift the old command word off the argument vector.
433ebc09c36SJim Ingham 
434ebc09c36SJim Ingham         // Verify that the command is alias'able, and get the appropriate command object.
435ebc09c36SJim Ingham 
436a7015092SGreg Clayton         if (m_interpreter.CommandExists (alias_command.c_str()))
437ebc09c36SJim Ingham         {
438ebc09c36SJim Ingham             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
439ebc09c36SJim Ingham                                          alias_command.c_str());
440ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
441ebc09c36SJim Ingham         }
442ebc09c36SJim Ingham         else
443ebc09c36SJim Ingham         {
444a7015092SGreg Clayton              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
445ebc09c36SJim Ingham              CommandObjectSP subcommand_obj_sp;
446ebc09c36SJim Ingham              bool use_subcommand = false;
447ebc09c36SJim Ingham              if (command_obj_sp.get())
448ebc09c36SJim Ingham              {
449ebc09c36SJim Ingham                  CommandObject *cmd_obj = command_obj_sp.get();
450c982c768SGreg Clayton                  CommandObject *sub_cmd_obj = NULL;
451ebc09c36SJim Ingham                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
452ebc09c36SJim Ingham                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
453ebc09c36SJim Ingham 
454844d2303SCaroline Tice                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
455ebc09c36SJim Ingham                  {
456ebc09c36SJim Ingham                      if (argc >= 3)
457ebc09c36SJim Ingham                      {
458ebc09c36SJim Ingham                          const std::string sub_command = args.GetArgumentAtIndex(0);
459ebc09c36SJim Ingham                          assert (sub_command.length() != 0);
460ebc09c36SJim Ingham                          subcommand_obj_sp =
461ebc09c36SJim Ingham                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
462ebc09c36SJim Ingham                          if (subcommand_obj_sp.get())
463ebc09c36SJim Ingham                          {
464ebc09c36SJim Ingham                              sub_cmd_obj = subcommand_obj_sp.get();
465ebc09c36SJim Ingham                              use_subcommand = true;
466ebc09c36SJim Ingham                              args.Shift();  // Shift the sub_command word off the argument vector.
467844d2303SCaroline Tice                              cmd_obj = sub_cmd_obj;
468ebc09c36SJim Ingham                          }
469ebc09c36SJim Ingham                          else
470ebc09c36SJim Ingham                          {
471f415eeb4SCaroline Tice                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
472f415eeb4SCaroline Tice                                                           "Unable to create alias.\n",
473f415eeb4SCaroline Tice                                                           sub_command.c_str(), actual_command.c_str());
474ebc09c36SJim Ingham                              result.SetStatus (eReturnStatusFailed);
475ebc09c36SJim Ingham                              return false;
476ebc09c36SJim Ingham                          }
477ebc09c36SJim Ingham                      }
478ebc09c36SJim Ingham                  }
479ebc09c36SJim Ingham 
480ebc09c36SJim Ingham                  // Verify & handle any options/arguments passed to the alias command
481ebc09c36SJim Ingham 
482ebc09c36SJim Ingham                  if (args.GetArgumentCount () > 0)
483ebc09c36SJim Ingham                  {
484ebc09c36SJim Ingham                      if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
485ebc09c36SJim Ingham                          || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
486ebc09c36SJim Ingham                      {
487ebc09c36SJim Ingham                          Options *options;
488ebc09c36SJim Ingham                          if (use_subcommand)
489ebc09c36SJim Ingham                              options = sub_cmd_obj->GetOptions();
490ebc09c36SJim Ingham                          else
491ebc09c36SJim Ingham                              options = cmd_obj->GetOptions();
492f6b8b581SGreg Clayton                          options->NotifyOptionParsingStarting ();
493844d2303SCaroline Tice                          std::string empty_string;
494ebc09c36SJim Ingham                          args.Unshift ("dummy_arg");
495844d2303SCaroline Tice                          args.ParseAliasOptions (*options, result, option_arg_vector, empty_string);
496ebc09c36SJim Ingham                          args.Shift ();
497ebc09c36SJim Ingham                          if (result.Succeeded())
498ebc09c36SJim Ingham                              options->VerifyPartialOptions (result);
499867b185dSCaroline Tice                          if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted)
500ebc09c36SJim Ingham                         {
501867b185dSCaroline Tice                             result.AppendError ("Unable to create requested command alias.\n");
502e7941795SCaroline Tice                             return false;
503867b185dSCaroline Tice                         }
504867b185dSCaroline Tice                      }
505867b185dSCaroline Tice 
506867b185dSCaroline Tice                      // Anything remaining in args must be a plain argument.
507867b185dSCaroline Tice 
508867b185dSCaroline Tice                      argc = args.GetArgumentCount();
509c982c768SGreg Clayton                      for (size_t i = 0; i < argc; ++i)
510636d6ed0SCaroline Tice                          if (strcmp (args.GetArgumentAtIndex (i), "") != 0)
511d9d63369SCaroline Tice                              option_arg_vector->push_back
512d9d63369SCaroline Tice                                            (OptionArgPair ("<argument>",
513d9d63369SCaroline Tice                                                            OptionArgValue (-1,
514d9d63369SCaroline Tice                                                                            std::string (args.GetArgumentAtIndex (i)))));
515ebc09c36SJim Ingham                  }
516ebc09c36SJim Ingham 
517ebc09c36SJim Ingham                  // Create the alias.
518ebc09c36SJim Ingham 
519a7015092SGreg Clayton                  if (m_interpreter.AliasExists (alias_command.c_str())
520a7015092SGreg Clayton                      || m_interpreter.UserCommandExists (alias_command.c_str()))
521ebc09c36SJim Ingham                  {
522a7015092SGreg Clayton                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
523ebc09c36SJim Ingham                      if (tmp_option_arg_sp.get())
524ebc09c36SJim Ingham                      {
525ebc09c36SJim Ingham                          if (option_arg_vector->size() == 0)
526a7015092SGreg Clayton                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
527ebc09c36SJim Ingham                      }
528ebc09c36SJim Ingham                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
529ebc09c36SJim Ingham                                                      alias_command.c_str());
530ebc09c36SJim Ingham                  }
531ebc09c36SJim Ingham 
532ebc09c36SJim Ingham                  if (use_subcommand)
533a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
534ebc09c36SJim Ingham                  else
535a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
536ebc09c36SJim Ingham                  if (option_arg_vector->size() > 0)
537a7015092SGreg Clayton                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
538ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
539ebc09c36SJim Ingham              }
540ebc09c36SJim Ingham              else
541ebc09c36SJim Ingham              {
542ebc09c36SJim Ingham                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
543ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusFailed);
544e7941795SCaroline Tice                  return false;
545ebc09c36SJim Ingham              }
546ebc09c36SJim Ingham         }
547ebc09c36SJim Ingham 
548ebc09c36SJim Ingham         return result.Succeeded();
549ebc09c36SJim Ingham     }
550ebc09c36SJim Ingham };
551ebc09c36SJim Ingham 
552ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
553ebc09c36SJim Ingham //-------------------------------------------------------------------------
554ebc09c36SJim Ingham // CommandObjectCommandsUnalias
555ebc09c36SJim Ingham //-------------------------------------------------------------------------
556ebc09c36SJim Ingham 
557ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject
558ebc09c36SJim Ingham {
559ebc09c36SJim Ingham public:
560a7015092SGreg Clayton     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
561a7015092SGreg Clayton         CommandObject (interpreter,
562a7015092SGreg Clayton                        "commands unalias",
56386ddae50SCaroline Tice                        "Allow the user to remove/delete a user-defined command abbreviation.",
564405fe67fSCaroline Tice                        NULL)
565ebc09c36SJim Ingham     {
566405fe67fSCaroline Tice         CommandArgumentEntry arg;
567405fe67fSCaroline Tice         CommandArgumentData alias_arg;
568405fe67fSCaroline Tice 
569405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
570405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
571405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
572405fe67fSCaroline Tice 
573405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
574405fe67fSCaroline Tice         arg.push_back (alias_arg);
575405fe67fSCaroline Tice 
576405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
577405fe67fSCaroline Tice         m_arguments.push_back (arg);
578ebc09c36SJim Ingham     }
579ebc09c36SJim Ingham 
580ebc09c36SJim Ingham     ~CommandObjectCommandsUnalias()
581ebc09c36SJim Ingham     {
582ebc09c36SJim Ingham     }
583ebc09c36SJim Ingham 
584ebc09c36SJim Ingham 
585ebc09c36SJim Ingham     bool
586ebc09c36SJim Ingham     Execute
587ebc09c36SJim Ingham     (
588ebc09c36SJim Ingham         Args& args,
589ebc09c36SJim Ingham         CommandReturnObject &result
590ebc09c36SJim Ingham     )
591ebc09c36SJim Ingham     {
592ebc09c36SJim Ingham         CommandObject::CommandMap::iterator pos;
593ebc09c36SJim Ingham         CommandObject *cmd_obj;
594ebc09c36SJim Ingham 
595ebc09c36SJim Ingham         if (args.GetArgumentCount() != 0)
596ebc09c36SJim Ingham         {
597ebc09c36SJim Ingham             const char *command_name = args.GetArgumentAtIndex(0);
598a7015092SGreg Clayton             cmd_obj = m_interpreter.GetCommandObject(command_name);
599ebc09c36SJim Ingham             if (cmd_obj)
600ebc09c36SJim Ingham             {
601a7015092SGreg Clayton                 if (m_interpreter.CommandExists (command_name))
602ebc09c36SJim Ingham                 {
603ebc09c36SJim Ingham                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
604ebc09c36SJim Ingham                                                   command_name);
605ebc09c36SJim Ingham                     result.SetStatus (eReturnStatusFailed);
606ebc09c36SJim Ingham                 }
607ebc09c36SJim Ingham                 else
608ebc09c36SJim Ingham                 {
609ebc09c36SJim Ingham 
610a7015092SGreg Clayton                     if (m_interpreter.RemoveAlias (command_name) == false)
611ebc09c36SJim Ingham                     {
612a7015092SGreg Clayton                         if (m_interpreter.AliasExists (command_name))
613ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
614ebc09c36SJim Ingham                                                           command_name);
615ebc09c36SJim Ingham                         else
616ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
617ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusFailed);
618ebc09c36SJim Ingham                     }
619ebc09c36SJim Ingham                     else
620ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
621ebc09c36SJim Ingham                 }
622ebc09c36SJim Ingham             }
623ebc09c36SJim Ingham             else
624ebc09c36SJim Ingham             {
625ebc09c36SJim Ingham                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
626ebc09c36SJim Ingham                                               "current list of commands.\n",
627ebc09c36SJim Ingham                                              command_name);
628ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusFailed);
629ebc09c36SJim Ingham             }
630ebc09c36SJim Ingham         }
631ebc09c36SJim Ingham         else
632ebc09c36SJim Ingham         {
633ebc09c36SJim Ingham             result.AppendError ("must call 'unalias' with a valid alias");
634ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
635ebc09c36SJim Ingham         }
636ebc09c36SJim Ingham 
637ebc09c36SJim Ingham         return result.Succeeded();
638ebc09c36SJim Ingham     }
639ebc09c36SJim Ingham };
640ebc09c36SJim Ingham 
641*de164aaaSGreg Clayton #pragma mark CommandObjectCommandsAddRegex
642*de164aaaSGreg Clayton //-------------------------------------------------------------------------
643*de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
644*de164aaaSGreg Clayton //-------------------------------------------------------------------------
645*de164aaaSGreg Clayton 
646*de164aaaSGreg Clayton class CommandObjectCommandsAddRegex : public CommandObject
647*de164aaaSGreg Clayton {
648*de164aaaSGreg Clayton public:
649*de164aaaSGreg Clayton     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
650*de164aaaSGreg Clayton         CommandObject (interpreter,
651*de164aaaSGreg Clayton                        "commands regex",
652*de164aaaSGreg Clayton                        "Allow the user to create a regular expression command.",
653*de164aaaSGreg Clayton                        NULL),
654*de164aaaSGreg Clayton         m_options (interpreter)
655*de164aaaSGreg Clayton     {
656*de164aaaSGreg Clayton     }
657*de164aaaSGreg Clayton 
658*de164aaaSGreg Clayton     ~CommandObjectCommandsAddRegex()
659*de164aaaSGreg Clayton     {
660*de164aaaSGreg Clayton     }
661*de164aaaSGreg Clayton 
662*de164aaaSGreg Clayton 
663*de164aaaSGreg Clayton     bool
664*de164aaaSGreg Clayton     Execute (Args& args, CommandReturnObject &result)
665*de164aaaSGreg Clayton     {
666*de164aaaSGreg Clayton         if (args.GetArgumentCount() == 1)
667*de164aaaSGreg Clayton         {
668*de164aaaSGreg Clayton             const char *name = args.GetArgumentAtIndex(0);
669*de164aaaSGreg Clayton             InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
670*de164aaaSGreg Clayton             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
671*de164aaaSGreg Clayton                                                                  name,
672*de164aaaSGreg Clayton                                                                  m_options.GetHelp (),
673*de164aaaSGreg Clayton                                                                  m_options.GetSyntax (),
674*de164aaaSGreg Clayton                                                                  10));
675*de164aaaSGreg Clayton             if (reader_sp)
676*de164aaaSGreg Clayton             {
677*de164aaaSGreg Clayton                 Error err (reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
678*de164aaaSGreg Clayton                                                   this,                         // baton
679*de164aaaSGreg Clayton                                                   eInputReaderGranularityLine,  // token size, to pass to callback function
680*de164aaaSGreg Clayton                                                   "DONE",                       // end token
681*de164aaaSGreg Clayton                                                   "> ",                         // prompt
682*de164aaaSGreg Clayton                                                   true));                       // echo input
683*de164aaaSGreg Clayton                 if (err.Success())
684*de164aaaSGreg Clayton                 {
685*de164aaaSGreg Clayton                     m_interpreter.GetDebugger().PushInputReader (reader_sp);
686*de164aaaSGreg Clayton                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
687*de164aaaSGreg Clayton                 }
688*de164aaaSGreg Clayton                 else
689*de164aaaSGreg Clayton                 {
690*de164aaaSGreg Clayton                     result.AppendError (err.AsCString());
691*de164aaaSGreg Clayton                     result.SetStatus (eReturnStatusFailed);
692*de164aaaSGreg Clayton                 }
693*de164aaaSGreg Clayton             }
694*de164aaaSGreg Clayton         }
695*de164aaaSGreg Clayton         else
696*de164aaaSGreg Clayton         {
697*de164aaaSGreg Clayton             result.AppendError ("invalid arguments.\n");
698*de164aaaSGreg Clayton             result.SetStatus (eReturnStatusFailed);
699*de164aaaSGreg Clayton         }
700*de164aaaSGreg Clayton         return result.Succeeded();
701*de164aaaSGreg Clayton     }
702*de164aaaSGreg Clayton 
703*de164aaaSGreg Clayton     bool
704*de164aaaSGreg Clayton     AppendRegexAndSubstitution (const char *regex, const char *subst)
705*de164aaaSGreg Clayton     {
706*de164aaaSGreg Clayton         if (m_regex_cmd_ap.get())
707*de164aaaSGreg Clayton         {
708*de164aaaSGreg Clayton             m_regex_cmd_ap->AddRegexCommand (regex, subst);
709*de164aaaSGreg Clayton             return true;
710*de164aaaSGreg Clayton         }
711*de164aaaSGreg Clayton         return false;
712*de164aaaSGreg Clayton     }
713*de164aaaSGreg Clayton 
714*de164aaaSGreg Clayton     void
715*de164aaaSGreg Clayton     InputReaderIsDone()
716*de164aaaSGreg Clayton     {
717*de164aaaSGreg Clayton         if (m_regex_cmd_ap.get())
718*de164aaaSGreg Clayton         {
719*de164aaaSGreg Clayton             if (m_regex_cmd_ap->HasRegexEntries())
720*de164aaaSGreg Clayton             {
721*de164aaaSGreg Clayton                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
722*de164aaaSGreg Clayton                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
723*de164aaaSGreg Clayton             }
724*de164aaaSGreg Clayton         }
725*de164aaaSGreg Clayton     }
726*de164aaaSGreg Clayton 
727*de164aaaSGreg Clayton     static size_t
728*de164aaaSGreg Clayton     InputReaderCallback (void *baton,
729*de164aaaSGreg Clayton                          InputReader &reader,
730*de164aaaSGreg Clayton                          lldb::InputReaderAction notification,
731*de164aaaSGreg Clayton                          const char *bytes,
732*de164aaaSGreg Clayton                          size_t bytes_len);
733*de164aaaSGreg Clayton private:
734*de164aaaSGreg Clayton     std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
735*de164aaaSGreg Clayton 
736*de164aaaSGreg Clayton      class CommandOptions : public Options
737*de164aaaSGreg Clayton      {
738*de164aaaSGreg Clayton      public:
739*de164aaaSGreg Clayton 
740*de164aaaSGreg Clayton          CommandOptions (CommandInterpreter &interpreter) :
741*de164aaaSGreg Clayton             Options (interpreter)
742*de164aaaSGreg Clayton          {
743*de164aaaSGreg Clayton          }
744*de164aaaSGreg Clayton 
745*de164aaaSGreg Clayton          virtual
746*de164aaaSGreg Clayton          ~CommandOptions (){}
747*de164aaaSGreg Clayton 
748*de164aaaSGreg Clayton          virtual Error
749*de164aaaSGreg Clayton          SetOptionValue (uint32_t option_idx, const char *option_arg)
750*de164aaaSGreg Clayton          {
751*de164aaaSGreg Clayton              Error error;
752*de164aaaSGreg Clayton              char short_option = (char) m_getopt_table[option_idx].val;
753*de164aaaSGreg Clayton 
754*de164aaaSGreg Clayton              switch (short_option)
755*de164aaaSGreg Clayton              {
756*de164aaaSGreg Clayton                  case 'h':
757*de164aaaSGreg Clayton                      m_help.assign (option_arg);
758*de164aaaSGreg Clayton                      break;
759*de164aaaSGreg Clayton                  case 's':
760*de164aaaSGreg Clayton                      m_syntax.assign (option_arg);
761*de164aaaSGreg Clayton                      break;
762*de164aaaSGreg Clayton 
763*de164aaaSGreg Clayton                  default:
764*de164aaaSGreg Clayton                      error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
765*de164aaaSGreg Clayton                      break;
766*de164aaaSGreg Clayton              }
767*de164aaaSGreg Clayton 
768*de164aaaSGreg Clayton              return error;
769*de164aaaSGreg Clayton          }
770*de164aaaSGreg Clayton 
771*de164aaaSGreg Clayton          void
772*de164aaaSGreg Clayton          OptionParsingStarting ()
773*de164aaaSGreg Clayton          {
774*de164aaaSGreg Clayton              m_help.clear();
775*de164aaaSGreg Clayton              m_syntax.clear();
776*de164aaaSGreg Clayton          }
777*de164aaaSGreg Clayton 
778*de164aaaSGreg Clayton          const OptionDefinition*
779*de164aaaSGreg Clayton          GetDefinitions ()
780*de164aaaSGreg Clayton          {
781*de164aaaSGreg Clayton              return g_option_table;
782*de164aaaSGreg Clayton          }
783*de164aaaSGreg Clayton 
784*de164aaaSGreg Clayton          // Options table: Required for subclasses of Options.
785*de164aaaSGreg Clayton 
786*de164aaaSGreg Clayton          static OptionDefinition g_option_table[];
787*de164aaaSGreg Clayton 
788*de164aaaSGreg Clayton          const char *
789*de164aaaSGreg Clayton          GetHelp ()
790*de164aaaSGreg Clayton          {
791*de164aaaSGreg Clayton              if (m_help.empty())
792*de164aaaSGreg Clayton                  return NULL;
793*de164aaaSGreg Clayton              return m_help.c_str();
794*de164aaaSGreg Clayton          }
795*de164aaaSGreg Clayton          const char *
796*de164aaaSGreg Clayton          GetSyntax ()
797*de164aaaSGreg Clayton          {
798*de164aaaSGreg Clayton              if (m_syntax.empty())
799*de164aaaSGreg Clayton                  return NULL;
800*de164aaaSGreg Clayton              return m_syntax.c_str();
801*de164aaaSGreg Clayton          }
802*de164aaaSGreg Clayton          // Instance variables to hold the values for command options.
803*de164aaaSGreg Clayton      protected:
804*de164aaaSGreg Clayton          std::string m_help;
805*de164aaaSGreg Clayton          std::string m_syntax;
806*de164aaaSGreg Clayton      };
807*de164aaaSGreg Clayton 
808*de164aaaSGreg Clayton      CommandOptions m_options;
809*de164aaaSGreg Clayton 
810*de164aaaSGreg Clayton      virtual Options *
811*de164aaaSGreg Clayton      GetOptions ()
812*de164aaaSGreg Clayton      {
813*de164aaaSGreg Clayton          return &m_options;
814*de164aaaSGreg Clayton      }
815*de164aaaSGreg Clayton 
816*de164aaaSGreg Clayton };
817*de164aaaSGreg Clayton 
818*de164aaaSGreg Clayton size_t
819*de164aaaSGreg Clayton CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
820*de164aaaSGreg Clayton                                                     InputReader &reader,
821*de164aaaSGreg Clayton                                                     lldb::InputReaderAction notification,
822*de164aaaSGreg Clayton                                                     const char *bytes,
823*de164aaaSGreg Clayton                                                     size_t bytes_len)
824*de164aaaSGreg Clayton {
825*de164aaaSGreg Clayton     CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
826*de164aaaSGreg Clayton 
827*de164aaaSGreg Clayton     switch (notification)
828*de164aaaSGreg Clayton     {
829*de164aaaSGreg Clayton         case eInputReaderActivate:
830*de164aaaSGreg Clayton             reader.GetDebugger().GetOutputStream().Printf("%s\n", "Enter multiple regular expressions in the form s/find/replace/ then terminate with an empty line:");
831*de164aaaSGreg Clayton             break;
832*de164aaaSGreg Clayton         case eInputReaderReactivate:
833*de164aaaSGreg Clayton             break;
834*de164aaaSGreg Clayton 
835*de164aaaSGreg Clayton         case eInputReaderDeactivate:
836*de164aaaSGreg Clayton             break;
837*de164aaaSGreg Clayton 
838*de164aaaSGreg Clayton         case eInputReaderGotToken:
839*de164aaaSGreg Clayton             if (bytes_len == 0)
840*de164aaaSGreg Clayton                 reader.SetIsDone(true);
841*de164aaaSGreg Clayton             else if (bytes)
842*de164aaaSGreg Clayton             {
843*de164aaaSGreg Clayton                 std::string regex_sed (bytes, bytes_len);
844*de164aaaSGreg Clayton                 bool success = regex_sed.size() > 3 && regex_sed[0] == 's';
845*de164aaaSGreg Clayton                 if (success)
846*de164aaaSGreg Clayton                 {
847*de164aaaSGreg Clayton                     const size_t first_separator_char_pos = 1;
848*de164aaaSGreg Clayton                     const char separator_char = regex_sed[first_separator_char_pos];
849*de164aaaSGreg Clayton                     const size_t third_separator_char_pos = regex_sed.rfind (separator_char);
850*de164aaaSGreg Clayton 
851*de164aaaSGreg Clayton                     if (third_separator_char_pos != regex_sed.size() - 1)
852*de164aaaSGreg Clayton                         success = false;    // Didn't end with regex separator char
853*de164aaaSGreg Clayton                     else
854*de164aaaSGreg Clayton                     {
855*de164aaaSGreg Clayton                         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
856*de164aaaSGreg Clayton                         if (second_separator_char_pos == std::string::npos)
857*de164aaaSGreg Clayton                             success = false;    // Didn't find second regex separator char
858*de164aaaSGreg Clayton                         else
859*de164aaaSGreg Clayton                         {
860*de164aaaSGreg Clayton                             if (second_separator_char_pos <= 3)
861*de164aaaSGreg Clayton                                 success = false;    // Empty regex is invalid ("s///")
862*de164aaaSGreg Clayton                             else
863*de164aaaSGreg Clayton                             {
864*de164aaaSGreg Clayton                                 std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
865*de164aaaSGreg Clayton                                 std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
866*de164aaaSGreg Clayton                                 if (regex.empty() || subst.empty())
867*de164aaaSGreg Clayton                                     success= false;
868*de164aaaSGreg Clayton                                 else
869*de164aaaSGreg Clayton                                 {
870*de164aaaSGreg Clayton                                     add_regex_cmd->AppendRegexAndSubstitution(regex.c_str(), subst.c_str());
871*de164aaaSGreg Clayton                                 }
872*de164aaaSGreg Clayton                             }
873*de164aaaSGreg Clayton                         }
874*de164aaaSGreg Clayton                     }
875*de164aaaSGreg Clayton                 }
876*de164aaaSGreg Clayton                 if (!success)
877*de164aaaSGreg Clayton                 {
878*de164aaaSGreg Clayton                     reader.GetDebugger().GetOutputStream().PutCString("Regular expressions should be in the form s/<regex>/<subst>/.\n");
879*de164aaaSGreg Clayton                 }
880*de164aaaSGreg Clayton             }
881*de164aaaSGreg Clayton             break;
882*de164aaaSGreg Clayton 
883*de164aaaSGreg Clayton         case eInputReaderInterrupt:
884*de164aaaSGreg Clayton             reader.SetIsDone (true);
885*de164aaaSGreg Clayton             reader.GetDebugger().GetOutputStream().PutCString("Regular expression command creations was cancelled.\n");
886*de164aaaSGreg Clayton             break;
887*de164aaaSGreg Clayton 
888*de164aaaSGreg Clayton         case eInputReaderEndOfFile:
889*de164aaaSGreg Clayton             reader.SetIsDone (true);
890*de164aaaSGreg Clayton             break;
891*de164aaaSGreg Clayton 
892*de164aaaSGreg Clayton         case eInputReaderDone:
893*de164aaaSGreg Clayton             add_regex_cmd->InputReaderIsDone();
894*de164aaaSGreg Clayton             break;
895*de164aaaSGreg Clayton     }
896*de164aaaSGreg Clayton 
897*de164aaaSGreg Clayton     return bytes_len;
898*de164aaaSGreg Clayton }
899*de164aaaSGreg Clayton 
900*de164aaaSGreg Clayton 
901*de164aaaSGreg Clayton OptionDefinition
902*de164aaaSGreg Clayton CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
903*de164aaaSGreg Clayton {
904*de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "help", 'h', required_argument, NULL, 0, eArgTypeNone,    "The help text to display for this command."},
905*de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
906*de164aaaSGreg Clayton { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
907*de164aaaSGreg Clayton };
908*de164aaaSGreg Clayton 
909*de164aaaSGreg Clayton 
910ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
911ebc09c36SJim Ingham 
912ebc09c36SJim Ingham //-------------------------------------------------------------------------
913ebc09c36SJim Ingham // CommandObjectMultiwordCommands
914ebc09c36SJim Ingham //-------------------------------------------------------------------------
915ebc09c36SJim Ingham 
916ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
917a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
918a7015092SGreg Clayton                             "commands",
9193f4c09c1SCaroline Tice                             "A set of commands for managing or customizing the debugger commands.",
920ebc09c36SJim Ingham                             "commands <subcommand> [<subcommand-options>]")
921ebc09c36SJim Ingham {
922a7015092SGreg Clayton     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
923a7015092SGreg Clayton     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
924a7015092SGreg Clayton     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
925*de164aaaSGreg Clayton     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
926ebc09c36SJim Ingham }
927ebc09c36SJim Ingham 
928ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
929ebc09c36SJim Ingham {
930ebc09c36SJim Ingham }
931ebc09c36SJim Ingham 
932