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
150e5e5a79SGreg Clayton #include "llvm/ADT/StringRef.h"
160e5e5a79SGreg Clayton 
17ebc09c36SJim Ingham // Project includes
18ebc09c36SJim Ingham #include "lldb/Core/Debugger.h"
19de164aaaSGreg Clayton #include "lldb/Core/InputReader.h"
20de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h"
21ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
22de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h"
23ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h"
24ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h"
25ebc09c36SJim Ingham 
26ebc09c36SJim Ingham using namespace lldb;
27ebc09c36SJim Ingham using namespace lldb_private;
28ebc09c36SJim Ingham 
29ebc09c36SJim Ingham //-------------------------------------------------------------------------
30ebc09c36SJim Ingham // CommandObjectCommandsSource
31ebc09c36SJim Ingham //-------------------------------------------------------------------------
32ebc09c36SJim Ingham 
33ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject
34ebc09c36SJim Ingham {
35e16c50a1SJim Ingham private:
36e16c50a1SJim Ingham 
37e16c50a1SJim Ingham     class CommandOptions : public Options
38e16c50a1SJim Ingham     {
39e16c50a1SJim Ingham     public:
40e16c50a1SJim Ingham 
41eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
42eb0103f2SGreg Clayton             Options (interpreter)
43eb0103f2SGreg Clayton         {
44eb0103f2SGreg Clayton         }
45e16c50a1SJim Ingham 
46e16c50a1SJim Ingham         virtual
47e16c50a1SJim Ingham         ~CommandOptions (){}
48e16c50a1SJim Ingham 
49e16c50a1SJim Ingham         virtual Error
50f6b8b581SGreg Clayton         SetOptionValue (uint32_t option_idx, const char *option_arg)
51e16c50a1SJim Ingham         {
52e16c50a1SJim Ingham             Error error;
53e16c50a1SJim Ingham             char short_option = (char) m_getopt_table[option_idx].val;
54e16c50a1SJim Ingham             bool success;
55e16c50a1SJim Ingham 
56e16c50a1SJim Ingham             switch (short_option)
57e16c50a1SJim Ingham             {
58e16c50a1SJim Ingham                 case 'e':
59e16c50a1SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
60e16c50a1SJim Ingham                     if (!success)
61e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
62e16c50a1SJim Ingham                     break;
63e16c50a1SJim Ingham                 case 'c':
64e16c50a1SJim Ingham                     m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
65e16c50a1SJim Ingham                     if (!success)
66e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
67e16c50a1SJim Ingham                     break;
68e16c50a1SJim Ingham                 default:
69e16c50a1SJim Ingham                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
70e16c50a1SJim Ingham                     break;
71e16c50a1SJim Ingham             }
72e16c50a1SJim Ingham 
73e16c50a1SJim Ingham             return error;
74e16c50a1SJim Ingham         }
75e16c50a1SJim Ingham 
76e16c50a1SJim Ingham         void
77f6b8b581SGreg Clayton         OptionParsingStarting ()
78e16c50a1SJim Ingham         {
79e16c50a1SJim Ingham             m_stop_on_error = true;
80e16c50a1SJim Ingham             m_stop_on_continue = true;
81e16c50a1SJim Ingham         }
82e16c50a1SJim Ingham 
83e0d378b3SGreg Clayton         const OptionDefinition*
84e16c50a1SJim Ingham         GetDefinitions ()
85e16c50a1SJim Ingham         {
86e16c50a1SJim Ingham             return g_option_table;
87e16c50a1SJim Ingham         }
88e16c50a1SJim Ingham 
89e16c50a1SJim Ingham         // Options table: Required for subclasses of Options.
90e16c50a1SJim Ingham 
91e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
92e16c50a1SJim Ingham 
93e16c50a1SJim Ingham         // Instance variables to hold the values for command options.
94e16c50a1SJim Ingham 
95e16c50a1SJim Ingham         bool m_stop_on_error;
96e16c50a1SJim Ingham         bool m_stop_on_continue;
97e16c50a1SJim Ingham     };
98e16c50a1SJim Ingham 
99e16c50a1SJim Ingham     CommandOptions m_options;
100e16c50a1SJim Ingham 
101e16c50a1SJim Ingham     virtual Options *
102e16c50a1SJim Ingham     GetOptions ()
103e16c50a1SJim Ingham     {
104e16c50a1SJim Ingham         return &m_options;
105e16c50a1SJim Ingham     }
106e16c50a1SJim Ingham 
107ebc09c36SJim Ingham public:
108a7015092SGreg Clayton     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
109a7015092SGreg Clayton         CommandObject (interpreter,
1100e5e5a79SGreg Clayton                        "command source",
111e3d26315SCaroline Tice                        "Read in debugger commands from the file <filename> and execute them.",
112eb0103f2SGreg Clayton                        NULL),
113eb0103f2SGreg Clayton         m_options (interpreter)
114ebc09c36SJim Ingham     {
115405fe67fSCaroline Tice         CommandArgumentEntry arg;
116405fe67fSCaroline Tice         CommandArgumentData file_arg;
117405fe67fSCaroline Tice 
118405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
119405fe67fSCaroline Tice         file_arg.arg_type = eArgTypeFilename;
120405fe67fSCaroline Tice         file_arg.arg_repetition = eArgRepeatPlain;
121405fe67fSCaroline Tice 
122405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
123405fe67fSCaroline Tice         arg.push_back (file_arg);
124405fe67fSCaroline Tice 
125405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
126405fe67fSCaroline Tice         m_arguments.push_back (arg);
127ebc09c36SJim Ingham     }
128ebc09c36SJim Ingham 
129ebc09c36SJim Ingham     ~CommandObjectCommandsSource ()
130ebc09c36SJim Ingham     {
131ebc09c36SJim Ingham     }
132ebc09c36SJim Ingham 
133ebc09c36SJim Ingham     bool
134ebc09c36SJim Ingham     Execute
135ebc09c36SJim Ingham     (
136ebc09c36SJim Ingham         Args& args,
137ebc09c36SJim Ingham         CommandReturnObject &result
138ebc09c36SJim Ingham     )
139ebc09c36SJim Ingham     {
140ebc09c36SJim Ingham         const int argc = args.GetArgumentCount();
141ebc09c36SJim Ingham         if (argc == 1)
142ebc09c36SJim Ingham         {
143ebc09c36SJim Ingham             const char *filename = args.GetArgumentAtIndex(0);
144ebc09c36SJim Ingham 
145ebc09c36SJim Ingham             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
146ebc09c36SJim Ingham 
1471ee3853fSJohnny Chen             FileSpec cmd_file (filename, true);
148e16c50a1SJim Ingham             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
149e16c50a1SJim Ingham             bool echo_commands    = true;
150e16c50a1SJim Ingham             bool print_results    = true;
151ebc09c36SJim Ingham 
152e16c50a1SJim Ingham             m_interpreter.HandleCommandsFromFile (cmd_file,
153e16c50a1SJim Ingham                                                   exe_ctx,
154e16c50a1SJim Ingham                                                   m_options.m_stop_on_continue,
155e16c50a1SJim Ingham                                                   m_options.m_stop_on_error,
156e16c50a1SJim Ingham                                                   echo_commands,
157e16c50a1SJim Ingham                                                   print_results,
158e16c50a1SJim Ingham                                                   result);
159ebc09c36SJim Ingham         }
160ebc09c36SJim Ingham         else
161ebc09c36SJim Ingham         {
162ebc09c36SJim Ingham             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
163ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
164ebc09c36SJim Ingham         }
165ebc09c36SJim Ingham         return result.Succeeded();
166ebc09c36SJim Ingham 
167ebc09c36SJim Ingham     }
168ebc09c36SJim Ingham };
169ebc09c36SJim Ingham 
170e0d378b3SGreg Clayton OptionDefinition
171e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] =
172e16c50a1SJim Ingham {
173e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
174e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
175e16c50a1SJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
176e16c50a1SJim Ingham };
177e16c50a1SJim Ingham 
178ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
179ebc09c36SJim Ingham //-------------------------------------------------------------------------
180ebc09c36SJim Ingham // CommandObjectCommandsAlias
181ebc09c36SJim Ingham //-------------------------------------------------------------------------
182ebc09c36SJim Ingham 
183ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject
184ebc09c36SJim Ingham {
185ebc09c36SJim Ingham public:
186a7015092SGreg Clayton     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
187a7015092SGreg Clayton         CommandObject (interpreter,
1880e5e5a79SGreg Clayton                        "command alias",
189e3d26315SCaroline Tice                        "Allow users to define their own debugger command abbreviations.",
190405fe67fSCaroline Tice                        NULL)
191ebc09c36SJim Ingham     {
192ebc09c36SJim Ingham         SetHelpLong(
193ebc09c36SJim Ingham     "'alias' allows the user to create a short-cut or abbreviation for long \n\
194ebc09c36SJim Ingham     commands, multi-word commands, and commands that take particular options. \n\
195ebc09c36SJim Ingham     Below are some simple examples of how one might use the 'alias' command: \n\
19609799af6SCaroline Tice     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
197ebc09c36SJim Ingham                                          // command. \n\
19809799af6SCaroline Tice     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
199ebc09c36SJim Ingham                                          // command.  Since breakpoint commands are two-word \n\
200ebc09c36SJim Ingham                                          // commands, the user will still need to enter the \n\
201ebc09c36SJim Ingham                                          // second word after 'bp', e.g. 'bp enable' or \n\
202ebc09c36SJim Ingham                                          // 'bp delete'. \n\
20309799af6SCaroline Tice     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
204ebc09c36SJim Ingham                                          // two-word command 'breakpoint list'. \n\
205ebc09c36SJim Ingham     \nAn alias can include some options for the command, with the values either \n\
206ebc09c36SJim Ingham     filled in at the time the alias is created, or specified as positional \n\
207ebc09c36SJim Ingham     arguments, to be filled in when the alias is invoked.  The following example \n\
208ebc09c36SJim Ingham     shows how to create aliases with options: \n\
209ebc09c36SJim Ingham     \n\
21009799af6SCaroline Tice     'commands alias bfl breakpoint set -f %1 -l %2' \n\
211ebc09c36SJim Ingham     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
212ebc09c36SJim Ingham     options already part of the alias.  So if the user wants to set a breakpoint \n\
213ebc09c36SJim Ingham     by file and line without explicitly having to use the -f and -l options, the \n\
214ebc09c36SJim Ingham     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
215ebc09c36SJim Ingham     for the actual arguments that will be passed when the alias command is used. \n\
216ebc09c36SJim Ingham     The number in the placeholder refers to the position/order the actual value \n\
217ebc09c36SJim Ingham     occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
218ebc09c36SJim Ingham     will be replaced with the first argument, all the occurrences of '%2' in the \n\
219ebc09c36SJim Ingham     alias will be replaced with the second argument, and so on.  This also allows \n\
220ebc09c36SJim Ingham     actual arguments to be used multiple times within an alias (see 'process \n\
221ebc09c36SJim Ingham     launch' example below).  So in the 'bfl' case, the actual file value will be \n\
222ebc09c36SJim Ingham     filled in with the first argument following 'bfl' and the actual line number \n\
223ebc09c36SJim Ingham     value will be filled in with the second argument.  The user would use this \n\
224ebc09c36SJim Ingham     alias as follows: \n\
22509799af6SCaroline Tice     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
226ebc09c36SJim Ingham     <... some time later ...> \n\
22709799af6SCaroline Tice     (lldb)  bfl my-file.c 137 \n\
228ebc09c36SJim Ingham     \nThis would be the same as if the user had entered \n\
229ebc09c36SJim Ingham     'breakpoint set -f my-file.c -l 137'. \n\
230ebc09c36SJim Ingham     \nAnother example: \n\
23109799af6SCaroline Tice     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
23209799af6SCaroline Tice     (lldb)  pltty /dev/tty0 \n\
233ebc09c36SJim Ingham            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
234ebc09c36SJim Ingham     \nIf the user always wanted to pass the same value to a particular option, the \n\
235ebc09c36SJim Ingham     alias could be defined with that value directly in the alias as a constant, \n\
236ebc09c36SJim Ingham     rather than using a positional placeholder: \n\
2370708e2c2SSean Callanan     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
238ebc09c36SJim Ingham                                                    // 3 of whatever file is indicated. \n");
239ebc09c36SJim Ingham 
240405fe67fSCaroline Tice         CommandArgumentEntry arg1;
241405fe67fSCaroline Tice         CommandArgumentEntry arg2;
242405fe67fSCaroline Tice         CommandArgumentEntry arg3;
243405fe67fSCaroline Tice         CommandArgumentData alias_arg;
244405fe67fSCaroline Tice         CommandArgumentData cmd_arg;
245405fe67fSCaroline Tice         CommandArgumentData options_arg;
246405fe67fSCaroline Tice 
247405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
248405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
249405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
250405fe67fSCaroline Tice 
251405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
252405fe67fSCaroline Tice         arg1.push_back (alias_arg);
253405fe67fSCaroline Tice 
254405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
255405fe67fSCaroline Tice         cmd_arg.arg_type = eArgTypeCommandName;
256405fe67fSCaroline Tice         cmd_arg.arg_repetition = eArgRepeatPlain;
257405fe67fSCaroline Tice 
258405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
259405fe67fSCaroline Tice         arg2.push_back (cmd_arg);
260405fe67fSCaroline Tice 
261405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
262405fe67fSCaroline Tice         options_arg.arg_type = eArgTypeAliasOptions;
263405fe67fSCaroline Tice         options_arg.arg_repetition = eArgRepeatOptional;
264405fe67fSCaroline Tice 
265405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
266405fe67fSCaroline Tice         arg3.push_back (options_arg);
267405fe67fSCaroline Tice 
268405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
269405fe67fSCaroline Tice         m_arguments.push_back (arg1);
270405fe67fSCaroline Tice         m_arguments.push_back (arg2);
271405fe67fSCaroline Tice         m_arguments.push_back (arg3);
272ebc09c36SJim Ingham     }
273ebc09c36SJim Ingham 
274ebc09c36SJim Ingham     ~CommandObjectCommandsAlias ()
275ebc09c36SJim Ingham     {
276ebc09c36SJim Ingham     }
277ebc09c36SJim Ingham 
278844d2303SCaroline Tice     bool
279844d2303SCaroline Tice     WantsRawCommandString ()
280844d2303SCaroline Tice     {
281844d2303SCaroline Tice         return true;
282844d2303SCaroline Tice     }
283844d2303SCaroline Tice 
284844d2303SCaroline Tice     bool
285844d2303SCaroline Tice     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
286844d2303SCaroline Tice     {
287844d2303SCaroline Tice         Args args (raw_command_line);
288844d2303SCaroline Tice         std::string raw_command_string (raw_command_line);
289844d2303SCaroline Tice 
290844d2303SCaroline Tice         size_t argc = args.GetArgumentCount();
291844d2303SCaroline Tice 
292844d2303SCaroline Tice         if (argc < 2)
293844d2303SCaroline Tice         {
294844d2303SCaroline Tice             result.AppendError ("'alias' requires at least two arguments");
295844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
296844d2303SCaroline Tice             return false;
297844d2303SCaroline Tice         }
298844d2303SCaroline Tice 
299844d2303SCaroline Tice         // Get the alias command.
300844d2303SCaroline Tice 
301844d2303SCaroline Tice         const std::string alias_command = args.GetArgumentAtIndex (0);
302844d2303SCaroline Tice 
303844d2303SCaroline Tice         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
304844d2303SCaroline Tice         // does the stripping itself.
305844d2303SCaroline Tice         size_t pos = raw_command_string.find (alias_command);
306844d2303SCaroline Tice         if (pos == 0)
307844d2303SCaroline Tice         {
308844d2303SCaroline Tice             raw_command_string = raw_command_string.substr (alias_command.size());
309844d2303SCaroline Tice             pos = raw_command_string.find_first_not_of (' ');
310844d2303SCaroline Tice             if ((pos != std::string::npos) && (pos > 0))
311844d2303SCaroline Tice                 raw_command_string = raw_command_string.substr (pos);
312844d2303SCaroline Tice         }
313844d2303SCaroline Tice         else
314844d2303SCaroline Tice         {
315844d2303SCaroline Tice             result.AppendError ("Error parsing command string.  No alias created.");
316844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
317844d2303SCaroline Tice             return false;
318844d2303SCaroline Tice         }
319844d2303SCaroline Tice 
320844d2303SCaroline Tice 
321844d2303SCaroline Tice         // Verify that the command is alias-able.
322844d2303SCaroline Tice         if (m_interpreter.CommandExists (alias_command.c_str()))
323844d2303SCaroline Tice         {
324844d2303SCaroline Tice             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
325844d2303SCaroline Tice                                           alias_command.c_str());
326844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
327844d2303SCaroline Tice             return false;
328844d2303SCaroline Tice         }
329844d2303SCaroline Tice 
330844d2303SCaroline Tice         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
331844d2303SCaroline Tice         // raw_command_string is returned with the name of the command object stripped off the front.
332844d2303SCaroline Tice         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
333844d2303SCaroline Tice 
334844d2303SCaroline Tice         if (!cmd_obj)
335844d2303SCaroline Tice         {
336844d2303SCaroline Tice             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
337844d2303SCaroline Tice                                           "  No alias created.", raw_command_string.c_str());
338844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
339844d2303SCaroline Tice             return false;
340844d2303SCaroline Tice         }
341844d2303SCaroline Tice         else if (!cmd_obj->WantsRawCommandString ())
342844d2303SCaroline Tice         {
343844d2303SCaroline Tice             // Note that args was initialized with the original command, and has not been updated to this point.
344844d2303SCaroline Tice             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
345844d2303SCaroline Tice             return Execute (args, result);
346844d2303SCaroline Tice         }
347844d2303SCaroline Tice         else
348844d2303SCaroline Tice         {
349844d2303SCaroline Tice             // Verify & handle any options/arguments passed to the alias command
350844d2303SCaroline Tice 
351844d2303SCaroline Tice             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
352844d2303SCaroline Tice             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
353844d2303SCaroline Tice 
354ca90c47eSCaroline Tice             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
355844d2303SCaroline Tice 
356ca90c47eSCaroline Tice             if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
357844d2303SCaroline Tice             {
358844d2303SCaroline Tice                 result.AppendError ("Unable to create requested alias.\n");
359ca90c47eSCaroline Tice                 result.SetStatus (eReturnStatusFailed);
360844d2303SCaroline Tice                 return false;
361844d2303SCaroline Tice             }
362844d2303SCaroline Tice 
363844d2303SCaroline Tice             // Create the alias
364844d2303SCaroline Tice             if (m_interpreter.AliasExists (alias_command.c_str())
365844d2303SCaroline Tice                 || m_interpreter.UserCommandExists (alias_command.c_str()))
366844d2303SCaroline Tice             {
367844d2303SCaroline Tice                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
368844d2303SCaroline Tice                 if (temp_option_arg_sp.get())
369844d2303SCaroline Tice                 {
370844d2303SCaroline Tice                     if (option_arg_vector->size() == 0)
371844d2303SCaroline Tice                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
372844d2303SCaroline Tice                 }
373844d2303SCaroline Tice                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
374844d2303SCaroline Tice                                                 alias_command.c_str());
375844d2303SCaroline Tice             }
376844d2303SCaroline Tice 
377472362e6SCaroline Tice             if (cmd_obj_sp)
378472362e6SCaroline Tice             {
379844d2303SCaroline Tice                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
380844d2303SCaroline Tice                 if (option_arg_vector->size() > 0)
381844d2303SCaroline Tice                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
382844d2303SCaroline Tice                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
383844d2303SCaroline Tice             }
384472362e6SCaroline Tice             else
385472362e6SCaroline Tice             {
386472362e6SCaroline Tice                 result.AppendError ("Unable to create requested alias.\n");
387472362e6SCaroline Tice                 result.SetStatus (eReturnStatusFailed);
388472362e6SCaroline Tice             }
389472362e6SCaroline Tice         }
390844d2303SCaroline Tice         return result.Succeeded();
391844d2303SCaroline Tice     }
392ebc09c36SJim Ingham 
393ebc09c36SJim Ingham     bool
394ebc09c36SJim Ingham     Execute
395ebc09c36SJim Ingham     (
396ebc09c36SJim Ingham         Args& args,
397ebc09c36SJim Ingham         CommandReturnObject &result
398ebc09c36SJim Ingham     )
399ebc09c36SJim Ingham     {
400867b185dSCaroline Tice         size_t argc = args.GetArgumentCount();
401ebc09c36SJim Ingham 
402ebc09c36SJim Ingham         if (argc < 2)
403ebc09c36SJim Ingham         {
404ebc09c36SJim Ingham             result.AppendError ("'alias' requires at least two arguments");
405ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
406ebc09c36SJim Ingham             return false;
407ebc09c36SJim Ingham         }
408ebc09c36SJim Ingham 
409ebc09c36SJim Ingham         const std::string alias_command = args.GetArgumentAtIndex(0);
410ebc09c36SJim Ingham         const std::string actual_command = args.GetArgumentAtIndex(1);
411ebc09c36SJim Ingham 
412ebc09c36SJim Ingham         args.Shift();  // Shift the alias command word off the argument vector.
413ebc09c36SJim Ingham         args.Shift();  // Shift the old command word off the argument vector.
414ebc09c36SJim Ingham 
415ebc09c36SJim Ingham         // Verify that the command is alias'able, and get the appropriate command object.
416ebc09c36SJim Ingham 
417a7015092SGreg Clayton         if (m_interpreter.CommandExists (alias_command.c_str()))
418ebc09c36SJim Ingham         {
419ebc09c36SJim Ingham             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
420ebc09c36SJim Ingham                                          alias_command.c_str());
421ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
422ebc09c36SJim Ingham         }
423ebc09c36SJim Ingham         else
424ebc09c36SJim Ingham         {
425a7015092SGreg Clayton              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
426ebc09c36SJim Ingham              CommandObjectSP subcommand_obj_sp;
427ebc09c36SJim Ingham              bool use_subcommand = false;
428ebc09c36SJim Ingham              if (command_obj_sp.get())
429ebc09c36SJim Ingham              {
430ebc09c36SJim Ingham                  CommandObject *cmd_obj = command_obj_sp.get();
431c982c768SGreg Clayton                  CommandObject *sub_cmd_obj = NULL;
432ebc09c36SJim Ingham                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
433ebc09c36SJim Ingham                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
434ebc09c36SJim Ingham 
435844d2303SCaroline Tice                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
436ebc09c36SJim Ingham                  {
437ebc09c36SJim Ingham                      if (argc >= 3)
438ebc09c36SJim Ingham                      {
439ebc09c36SJim Ingham                          const std::string sub_command = args.GetArgumentAtIndex(0);
440ebc09c36SJim Ingham                          assert (sub_command.length() != 0);
441ebc09c36SJim Ingham                          subcommand_obj_sp =
442ebc09c36SJim Ingham                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
443ebc09c36SJim Ingham                          if (subcommand_obj_sp.get())
444ebc09c36SJim Ingham                          {
445ebc09c36SJim Ingham                              sub_cmd_obj = subcommand_obj_sp.get();
446ebc09c36SJim Ingham                              use_subcommand = true;
447ebc09c36SJim Ingham                              args.Shift();  // Shift the sub_command word off the argument vector.
448844d2303SCaroline Tice                              cmd_obj = sub_cmd_obj;
449ebc09c36SJim Ingham                          }
450ebc09c36SJim Ingham                          else
451ebc09c36SJim Ingham                          {
452f415eeb4SCaroline Tice                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
453f415eeb4SCaroline Tice                                                           "Unable to create alias.\n",
454f415eeb4SCaroline Tice                                                           sub_command.c_str(), actual_command.c_str());
455ebc09c36SJim Ingham                              result.SetStatus (eReturnStatusFailed);
456ebc09c36SJim Ingham                              return false;
457ebc09c36SJim Ingham                          }
458ebc09c36SJim Ingham                      }
459ebc09c36SJim Ingham                  }
460ebc09c36SJim Ingham 
461ebc09c36SJim Ingham                  // Verify & handle any options/arguments passed to the alias command
462ebc09c36SJim Ingham 
463ebc09c36SJim Ingham                  if (args.GetArgumentCount () > 0)
464ebc09c36SJim Ingham                  {
465ca90c47eSCaroline Tice                     CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
466ebc09c36SJim Ingham                     if (use_subcommand)
467ca90c47eSCaroline Tice                         tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
468ca90c47eSCaroline Tice 
469ca90c47eSCaroline Tice                     std::string args_string;
470ca90c47eSCaroline Tice                     args.GetCommandString (args_string);
471ca90c47eSCaroline Tice 
472ca90c47eSCaroline Tice                     if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
473ebc09c36SJim Ingham                     {
474ca90c47eSCaroline Tice                         result.AppendError ("Unable to create requested alias.\n");
475ca90c47eSCaroline Tice                         result.SetStatus (eReturnStatusFailed);
476e7941795SCaroline Tice                         return false;
477867b185dSCaroline Tice                     }
478867b185dSCaroline Tice                  }
479867b185dSCaroline Tice 
480ebc09c36SJim Ingham                  // Create the alias.
481ebc09c36SJim Ingham 
482a7015092SGreg Clayton                  if (m_interpreter.AliasExists (alias_command.c_str())
483a7015092SGreg Clayton                      || m_interpreter.UserCommandExists (alias_command.c_str()))
484ebc09c36SJim Ingham                  {
485a7015092SGreg Clayton                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
486ebc09c36SJim Ingham                      if (tmp_option_arg_sp.get())
487ebc09c36SJim Ingham                      {
488ebc09c36SJim Ingham                          if (option_arg_vector->size() == 0)
489a7015092SGreg Clayton                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
490ebc09c36SJim Ingham                      }
491ebc09c36SJim Ingham                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
492ebc09c36SJim Ingham                                                      alias_command.c_str());
493ebc09c36SJim Ingham                  }
494ebc09c36SJim Ingham 
495ebc09c36SJim Ingham                  if (use_subcommand)
496a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
497ebc09c36SJim Ingham                  else
498a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
499ebc09c36SJim Ingham                  if (option_arg_vector->size() > 0)
500a7015092SGreg Clayton                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
501ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
502ebc09c36SJim Ingham              }
503ebc09c36SJim Ingham              else
504ebc09c36SJim Ingham              {
505ebc09c36SJim Ingham                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
506ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusFailed);
507e7941795SCaroline Tice                  return false;
508ebc09c36SJim Ingham              }
509ebc09c36SJim Ingham         }
510ebc09c36SJim Ingham 
511ebc09c36SJim Ingham         return result.Succeeded();
512ebc09c36SJim Ingham     }
513ebc09c36SJim Ingham };
514ebc09c36SJim Ingham 
515ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
516ebc09c36SJim Ingham //-------------------------------------------------------------------------
517ebc09c36SJim Ingham // CommandObjectCommandsUnalias
518ebc09c36SJim Ingham //-------------------------------------------------------------------------
519ebc09c36SJim Ingham 
520ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject
521ebc09c36SJim Ingham {
522ebc09c36SJim Ingham public:
523a7015092SGreg Clayton     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
524a7015092SGreg Clayton         CommandObject (interpreter,
5250e5e5a79SGreg Clayton                        "command unalias",
52686ddae50SCaroline Tice                        "Allow the user to remove/delete a user-defined command abbreviation.",
527405fe67fSCaroline Tice                        NULL)
528ebc09c36SJim Ingham     {
529405fe67fSCaroline Tice         CommandArgumentEntry arg;
530405fe67fSCaroline Tice         CommandArgumentData alias_arg;
531405fe67fSCaroline Tice 
532405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
533405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
534405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
535405fe67fSCaroline Tice 
536405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
537405fe67fSCaroline Tice         arg.push_back (alias_arg);
538405fe67fSCaroline Tice 
539405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
540405fe67fSCaroline Tice         m_arguments.push_back (arg);
541ebc09c36SJim Ingham     }
542ebc09c36SJim Ingham 
543ebc09c36SJim Ingham     ~CommandObjectCommandsUnalias()
544ebc09c36SJim Ingham     {
545ebc09c36SJim Ingham     }
546ebc09c36SJim Ingham 
547ebc09c36SJim Ingham 
548ebc09c36SJim Ingham     bool
549ebc09c36SJim Ingham     Execute
550ebc09c36SJim Ingham     (
551ebc09c36SJim Ingham         Args& args,
552ebc09c36SJim Ingham         CommandReturnObject &result
553ebc09c36SJim Ingham     )
554ebc09c36SJim Ingham     {
555ebc09c36SJim Ingham         CommandObject::CommandMap::iterator pos;
556ebc09c36SJim Ingham         CommandObject *cmd_obj;
557ebc09c36SJim Ingham 
558ebc09c36SJim Ingham         if (args.GetArgumentCount() != 0)
559ebc09c36SJim Ingham         {
560ebc09c36SJim Ingham             const char *command_name = args.GetArgumentAtIndex(0);
561a7015092SGreg Clayton             cmd_obj = m_interpreter.GetCommandObject(command_name);
562ebc09c36SJim Ingham             if (cmd_obj)
563ebc09c36SJim Ingham             {
564a7015092SGreg Clayton                 if (m_interpreter.CommandExists (command_name))
565ebc09c36SJim Ingham                 {
566ebc09c36SJim Ingham                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
567ebc09c36SJim Ingham                                                   command_name);
568ebc09c36SJim Ingham                     result.SetStatus (eReturnStatusFailed);
569ebc09c36SJim Ingham                 }
570ebc09c36SJim Ingham                 else
571ebc09c36SJim Ingham                 {
572ebc09c36SJim Ingham 
573a7015092SGreg Clayton                     if (m_interpreter.RemoveAlias (command_name) == false)
574ebc09c36SJim Ingham                     {
575a7015092SGreg Clayton                         if (m_interpreter.AliasExists (command_name))
576ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
577ebc09c36SJim Ingham                                                           command_name);
578ebc09c36SJim Ingham                         else
579ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
580ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusFailed);
581ebc09c36SJim Ingham                     }
582ebc09c36SJim Ingham                     else
583ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
584ebc09c36SJim Ingham                 }
585ebc09c36SJim Ingham             }
586ebc09c36SJim Ingham             else
587ebc09c36SJim Ingham             {
588ebc09c36SJim Ingham                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
589ebc09c36SJim Ingham                                               "current list of commands.\n",
590ebc09c36SJim Ingham                                              command_name);
591ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusFailed);
592ebc09c36SJim Ingham             }
593ebc09c36SJim Ingham         }
594ebc09c36SJim Ingham         else
595ebc09c36SJim Ingham         {
596ebc09c36SJim Ingham             result.AppendError ("must call 'unalias' with a valid alias");
597ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
598ebc09c36SJim Ingham         }
599ebc09c36SJim Ingham 
600ebc09c36SJim Ingham         return result.Succeeded();
601ebc09c36SJim Ingham     }
602ebc09c36SJim Ingham };
603ebc09c36SJim Ingham 
604de164aaaSGreg Clayton #pragma mark CommandObjectCommandsAddRegex
605de164aaaSGreg Clayton //-------------------------------------------------------------------------
606de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
607de164aaaSGreg Clayton //-------------------------------------------------------------------------
608de164aaaSGreg Clayton 
609de164aaaSGreg Clayton class CommandObjectCommandsAddRegex : public CommandObject
610de164aaaSGreg Clayton {
611de164aaaSGreg Clayton public:
612de164aaaSGreg Clayton     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
613de164aaaSGreg Clayton         CommandObject (interpreter,
6140e5e5a79SGreg Clayton                        "command regex",
615de164aaaSGreg Clayton                        "Allow the user to create a regular expression command.",
6160e5e5a79SGreg Clayton                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
617de164aaaSGreg Clayton         m_options (interpreter)
618de164aaaSGreg Clayton     {
6190e5e5a79SGreg Clayton         SetHelpLong(
6200e5e5a79SGreg Clayton "This command allows the user to create powerful regular expression commands\n"
6210e5e5a79SGreg Clayton "with substitutions. The regular expressions and substitutions are specified\n"
6220e5e5a79SGreg Clayton "using the regular exression substitution format of:\n"
6230e5e5a79SGreg Clayton "\n"
6240e5e5a79SGreg Clayton "    s/<regex>/<subst>/\n"
6250e5e5a79SGreg Clayton "\n"
6260e5e5a79SGreg Clayton "<regex> is a regular expression that can use parenthesis to capture regular\n"
6270e5e5a79SGreg Clayton "expression input and substitute the captured matches in the output using %1\n"
6280e5e5a79SGreg Clayton "for the first match, %2 for the second, and so on.\n"
6290e5e5a79SGreg Clayton "\n"
6300e5e5a79SGreg Clayton "The regular expressions can all be specified on the command line if more than\n"
6310e5e5a79SGreg Clayton "one argument is provided. If just the command name is provided on the command\n"
6320e5e5a79SGreg Clayton "line, then the regular expressions and substitutions can be entered on separate\n"
6330e5e5a79SGreg Clayton " lines, followed by an empty line to terminate the command definition.\n"
6340e5e5a79SGreg Clayton "\n"
6350e5e5a79SGreg Clayton "EXAMPLES\n"
6360e5e5a79SGreg Clayton "\n"
6370e5e5a79SGreg Clayton "The following example with define a regular expression command named 'f' that\n"
6380e5e5a79SGreg Clayton "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
6390e5e5a79SGreg Clayton "a number follows 'f':\n"
6400e5e5a79SGreg Clayton "(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
6410e5e5a79SGreg Clayton                     );
642de164aaaSGreg Clayton     }
643de164aaaSGreg Clayton 
644de164aaaSGreg Clayton     ~CommandObjectCommandsAddRegex()
645de164aaaSGreg Clayton     {
646de164aaaSGreg Clayton     }
647de164aaaSGreg Clayton 
648de164aaaSGreg Clayton 
649de164aaaSGreg Clayton     bool
650de164aaaSGreg Clayton     Execute (Args& args, CommandReturnObject &result)
651de164aaaSGreg Clayton     {
6520e5e5a79SGreg Clayton         const size_t argc = args.GetArgumentCount();
6530e5e5a79SGreg Clayton         if (argc == 0)
654de164aaaSGreg Clayton         {
6550e5e5a79SGreg Clayton             result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
6560e5e5a79SGreg Clayton             result.SetStatus (eReturnStatusFailed);
6570e5e5a79SGreg Clayton         }
6580e5e5a79SGreg Clayton         else
6590e5e5a79SGreg Clayton         {
6600e5e5a79SGreg Clayton             Error error;
661de164aaaSGreg Clayton             const char *name = args.GetArgumentAtIndex(0);
662de164aaaSGreg Clayton             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
663de164aaaSGreg Clayton                                                                  name,
664de164aaaSGreg Clayton                                                                  m_options.GetHelp (),
665de164aaaSGreg Clayton                                                                  m_options.GetSyntax (),
666de164aaaSGreg Clayton                                                                  10));
6670e5e5a79SGreg Clayton 
6680e5e5a79SGreg Clayton             if (argc == 1)
6690e5e5a79SGreg Clayton             {
6700e5e5a79SGreg Clayton                 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
671de164aaaSGreg Clayton                 if (reader_sp)
672de164aaaSGreg Clayton                 {
6730e5e5a79SGreg Clayton                     error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
674de164aaaSGreg Clayton                                                   this,                         // baton
675de164aaaSGreg Clayton                                                   eInputReaderGranularityLine,  // token size, to pass to callback function
6760e5e5a79SGreg Clayton                                                   NULL,                         // end token
677de164aaaSGreg Clayton                                                   "> ",                         // prompt
6780e5e5a79SGreg Clayton                                                   true);                        // echo input
6790e5e5a79SGreg Clayton                     if (error.Success())
680de164aaaSGreg Clayton                     {
681de164aaaSGreg Clayton                         m_interpreter.GetDebugger().PushInputReader (reader_sp);
682de164aaaSGreg Clayton                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
6830e5e5a79SGreg Clayton                         return true;
684de164aaaSGreg Clayton                     }
685de164aaaSGreg Clayton                 }
686de164aaaSGreg Clayton             }
687de164aaaSGreg Clayton             else
688de164aaaSGreg Clayton             {
6890e5e5a79SGreg Clayton                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
6900e5e5a79SGreg Clayton                 {
6910e5e5a79SGreg Clayton                     llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
6920e5e5a79SGreg Clayton                     error = AppendRegexSubstitution (arg_strref);
6930e5e5a79SGreg Clayton                     if (error.Fail())
6940e5e5a79SGreg Clayton                         break;
6950e5e5a79SGreg Clayton                 }
6960e5e5a79SGreg Clayton 
6970e5e5a79SGreg Clayton                 if (error.Success())
6980e5e5a79SGreg Clayton                 {
6990e5e5a79SGreg Clayton                     AddRegexCommandToInterpreter();
7000e5e5a79SGreg Clayton                 }
7010e5e5a79SGreg Clayton             }
7020e5e5a79SGreg Clayton             if (error.Fail())
7030e5e5a79SGreg Clayton             {
7040e5e5a79SGreg Clayton                 result.AppendError (error.AsCString());
705de164aaaSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
706de164aaaSGreg Clayton             }
7070e5e5a79SGreg Clayton         }
7080e5e5a79SGreg Clayton 
709de164aaaSGreg Clayton         return result.Succeeded();
710de164aaaSGreg Clayton     }
711de164aaaSGreg Clayton 
7120e5e5a79SGreg Clayton     Error
7130e5e5a79SGreg Clayton     AppendRegexSubstitution (const llvm::StringRef &regex_sed)
714de164aaaSGreg Clayton     {
7150e5e5a79SGreg Clayton         Error error;
7160e5e5a79SGreg Clayton 
7170e5e5a79SGreg Clayton         if (m_regex_cmd_ap.get() == NULL)
718de164aaaSGreg Clayton         {
7190e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
7200e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
7210e5e5a79SGreg Clayton                                            regex_sed.data());
7220e5e5a79SGreg Clayton             return error;
723de164aaaSGreg Clayton         }
7240e5e5a79SGreg Clayton 
7250e5e5a79SGreg Clayton         size_t regex_sed_size = regex_sed.size();
7260e5e5a79SGreg Clayton 
7270e5e5a79SGreg Clayton         if (regex_sed_size <= 1)
7280e5e5a79SGreg Clayton         {
7290e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
7300e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
7310e5e5a79SGreg Clayton                                            regex_sed.data());
7320e5e5a79SGreg Clayton             return error;
7330e5e5a79SGreg Clayton         }
7340e5e5a79SGreg Clayton 
7350e5e5a79SGreg Clayton         if (regex_sed[0] != 's')
7360e5e5a79SGreg Clayton         {
7370e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
7380e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
7390e5e5a79SGreg Clayton                                            regex_sed.data());
7400e5e5a79SGreg Clayton             return error;
7410e5e5a79SGreg Clayton         }
7420e5e5a79SGreg Clayton         const size_t first_separator_char_pos = 1;
7430e5e5a79SGreg Clayton         // use the char that follows 's' as the regex separator character
7440e5e5a79SGreg Clayton         // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
7450e5e5a79SGreg Clayton         const char separator_char = regex_sed[first_separator_char_pos];
7460e5e5a79SGreg Clayton         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
7470e5e5a79SGreg Clayton 
7480e5e5a79SGreg Clayton         if (second_separator_char_pos == std::string::npos)
7490e5e5a79SGreg Clayton         {
7500e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
7510e5e5a79SGreg Clayton                                            separator_char,
7520e5e5a79SGreg Clayton                                            (int)(regex_sed.size() - first_separator_char_pos - 1),
7530e5e5a79SGreg Clayton                                            regex_sed.data() + (first_separator_char_pos + 1));
7540e5e5a79SGreg Clayton             return error;
7550e5e5a79SGreg Clayton         }
7560e5e5a79SGreg Clayton 
7570e5e5a79SGreg Clayton         const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
7580e5e5a79SGreg Clayton 
7590e5e5a79SGreg Clayton         if (third_separator_char_pos == std::string::npos)
7600e5e5a79SGreg Clayton         {
7610e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
7620e5e5a79SGreg Clayton                                            separator_char,
7630e5e5a79SGreg Clayton                                            (int)(regex_sed.size() - second_separator_char_pos - 1),
7640e5e5a79SGreg Clayton                                            regex_sed.data() + (second_separator_char_pos + 1));
7650e5e5a79SGreg Clayton             return error;
7660e5e5a79SGreg Clayton         }
7670e5e5a79SGreg Clayton 
7680e5e5a79SGreg Clayton         if (third_separator_char_pos != regex_sed_size - 1)
7690e5e5a79SGreg Clayton         {
7700e5e5a79SGreg Clayton             // Make sure that everything that follows the last regex
7710e5e5a79SGreg Clayton             // separator char
7720e5e5a79SGreg Clayton             if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
7730e5e5a79SGreg Clayton             {
7740e5e5a79SGreg Clayton                 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
7750e5e5a79SGreg Clayton                                                (int)third_separator_char_pos + 1,
7760e5e5a79SGreg Clayton                                                regex_sed.data(),
7770e5e5a79SGreg Clayton                                                (int)(regex_sed.size() - third_separator_char_pos - 1),
7780e5e5a79SGreg Clayton                                                regex_sed.data() + (third_separator_char_pos + 1));
7790e5e5a79SGreg Clayton                 return error;
7800e5e5a79SGreg Clayton             }
7810e5e5a79SGreg Clayton 
7820e5e5a79SGreg Clayton         }
7830e5e5a79SGreg Clayton         else if (first_separator_char_pos + 1 == second_separator_char_pos)
7840e5e5a79SGreg Clayton         {
7850e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
7860e5e5a79SGreg Clayton                                            separator_char,
7870e5e5a79SGreg Clayton                                            separator_char,
7880e5e5a79SGreg Clayton                                            separator_char,
7890e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
7900e5e5a79SGreg Clayton                                            regex_sed.data());
7910e5e5a79SGreg Clayton             return error;
7920e5e5a79SGreg Clayton         }
7930e5e5a79SGreg Clayton         else if (second_separator_char_pos + 1 == third_separator_char_pos)
7940e5e5a79SGreg Clayton         {
7950e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
7960e5e5a79SGreg Clayton                                            separator_char,
7970e5e5a79SGreg Clayton                                            separator_char,
7980e5e5a79SGreg Clayton                                            separator_char,
7990e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
8000e5e5a79SGreg Clayton                                            regex_sed.data());
8010e5e5a79SGreg Clayton             return error;
8020e5e5a79SGreg Clayton         }
8030e5e5a79SGreg Clayton         std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
8040e5e5a79SGreg Clayton         std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
8050e5e5a79SGreg Clayton         m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
8060e5e5a79SGreg Clayton                                          subst.c_str());
8070e5e5a79SGreg Clayton         return error;
808de164aaaSGreg Clayton     }
809de164aaaSGreg Clayton 
810de164aaaSGreg Clayton     void
8110e5e5a79SGreg Clayton     AddRegexCommandToInterpreter()
812de164aaaSGreg Clayton     {
813de164aaaSGreg Clayton         if (m_regex_cmd_ap.get())
814de164aaaSGreg Clayton         {
815de164aaaSGreg Clayton             if (m_regex_cmd_ap->HasRegexEntries())
816de164aaaSGreg Clayton             {
817de164aaaSGreg Clayton                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
818de164aaaSGreg Clayton                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
819de164aaaSGreg Clayton             }
820de164aaaSGreg Clayton         }
821de164aaaSGreg Clayton     }
822de164aaaSGreg Clayton 
8230e5e5a79SGreg Clayton     void
8240e5e5a79SGreg Clayton     InputReaderDidCancel()
8250e5e5a79SGreg Clayton     {
8260e5e5a79SGreg Clayton         m_regex_cmd_ap.reset();
8270e5e5a79SGreg Clayton     }
8280e5e5a79SGreg Clayton 
829de164aaaSGreg Clayton     static size_t
830de164aaaSGreg Clayton     InputReaderCallback (void *baton,
831de164aaaSGreg Clayton                          InputReader &reader,
832de164aaaSGreg Clayton                          lldb::InputReaderAction notification,
833de164aaaSGreg Clayton                          const char *bytes,
834de164aaaSGreg Clayton                          size_t bytes_len);
835de164aaaSGreg Clayton private:
836de164aaaSGreg Clayton     std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
837de164aaaSGreg Clayton 
838de164aaaSGreg Clayton      class CommandOptions : public Options
839de164aaaSGreg Clayton      {
840de164aaaSGreg Clayton      public:
841de164aaaSGreg Clayton 
842de164aaaSGreg Clayton          CommandOptions (CommandInterpreter &interpreter) :
843de164aaaSGreg Clayton             Options (interpreter)
844de164aaaSGreg Clayton          {
845de164aaaSGreg Clayton          }
846de164aaaSGreg Clayton 
847de164aaaSGreg Clayton          virtual
848de164aaaSGreg Clayton          ~CommandOptions (){}
849de164aaaSGreg Clayton 
850de164aaaSGreg Clayton          virtual Error
851de164aaaSGreg Clayton          SetOptionValue (uint32_t option_idx, const char *option_arg)
852de164aaaSGreg Clayton          {
853de164aaaSGreg Clayton              Error error;
854de164aaaSGreg Clayton              char short_option = (char) m_getopt_table[option_idx].val;
855de164aaaSGreg Clayton 
856de164aaaSGreg Clayton              switch (short_option)
857de164aaaSGreg Clayton              {
858de164aaaSGreg Clayton                  case 'h':
859de164aaaSGreg Clayton                      m_help.assign (option_arg);
860de164aaaSGreg Clayton                      break;
861de164aaaSGreg Clayton                  case 's':
862de164aaaSGreg Clayton                      m_syntax.assign (option_arg);
863de164aaaSGreg Clayton                      break;
864de164aaaSGreg Clayton 
865de164aaaSGreg Clayton                  default:
866de164aaaSGreg Clayton                      error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
867de164aaaSGreg Clayton                      break;
868de164aaaSGreg Clayton              }
869de164aaaSGreg Clayton 
870de164aaaSGreg Clayton              return error;
871de164aaaSGreg Clayton          }
872de164aaaSGreg Clayton 
873de164aaaSGreg Clayton          void
874de164aaaSGreg Clayton          OptionParsingStarting ()
875de164aaaSGreg Clayton          {
876de164aaaSGreg Clayton              m_help.clear();
877de164aaaSGreg Clayton              m_syntax.clear();
878de164aaaSGreg Clayton          }
879de164aaaSGreg Clayton 
880de164aaaSGreg Clayton          const OptionDefinition*
881de164aaaSGreg Clayton          GetDefinitions ()
882de164aaaSGreg Clayton          {
883de164aaaSGreg Clayton              return g_option_table;
884de164aaaSGreg Clayton          }
885de164aaaSGreg Clayton 
886de164aaaSGreg Clayton          // Options table: Required for subclasses of Options.
887de164aaaSGreg Clayton 
888de164aaaSGreg Clayton          static OptionDefinition g_option_table[];
889de164aaaSGreg Clayton 
890de164aaaSGreg Clayton          const char *
891de164aaaSGreg Clayton          GetHelp ()
892de164aaaSGreg Clayton          {
893de164aaaSGreg Clayton              if (m_help.empty())
894de164aaaSGreg Clayton                  return NULL;
895de164aaaSGreg Clayton              return m_help.c_str();
896de164aaaSGreg Clayton          }
897de164aaaSGreg Clayton          const char *
898de164aaaSGreg Clayton          GetSyntax ()
899de164aaaSGreg Clayton          {
900de164aaaSGreg Clayton              if (m_syntax.empty())
901de164aaaSGreg Clayton                  return NULL;
902de164aaaSGreg Clayton              return m_syntax.c_str();
903de164aaaSGreg Clayton          }
904de164aaaSGreg Clayton          // Instance variables to hold the values for command options.
905de164aaaSGreg Clayton      protected:
906de164aaaSGreg Clayton          std::string m_help;
907de164aaaSGreg Clayton          std::string m_syntax;
908de164aaaSGreg Clayton      };
909de164aaaSGreg Clayton 
910de164aaaSGreg Clayton      CommandOptions m_options;
911de164aaaSGreg Clayton 
912de164aaaSGreg Clayton      virtual Options *
913de164aaaSGreg Clayton      GetOptions ()
914de164aaaSGreg Clayton      {
915de164aaaSGreg Clayton          return &m_options;
916de164aaaSGreg Clayton      }
917de164aaaSGreg Clayton 
918de164aaaSGreg Clayton };
919de164aaaSGreg Clayton 
920de164aaaSGreg Clayton size_t
921de164aaaSGreg Clayton CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
922de164aaaSGreg Clayton                                                     InputReader &reader,
923de164aaaSGreg Clayton                                                     lldb::InputReaderAction notification,
924de164aaaSGreg Clayton                                                     const char *bytes,
925de164aaaSGreg Clayton                                                     size_t bytes_len)
926de164aaaSGreg Clayton {
927de164aaaSGreg Clayton     CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
928*d61c10bcSCaroline Tice     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
929de164aaaSGreg Clayton 
930de164aaaSGreg Clayton     switch (notification)
931de164aaaSGreg Clayton     {
932de164aaaSGreg Clayton         case eInputReaderActivate:
933*d61c10bcSCaroline Tice             if (!batch_mode)
93415356e7fSCaroline Tice             {
93515356e7fSCaroline Tice                 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
93615356e7fSCaroline Tice                 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
93715356e7fSCaroline Tice                 out_stream->Flush();
93815356e7fSCaroline Tice             }
939de164aaaSGreg Clayton             break;
940de164aaaSGreg Clayton         case eInputReaderReactivate:
941de164aaaSGreg Clayton             break;
942de164aaaSGreg Clayton 
943de164aaaSGreg Clayton         case eInputReaderDeactivate:
944de164aaaSGreg Clayton             break;
945de164aaaSGreg Clayton 
946969ed3d1SCaroline Tice         case eInputReaderAsynchronousOutputWritten:
947969ed3d1SCaroline Tice             break;
948969ed3d1SCaroline Tice 
949de164aaaSGreg Clayton         case eInputReaderGotToken:
9500e5e5a79SGreg Clayton             while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
9510e5e5a79SGreg Clayton                 --bytes_len;
952de164aaaSGreg Clayton             if (bytes_len == 0)
953de164aaaSGreg Clayton                 reader.SetIsDone(true);
954de164aaaSGreg Clayton             else if (bytes)
955de164aaaSGreg Clayton             {
9560e5e5a79SGreg Clayton                 llvm::StringRef bytes_strref (bytes, bytes_len);
9570e5e5a79SGreg Clayton                 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
9580e5e5a79SGreg Clayton                 if (error.Fail())
959de164aaaSGreg Clayton                 {
960*d61c10bcSCaroline Tice                     if (!batch_mode)
961*d61c10bcSCaroline Tice                     {
96215356e7fSCaroline Tice                         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
96315356e7fSCaroline Tice                         out_stream->Printf("error: %s\n", error.AsCString());
96415356e7fSCaroline Tice                         out_stream->Flush();
965*d61c10bcSCaroline Tice                     }
9660e5e5a79SGreg Clayton                     add_regex_cmd->InputReaderDidCancel ();
9670e5e5a79SGreg Clayton                     reader.SetIsDone (true);
968de164aaaSGreg Clayton                 }
969de164aaaSGreg Clayton             }
970de164aaaSGreg Clayton             break;
971de164aaaSGreg Clayton 
972de164aaaSGreg Clayton         case eInputReaderInterrupt:
97315356e7fSCaroline Tice             {
974de164aaaSGreg Clayton                 reader.SetIsDone (true);
975*d61c10bcSCaroline Tice                 if (!batch_mode)
976*d61c10bcSCaroline Tice                 {
97715356e7fSCaroline Tice                     StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
97815356e7fSCaroline Tice                     out_stream->PutCString("Regular expression command creations was cancelled.\n");
97915356e7fSCaroline Tice                     out_stream->Flush();
980*d61c10bcSCaroline Tice                 }
9810e5e5a79SGreg Clayton                 add_regex_cmd->InputReaderDidCancel ();
98215356e7fSCaroline Tice             }
983de164aaaSGreg Clayton             break;
984de164aaaSGreg Clayton 
985de164aaaSGreg Clayton         case eInputReaderEndOfFile:
986de164aaaSGreg Clayton             reader.SetIsDone (true);
987de164aaaSGreg Clayton             break;
988de164aaaSGreg Clayton 
989de164aaaSGreg Clayton         case eInputReaderDone:
9900e5e5a79SGreg Clayton             add_regex_cmd->AddRegexCommandToInterpreter();
991de164aaaSGreg Clayton             break;
992de164aaaSGreg Clayton     }
993de164aaaSGreg Clayton 
994de164aaaSGreg Clayton     return bytes_len;
995de164aaaSGreg Clayton }
996de164aaaSGreg Clayton 
997de164aaaSGreg Clayton 
998de164aaaSGreg Clayton OptionDefinition
999de164aaaSGreg Clayton CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1000de164aaaSGreg Clayton {
1001de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "help"  , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
1002de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1003de164aaaSGreg Clayton { 0             , false,  NULL   , 0  , 0                , NULL, 0, eArgTypeNone, NULL }
1004de164aaaSGreg Clayton };
1005de164aaaSGreg Clayton 
1006de164aaaSGreg Clayton 
1007ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
1008ebc09c36SJim Ingham 
1009ebc09c36SJim Ingham //-------------------------------------------------------------------------
1010ebc09c36SJim Ingham // CommandObjectMultiwordCommands
1011ebc09c36SJim Ingham //-------------------------------------------------------------------------
1012ebc09c36SJim Ingham 
1013ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
1014a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
10150e5e5a79SGreg Clayton                             "command",
10163f4c09c1SCaroline Tice                             "A set of commands for managing or customizing the debugger commands.",
10170e5e5a79SGreg Clayton                             "command <subcommand> [<subcommand-options>]")
1018ebc09c36SJim Ingham {
1019a7015092SGreg Clayton     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1020a7015092SGreg Clayton     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1021a7015092SGreg Clayton     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
1022de164aaaSGreg Clayton     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
1023ebc09c36SJim Ingham }
1024ebc09c36SJim Ingham 
1025ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1026ebc09c36SJim Ingham {
1027ebc09c36SJim Ingham }
1028ebc09c36SJim Ingham 
1029