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
18*be93a35aSEnrico Granata #include "CommandObjectPythonFunction.h"
19ebc09c36SJim Ingham #include "lldb/Core/Debugger.h"
20de164aaaSGreg Clayton #include "lldb/Core/InputReader.h"
21*be93a35aSEnrico Granata #include "lldb/Core/InputReaderEZ.h"
22*be93a35aSEnrico Granata #include "lldb/Core/StringList.h"
23de164aaaSGreg Clayton #include "lldb/Interpreter/Args.h"
24ebc09c36SJim Ingham #include "lldb/Interpreter/CommandInterpreter.h"
25de164aaaSGreg Clayton #include "lldb/Interpreter/CommandObjectRegexCommand.h"
26ebc09c36SJim Ingham #include "lldb/Interpreter/CommandReturnObject.h"
27ebc09c36SJim Ingham #include "lldb/Interpreter/Options.h"
28ebc09c36SJim Ingham 
29ebc09c36SJim Ingham using namespace lldb;
30ebc09c36SJim Ingham using namespace lldb_private;
31ebc09c36SJim Ingham 
32ebc09c36SJim Ingham //-------------------------------------------------------------------------
33ebc09c36SJim Ingham // CommandObjectCommandsSource
34ebc09c36SJim Ingham //-------------------------------------------------------------------------
35ebc09c36SJim Ingham 
36a5a97ebeSJim Ingham class CommandObjectCommandsHistory : public CommandObject
37a5a97ebeSJim Ingham {
38a5a97ebeSJim Ingham private:
39a5a97ebeSJim Ingham 
40a5a97ebeSJim Ingham     class CommandOptions : public Options
41a5a97ebeSJim Ingham     {
42a5a97ebeSJim Ingham     public:
43a5a97ebeSJim Ingham 
44a5a97ebeSJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
45a5a97ebeSJim Ingham             Options (interpreter)
46a5a97ebeSJim Ingham         {
47a5a97ebeSJim Ingham         }
48a5a97ebeSJim Ingham 
49a5a97ebeSJim Ingham         virtual
50a5a97ebeSJim Ingham         ~CommandOptions (){}
51a5a97ebeSJim Ingham 
52a5a97ebeSJim Ingham         virtual Error
53a5a97ebeSJim Ingham         SetOptionValue (uint32_t option_idx, const char *option_arg)
54a5a97ebeSJim Ingham         {
55a5a97ebeSJim Ingham             Error error;
56a5a97ebeSJim Ingham             char short_option = (char) m_getopt_table[option_idx].val;
57a5a97ebeSJim Ingham             bool success;
58a5a97ebeSJim Ingham 
59a5a97ebeSJim Ingham             switch (short_option)
60a5a97ebeSJim Ingham             {
61a5a97ebeSJim Ingham                 case 'c':
62a5a97ebeSJim Ingham                     m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
63a5a97ebeSJim Ingham                     if (!success)
64a5a97ebeSJim Ingham                         error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
65a5a97ebeSJim Ingham                     if (m_end_idx != 0)
66a5a97ebeSJim Ingham                         m_end_idx--;
67a5a97ebeSJim Ingham                     m_start_idx = 0;
68a5a97ebeSJim Ingham                     break;
69a5a97ebeSJim Ingham                 case 'e':
70a5a97ebeSJim Ingham                     m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
71a5a97ebeSJim Ingham                     if (!success)
72a5a97ebeSJim Ingham                         error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
73a5a97ebeSJim Ingham                     break;
74a5a97ebeSJim Ingham                 case 's':
75a5a97ebeSJim Ingham                     m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
76a5a97ebeSJim Ingham                     if (!success)
77a5a97ebeSJim Ingham                         error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
78a5a97ebeSJim Ingham                     break;
79a5a97ebeSJim Ingham                 default:
80a5a97ebeSJim Ingham                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
81a5a97ebeSJim Ingham                     break;
82a5a97ebeSJim Ingham             }
83a5a97ebeSJim Ingham 
84a5a97ebeSJim Ingham             return error;
85a5a97ebeSJim Ingham         }
86a5a97ebeSJim Ingham 
87a5a97ebeSJim Ingham         void
88a5a97ebeSJim Ingham         OptionParsingStarting ()
89a5a97ebeSJim Ingham         {
90a5a97ebeSJim Ingham             m_start_idx = 0;
91a5a97ebeSJim Ingham             m_end_idx = UINT_MAX;
92a5a97ebeSJim Ingham         }
93a5a97ebeSJim Ingham 
94a5a97ebeSJim Ingham         const OptionDefinition*
95a5a97ebeSJim Ingham         GetDefinitions ()
96a5a97ebeSJim Ingham         {
97a5a97ebeSJim Ingham             return g_option_table;
98a5a97ebeSJim Ingham         }
99a5a97ebeSJim Ingham 
100a5a97ebeSJim Ingham         // Options table: Required for subclasses of Options.
101a5a97ebeSJim Ingham 
102a5a97ebeSJim Ingham         static OptionDefinition g_option_table[];
103a5a97ebeSJim Ingham 
104a5a97ebeSJim Ingham         // Instance variables to hold the values for command options.
105a5a97ebeSJim Ingham 
106a5a97ebeSJim Ingham         uint32_t m_start_idx;
107a5a97ebeSJim Ingham         uint32_t m_end_idx;
108a5a97ebeSJim Ingham     };
109a5a97ebeSJim Ingham 
110a5a97ebeSJim Ingham     CommandOptions m_options;
111a5a97ebeSJim Ingham 
112a5a97ebeSJim Ingham     virtual Options *
113a5a97ebeSJim Ingham     GetOptions ()
114a5a97ebeSJim Ingham     {
115a5a97ebeSJim Ingham         return &m_options;
116a5a97ebeSJim Ingham     }
117a5a97ebeSJim Ingham 
118a5a97ebeSJim Ingham public:
119a5a97ebeSJim Ingham     CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
120a5a97ebeSJim Ingham         CommandObject (interpreter,
121a5a97ebeSJim Ingham                        "command history",
122a5a97ebeSJim Ingham                        "Dump the history of commands in this session.",
123a5a97ebeSJim Ingham                        NULL),
124a5a97ebeSJim Ingham         m_options (interpreter)
125a5a97ebeSJim Ingham     {
126a5a97ebeSJim Ingham     }
127a5a97ebeSJim Ingham 
128a5a97ebeSJim Ingham     ~CommandObjectCommandsHistory ()
129a5a97ebeSJim Ingham     {
130a5a97ebeSJim Ingham     }
131a5a97ebeSJim Ingham 
132a5a97ebeSJim Ingham     bool
133a5a97ebeSJim Ingham     Execute
134a5a97ebeSJim Ingham     (
135a5a97ebeSJim Ingham         Args& args,
136a5a97ebeSJim Ingham         CommandReturnObject &result
137a5a97ebeSJim Ingham     )
138a5a97ebeSJim Ingham     {
139a5a97ebeSJim Ingham 
140a5a97ebeSJim Ingham         m_interpreter.DumpHistory (result.GetOutputStream(),
141a5a97ebeSJim Ingham                                    m_options.m_start_idx,
142a5a97ebeSJim Ingham                                    m_options.m_end_idx);
143a5a97ebeSJim Ingham         return result.Succeeded();
144a5a97ebeSJim Ingham 
145a5a97ebeSJim Ingham     }
146a5a97ebeSJim Ingham };
147a5a97ebeSJim Ingham 
148a5a97ebeSJim Ingham OptionDefinition
149a5a97ebeSJim Ingham CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
150a5a97ebeSJim Ingham {
151a5a97ebeSJim Ingham { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger,        "How many history commands to print."},
152a5a97ebeSJim Ingham { LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger,  "Index at which to start printing history commands."},
153a5a97ebeSJim Ingham { LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger,    "Index at which to stop printing history commands."},
154a5a97ebeSJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
155a5a97ebeSJim Ingham };
156a5a97ebeSJim Ingham 
157a5a97ebeSJim Ingham 
158a5a97ebeSJim Ingham //-------------------------------------------------------------------------
159a5a97ebeSJim Ingham // CommandObjectCommandsSource
160a5a97ebeSJim Ingham //-------------------------------------------------------------------------
161a5a97ebeSJim Ingham 
162ebc09c36SJim Ingham class CommandObjectCommandsSource : public CommandObject
163ebc09c36SJim Ingham {
164e16c50a1SJim Ingham private:
165e16c50a1SJim Ingham 
166e16c50a1SJim Ingham     class CommandOptions : public Options
167e16c50a1SJim Ingham     {
168e16c50a1SJim Ingham     public:
169e16c50a1SJim Ingham 
170eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
171eb0103f2SGreg Clayton             Options (interpreter)
172eb0103f2SGreg Clayton         {
173eb0103f2SGreg Clayton         }
174e16c50a1SJim Ingham 
175e16c50a1SJim Ingham         virtual
176e16c50a1SJim Ingham         ~CommandOptions (){}
177e16c50a1SJim Ingham 
178e16c50a1SJim Ingham         virtual Error
179f6b8b581SGreg Clayton         SetOptionValue (uint32_t option_idx, const char *option_arg)
180e16c50a1SJim Ingham         {
181e16c50a1SJim Ingham             Error error;
182e16c50a1SJim Ingham             char short_option = (char) m_getopt_table[option_idx].val;
183e16c50a1SJim Ingham             bool success;
184e16c50a1SJim Ingham 
185e16c50a1SJim Ingham             switch (short_option)
186e16c50a1SJim Ingham             {
187e16c50a1SJim Ingham                 case 'e':
188e16c50a1SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
189e16c50a1SJim Ingham                     if (!success)
190e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
191e16c50a1SJim Ingham                     break;
192e16c50a1SJim Ingham                 case 'c':
193e16c50a1SJim Ingham                     m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
194e16c50a1SJim Ingham                     if (!success)
195e16c50a1SJim Ingham                         error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
196e16c50a1SJim Ingham                     break;
197e16c50a1SJim Ingham                 default:
198e16c50a1SJim Ingham                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
199e16c50a1SJim Ingham                     break;
200e16c50a1SJim Ingham             }
201e16c50a1SJim Ingham 
202e16c50a1SJim Ingham             return error;
203e16c50a1SJim Ingham         }
204e16c50a1SJim Ingham 
205e16c50a1SJim Ingham         void
206f6b8b581SGreg Clayton         OptionParsingStarting ()
207e16c50a1SJim Ingham         {
208e16c50a1SJim Ingham             m_stop_on_error = true;
209e16c50a1SJim Ingham             m_stop_on_continue = true;
210e16c50a1SJim Ingham         }
211e16c50a1SJim Ingham 
212e0d378b3SGreg Clayton         const OptionDefinition*
213e16c50a1SJim Ingham         GetDefinitions ()
214e16c50a1SJim Ingham         {
215e16c50a1SJim Ingham             return g_option_table;
216e16c50a1SJim Ingham         }
217e16c50a1SJim Ingham 
218e16c50a1SJim Ingham         // Options table: Required for subclasses of Options.
219e16c50a1SJim Ingham 
220e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
221e16c50a1SJim Ingham 
222e16c50a1SJim Ingham         // Instance variables to hold the values for command options.
223e16c50a1SJim Ingham 
224e16c50a1SJim Ingham         bool m_stop_on_error;
225e16c50a1SJim Ingham         bool m_stop_on_continue;
226e16c50a1SJim Ingham     };
227e16c50a1SJim Ingham 
228e16c50a1SJim Ingham     CommandOptions m_options;
229e16c50a1SJim Ingham 
230e16c50a1SJim Ingham     virtual Options *
231e16c50a1SJim Ingham     GetOptions ()
232e16c50a1SJim Ingham     {
233e16c50a1SJim Ingham         return &m_options;
234e16c50a1SJim Ingham     }
235e16c50a1SJim Ingham 
236ebc09c36SJim Ingham public:
237a7015092SGreg Clayton     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
238a7015092SGreg Clayton         CommandObject (interpreter,
2390e5e5a79SGreg Clayton                        "command source",
240e3d26315SCaroline Tice                        "Read in debugger commands from the file <filename> and execute them.",
241eb0103f2SGreg Clayton                        NULL),
242eb0103f2SGreg Clayton         m_options (interpreter)
243ebc09c36SJim Ingham     {
244405fe67fSCaroline Tice         CommandArgumentEntry arg;
245405fe67fSCaroline Tice         CommandArgumentData file_arg;
246405fe67fSCaroline Tice 
247405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
248405fe67fSCaroline Tice         file_arg.arg_type = eArgTypeFilename;
249405fe67fSCaroline Tice         file_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         arg.push_back (file_arg);
253405fe67fSCaroline Tice 
254405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
255405fe67fSCaroline Tice         m_arguments.push_back (arg);
256ebc09c36SJim Ingham     }
257ebc09c36SJim Ingham 
258ebc09c36SJim Ingham     ~CommandObjectCommandsSource ()
259ebc09c36SJim Ingham     {
260ebc09c36SJim Ingham     }
261ebc09c36SJim Ingham 
262ebc09c36SJim Ingham     bool
263ebc09c36SJim Ingham     Execute
264ebc09c36SJim Ingham     (
265ebc09c36SJim Ingham         Args& args,
266ebc09c36SJim Ingham         CommandReturnObject &result
267ebc09c36SJim Ingham     )
268ebc09c36SJim Ingham     {
269ebc09c36SJim Ingham         const int argc = args.GetArgumentCount();
270ebc09c36SJim Ingham         if (argc == 1)
271ebc09c36SJim Ingham         {
272ebc09c36SJim Ingham             const char *filename = args.GetArgumentAtIndex(0);
273ebc09c36SJim Ingham 
274ebc09c36SJim Ingham             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
275ebc09c36SJim Ingham 
2761ee3853fSJohnny Chen             FileSpec cmd_file (filename, true);
277e16c50a1SJim Ingham             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
278e16c50a1SJim Ingham             bool echo_commands    = true;
279e16c50a1SJim Ingham             bool print_results    = true;
280ebc09c36SJim Ingham 
281e16c50a1SJim Ingham             m_interpreter.HandleCommandsFromFile (cmd_file,
282e16c50a1SJim Ingham                                                   exe_ctx,
283e16c50a1SJim Ingham                                                   m_options.m_stop_on_continue,
284e16c50a1SJim Ingham                                                   m_options.m_stop_on_error,
285e16c50a1SJim Ingham                                                   echo_commands,
286e16c50a1SJim Ingham                                                   print_results,
287e16c50a1SJim Ingham                                                   result);
288ebc09c36SJim Ingham         }
289ebc09c36SJim Ingham         else
290ebc09c36SJim Ingham         {
291ebc09c36SJim Ingham             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
292ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
293ebc09c36SJim Ingham         }
294ebc09c36SJim Ingham         return result.Succeeded();
295ebc09c36SJim Ingham 
296ebc09c36SJim Ingham     }
297ebc09c36SJim Ingham };
298ebc09c36SJim Ingham 
299e0d378b3SGreg Clayton OptionDefinition
300e16c50a1SJim Ingham CommandObjectCommandsSource::CommandOptions::g_option_table[] =
301e16c50a1SJim Ingham {
302e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
303e16c50a1SJim Ingham { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
304e16c50a1SJim Ingham { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
305e16c50a1SJim Ingham };
306e16c50a1SJim Ingham 
307ebc09c36SJim Ingham #pragma mark CommandObjectCommandsAlias
308ebc09c36SJim Ingham //-------------------------------------------------------------------------
309ebc09c36SJim Ingham // CommandObjectCommandsAlias
310ebc09c36SJim Ingham //-------------------------------------------------------------------------
311ebc09c36SJim Ingham 
312*be93a35aSEnrico Granata static const char *g_python_command_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
313*be93a35aSEnrico Granata                                                      "You must define a Python function with this signature:\n"
314*be93a35aSEnrico Granata                                                      "def my_command_impl(debugger, args, stream, dict):";
315*be93a35aSEnrico Granata 
316*be93a35aSEnrico Granata 
317ebc09c36SJim Ingham class CommandObjectCommandsAlias : public CommandObject
318ebc09c36SJim Ingham {
319*be93a35aSEnrico Granata 
320*be93a35aSEnrico Granata     class PythonAliasReader : public InputReaderEZ
321*be93a35aSEnrico Granata     {
322*be93a35aSEnrico Granata     private:
323*be93a35aSEnrico Granata         CommandInterpreter& m_interpreter;
324*be93a35aSEnrico Granata         std::string m_cmd_name;
325*be93a35aSEnrico Granata         StringList m_user_input;
326*be93a35aSEnrico Granata         DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
327*be93a35aSEnrico Granata     public:
328*be93a35aSEnrico Granata         PythonAliasReader(Debugger& debugger,
329*be93a35aSEnrico Granata                           CommandInterpreter& interpreter,
330*be93a35aSEnrico Granata                           std::string cmd_name) :
331*be93a35aSEnrico Granata         InputReaderEZ(debugger),
332*be93a35aSEnrico Granata         m_interpreter(interpreter),
333*be93a35aSEnrico Granata         m_cmd_name(cmd_name),
334*be93a35aSEnrico Granata         m_user_input()
335*be93a35aSEnrico Granata         {}
336*be93a35aSEnrico Granata 
337*be93a35aSEnrico Granata         virtual
338*be93a35aSEnrico Granata         ~PythonAliasReader()
339*be93a35aSEnrico Granata         {
340*be93a35aSEnrico Granata         }
341*be93a35aSEnrico Granata 
342*be93a35aSEnrico Granata         virtual void ActivateHandler(HandlerData& data)
343*be93a35aSEnrico Granata         {
344*be93a35aSEnrico Granata             StreamSP out_stream = data.GetOutStream();
345*be93a35aSEnrico Granata             bool batch_mode = data.GetBatchMode();
346*be93a35aSEnrico Granata             if (!batch_mode)
347*be93a35aSEnrico Granata             {
348*be93a35aSEnrico Granata                 out_stream->Printf ("%s\n", g_python_command_instructions);
349*be93a35aSEnrico Granata                 if (data.reader.GetPrompt())
350*be93a35aSEnrico Granata                     out_stream->Printf ("%s", data.reader.GetPrompt());
351*be93a35aSEnrico Granata                 out_stream->Flush();
352*be93a35aSEnrico Granata             }
353*be93a35aSEnrico Granata         }
354*be93a35aSEnrico Granata 
355*be93a35aSEnrico Granata         virtual void ReactivateHandler(HandlerData& data)
356*be93a35aSEnrico Granata         {
357*be93a35aSEnrico Granata             StreamSP out_stream = data.GetOutStream();
358*be93a35aSEnrico Granata             bool batch_mode = data.GetBatchMode();
359*be93a35aSEnrico Granata             if (data.reader.GetPrompt() && !batch_mode)
360*be93a35aSEnrico Granata             {
361*be93a35aSEnrico Granata                 out_stream->Printf ("%s", data.reader.GetPrompt());
362*be93a35aSEnrico Granata                 out_stream->Flush();
363*be93a35aSEnrico Granata             }
364*be93a35aSEnrico Granata         }
365*be93a35aSEnrico Granata         virtual void GotTokenHandler(HandlerData& data)
366*be93a35aSEnrico Granata         {
367*be93a35aSEnrico Granata             StreamSP out_stream = data.GetOutStream();
368*be93a35aSEnrico Granata             bool batch_mode = data.GetBatchMode();
369*be93a35aSEnrico Granata             if (data.bytes && data.bytes_len)
370*be93a35aSEnrico Granata             {
371*be93a35aSEnrico Granata                 m_user_input.AppendString(data.bytes, data.bytes_len);
372*be93a35aSEnrico Granata             }
373*be93a35aSEnrico Granata             if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
374*be93a35aSEnrico Granata             {
375*be93a35aSEnrico Granata                 out_stream->Printf ("%s", data.reader.GetPrompt());
376*be93a35aSEnrico Granata                 out_stream->Flush();
377*be93a35aSEnrico Granata             }
378*be93a35aSEnrico Granata         }
379*be93a35aSEnrico Granata         virtual void InterruptHandler(HandlerData& data)
380*be93a35aSEnrico Granata         {
381*be93a35aSEnrico Granata             StreamSP out_stream = data.GetOutStream();
382*be93a35aSEnrico Granata             bool batch_mode = data.GetBatchMode();
383*be93a35aSEnrico Granata             data.reader.SetIsDone (true);
384*be93a35aSEnrico Granata             if (!batch_mode)
385*be93a35aSEnrico Granata             {
386*be93a35aSEnrico Granata                 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
387*be93a35aSEnrico Granata                 out_stream->Flush();
388*be93a35aSEnrico Granata             }
389*be93a35aSEnrico Granata         }
390*be93a35aSEnrico Granata         virtual void EOFHandler(HandlerData& data)
391*be93a35aSEnrico Granata         {
392*be93a35aSEnrico Granata             data.reader.SetIsDone (true);
393*be93a35aSEnrico Granata         }
394*be93a35aSEnrico Granata         virtual void DoneHandler(HandlerData& data)
395*be93a35aSEnrico Granata         {
396*be93a35aSEnrico Granata             StreamSP out_stream = data.GetOutStream();
397*be93a35aSEnrico Granata 
398*be93a35aSEnrico Granata             ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
399*be93a35aSEnrico Granata             if (!interpreter)
400*be93a35aSEnrico Granata             {
401*be93a35aSEnrico Granata                 out_stream->Printf ("Internal error #1: no script attached.\n");
402*be93a35aSEnrico Granata                 out_stream->Flush();
403*be93a35aSEnrico Granata                 return;
404*be93a35aSEnrico Granata             }
405*be93a35aSEnrico Granata             StringList funct_name_sl;
406*be93a35aSEnrico Granata             if (!interpreter->GenerateScriptAliasFunction (m_user_input,
407*be93a35aSEnrico Granata                                                            funct_name_sl))
408*be93a35aSEnrico Granata             {
409*be93a35aSEnrico Granata                 out_stream->Printf ("Internal error #2: no script attached.\n");
410*be93a35aSEnrico Granata                 out_stream->Flush();
411*be93a35aSEnrico Granata                 return;
412*be93a35aSEnrico Granata             }
413*be93a35aSEnrico Granata             if (funct_name_sl.GetSize() == 0)
414*be93a35aSEnrico Granata             {
415*be93a35aSEnrico Granata                 out_stream->Printf ("Internal error #3: no script attached.\n");
416*be93a35aSEnrico Granata                 out_stream->Flush();
417*be93a35aSEnrico Granata                 return;
418*be93a35aSEnrico Granata             }
419*be93a35aSEnrico Granata             const char *funct_name = funct_name_sl.GetStringAtIndex(0);
420*be93a35aSEnrico Granata             if (!funct_name || !funct_name[0])
421*be93a35aSEnrico Granata             {
422*be93a35aSEnrico Granata                 out_stream->Printf ("Internal error #4: no script attached.\n");
423*be93a35aSEnrico Granata                 out_stream->Flush();
424*be93a35aSEnrico Granata                 return;
425*be93a35aSEnrico Granata             }
426*be93a35aSEnrico Granata 
427*be93a35aSEnrico Granata             // everything should be fine now, let's add this alias
428*be93a35aSEnrico Granata 
429*be93a35aSEnrico Granata             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
430*be93a35aSEnrico Granata                                                                            m_cmd_name,
431*be93a35aSEnrico Granata                                                                            funct_name));
432*be93a35aSEnrico Granata 
433*be93a35aSEnrico Granata             m_interpreter.AddAlias(m_cmd_name.c_str(), command_obj_sp);
434*be93a35aSEnrico Granata         }
435*be93a35aSEnrico Granata     };
436*be93a35aSEnrico Granata 
437ebc09c36SJim Ingham public:
438a7015092SGreg Clayton     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
439a7015092SGreg Clayton         CommandObject (interpreter,
4400e5e5a79SGreg Clayton                        "command alias",
441e3d26315SCaroline Tice                        "Allow users to define their own debugger command abbreviations.",
442405fe67fSCaroline Tice                        NULL)
443ebc09c36SJim Ingham     {
444ebc09c36SJim Ingham         SetHelpLong(
445ebc09c36SJim Ingham     "'alias' allows the user to create a short-cut or abbreviation for long \n\
446ebc09c36SJim Ingham     commands, multi-word commands, and commands that take particular options. \n\
447ebc09c36SJim Ingham     Below are some simple examples of how one might use the 'alias' command: \n\
44809799af6SCaroline Tice     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
449ebc09c36SJim Ingham                                          // command. \n\
45009799af6SCaroline Tice     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
451ebc09c36SJim Ingham                                          // command.  Since breakpoint commands are two-word \n\
452ebc09c36SJim Ingham                                          // commands, the user will still need to enter the \n\
453ebc09c36SJim Ingham                                          // second word after 'bp', e.g. 'bp enable' or \n\
454ebc09c36SJim Ingham                                          // 'bp delete'. \n\
45509799af6SCaroline Tice     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
456ebc09c36SJim Ingham                                          // two-word command 'breakpoint list'. \n\
457ebc09c36SJim Ingham     \nAn alias can include some options for the command, with the values either \n\
458ebc09c36SJim Ingham     filled in at the time the alias is created, or specified as positional \n\
459ebc09c36SJim Ingham     arguments, to be filled in when the alias is invoked.  The following example \n\
460ebc09c36SJim Ingham     shows how to create aliases with options: \n\
461ebc09c36SJim Ingham     \n\
46209799af6SCaroline Tice     'commands alias bfl breakpoint set -f %1 -l %2' \n\
463ebc09c36SJim Ingham     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
464ebc09c36SJim Ingham     options already part of the alias.  So if the user wants to set a breakpoint \n\
465ebc09c36SJim Ingham     by file and line without explicitly having to use the -f and -l options, the \n\
466ebc09c36SJim Ingham     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
467ebc09c36SJim Ingham     for the actual arguments that will be passed when the alias command is used. \n\
468ebc09c36SJim Ingham     The number in the placeholder refers to the position/order the actual value \n\
469ebc09c36SJim Ingham     occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
470ebc09c36SJim Ingham     will be replaced with the first argument, all the occurrences of '%2' in the \n\
471ebc09c36SJim Ingham     alias will be replaced with the second argument, and so on.  This also allows \n\
472ebc09c36SJim Ingham     actual arguments to be used multiple times within an alias (see 'process \n\
473ebc09c36SJim Ingham     launch' example below).  So in the 'bfl' case, the actual file value will be \n\
474ebc09c36SJim Ingham     filled in with the first argument following 'bfl' and the actual line number \n\
475ebc09c36SJim Ingham     value will be filled in with the second argument.  The user would use this \n\
476ebc09c36SJim Ingham     alias as follows: \n\
47709799af6SCaroline Tice     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
478ebc09c36SJim Ingham     <... some time later ...> \n\
47909799af6SCaroline Tice     (lldb)  bfl my-file.c 137 \n\
480ebc09c36SJim Ingham     \nThis would be the same as if the user had entered \n\
481ebc09c36SJim Ingham     'breakpoint set -f my-file.c -l 137'. \n\
482ebc09c36SJim Ingham     \nAnother example: \n\
48309799af6SCaroline Tice     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
48409799af6SCaroline Tice     (lldb)  pltty /dev/tty0 \n\
485ebc09c36SJim Ingham            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
486ebc09c36SJim Ingham     \nIf the user always wanted to pass the same value to a particular option, the \n\
487ebc09c36SJim Ingham     alias could be defined with that value directly in the alias as a constant, \n\
488ebc09c36SJim Ingham     rather than using a positional placeholder: \n\
4890708e2c2SSean Callanan     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
490ebc09c36SJim Ingham                                                    // 3 of whatever file is indicated. \n");
491ebc09c36SJim Ingham 
492405fe67fSCaroline Tice         CommandArgumentEntry arg1;
493405fe67fSCaroline Tice         CommandArgumentEntry arg2;
494405fe67fSCaroline Tice         CommandArgumentEntry arg3;
495405fe67fSCaroline Tice         CommandArgumentData alias_arg;
496405fe67fSCaroline Tice         CommandArgumentData cmd_arg;
497405fe67fSCaroline Tice         CommandArgumentData options_arg;
498405fe67fSCaroline Tice 
499405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
500405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
501405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
502405fe67fSCaroline Tice 
503405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
504405fe67fSCaroline Tice         arg1.push_back (alias_arg);
505405fe67fSCaroline Tice 
506405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
507405fe67fSCaroline Tice         cmd_arg.arg_type = eArgTypeCommandName;
508405fe67fSCaroline Tice         cmd_arg.arg_repetition = eArgRepeatPlain;
509405fe67fSCaroline Tice 
510405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
511405fe67fSCaroline Tice         arg2.push_back (cmd_arg);
512405fe67fSCaroline Tice 
513405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
514405fe67fSCaroline Tice         options_arg.arg_type = eArgTypeAliasOptions;
515405fe67fSCaroline Tice         options_arg.arg_repetition = eArgRepeatOptional;
516405fe67fSCaroline Tice 
517405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
518405fe67fSCaroline Tice         arg3.push_back (options_arg);
519405fe67fSCaroline Tice 
520405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
521405fe67fSCaroline Tice         m_arguments.push_back (arg1);
522405fe67fSCaroline Tice         m_arguments.push_back (arg2);
523405fe67fSCaroline Tice         m_arguments.push_back (arg3);
524ebc09c36SJim Ingham     }
525ebc09c36SJim Ingham 
526ebc09c36SJim Ingham     ~CommandObjectCommandsAlias ()
527ebc09c36SJim Ingham     {
528ebc09c36SJim Ingham     }
529ebc09c36SJim Ingham 
530844d2303SCaroline Tice     bool
531844d2303SCaroline Tice     WantsRawCommandString ()
532844d2303SCaroline Tice     {
533844d2303SCaroline Tice         return true;
534844d2303SCaroline Tice     }
535844d2303SCaroline Tice 
536844d2303SCaroline Tice     bool
537844d2303SCaroline Tice     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
538844d2303SCaroline Tice     {
539844d2303SCaroline Tice         Args args (raw_command_line);
540844d2303SCaroline Tice         std::string raw_command_string (raw_command_line);
541844d2303SCaroline Tice 
542844d2303SCaroline Tice         size_t argc = args.GetArgumentCount();
543844d2303SCaroline Tice 
544844d2303SCaroline Tice         if (argc < 2)
545844d2303SCaroline Tice         {
546844d2303SCaroline Tice             result.AppendError ("'alias' requires at least two arguments");
547844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
548844d2303SCaroline Tice             return false;
549844d2303SCaroline Tice         }
550844d2303SCaroline Tice 
551844d2303SCaroline Tice         // Get the alias command.
552844d2303SCaroline Tice 
553844d2303SCaroline Tice         const std::string alias_command = args.GetArgumentAtIndex (0);
554844d2303SCaroline Tice 
555*be93a35aSEnrico Granata         if (
556*be93a35aSEnrico Granata             (strcmp("--python",alias_command.c_str()) == 0) ||
557*be93a35aSEnrico Granata             (strcmp("-P",alias_command.c_str()) == 0)
558*be93a35aSEnrico Granata             )
559*be93a35aSEnrico Granata         {
560*be93a35aSEnrico Granata 
561*be93a35aSEnrico Granata             if (argc < 3)
562*be93a35aSEnrico Granata             {
563*be93a35aSEnrico Granata                 // this is a definition of the form
564*be93a35aSEnrico Granata                 // command alias --python foo_cmd
565*be93a35aSEnrico Granata                 // and the user will type foo_cmd_impl by hand
566*be93a35aSEnrico Granata                 std::string cmd_name = args.GetArgumentAtIndex(1);
567*be93a35aSEnrico Granata                 // Verify that the command is alias-able.
568*be93a35aSEnrico Granata                 if (m_interpreter.CommandExists (cmd_name.c_str()))
569*be93a35aSEnrico Granata                 {
570*be93a35aSEnrico Granata                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
571*be93a35aSEnrico Granata                                                   cmd_name.c_str());
572*be93a35aSEnrico Granata                     result.SetStatus (eReturnStatusFailed);
573*be93a35aSEnrico Granata                     return false;
574*be93a35aSEnrico Granata                 }
575*be93a35aSEnrico Granata                 if (m_interpreter.AliasExists (cmd_name.c_str())
576*be93a35aSEnrico Granata                     || m_interpreter.UserCommandExists (cmd_name.c_str()))
577*be93a35aSEnrico Granata                 {
578*be93a35aSEnrico Granata                     result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
579*be93a35aSEnrico Granata                                                     cmd_name.c_str());
580*be93a35aSEnrico Granata                 }
581*be93a35aSEnrico Granata 
582*be93a35aSEnrico Granata 
583*be93a35aSEnrico Granata                 InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
584*be93a35aSEnrico Granata                                                                 m_interpreter,
585*be93a35aSEnrico Granata                                                                 cmd_name));
586*be93a35aSEnrico Granata 
587*be93a35aSEnrico Granata                 if (reader_sp)
588*be93a35aSEnrico Granata                 {
589*be93a35aSEnrico Granata 
590*be93a35aSEnrico Granata                     InputReaderEZ::InitializationParameters ipr;
591*be93a35aSEnrico Granata 
592*be93a35aSEnrico Granata                     Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt("     ")));
593*be93a35aSEnrico Granata                     if (err.Success())
594*be93a35aSEnrico Granata                     {
595*be93a35aSEnrico Granata                         m_interpreter.GetDebugger().PushInputReader (reader_sp);
596*be93a35aSEnrico Granata                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
597*be93a35aSEnrico Granata                     }
598*be93a35aSEnrico Granata                     else
599*be93a35aSEnrico Granata                     {
600*be93a35aSEnrico Granata                         result.AppendError (err.AsCString());
601*be93a35aSEnrico Granata                         result.SetStatus (eReturnStatusFailed);
602*be93a35aSEnrico Granata                     }
603*be93a35aSEnrico Granata                 }
604*be93a35aSEnrico Granata                 else
605*be93a35aSEnrico Granata                 {
606*be93a35aSEnrico Granata                     result.AppendError("out of memory");
607*be93a35aSEnrico Granata                     result.SetStatus (eReturnStatusFailed);
608*be93a35aSEnrico Granata                 }
609*be93a35aSEnrico Granata 
610*be93a35aSEnrico Granata                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
611*be93a35aSEnrico Granata                 return result.Succeeded();
612*be93a35aSEnrico Granata             }
613*be93a35aSEnrico Granata             else
614*be93a35aSEnrico Granata             {
615*be93a35aSEnrico Granata                 // this is a definition of the form
616*be93a35aSEnrico Granata                 // command alias --python foo_cmd funct_impl_foo
617*be93a35aSEnrico Granata                 std::string cmd_name = args.GetArgumentAtIndex(1);
618*be93a35aSEnrico Granata                 std::string funct_name = args.GetArgumentAtIndex(2);
619*be93a35aSEnrico Granata 
620*be93a35aSEnrico Granata                 // Verify that the command is alias-able.
621*be93a35aSEnrico Granata                 if (m_interpreter.CommandExists (cmd_name.c_str()))
622*be93a35aSEnrico Granata                 {
623*be93a35aSEnrico Granata                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
624*be93a35aSEnrico Granata                                                   cmd_name.c_str());
625*be93a35aSEnrico Granata                     result.SetStatus (eReturnStatusFailed);
626*be93a35aSEnrico Granata                     return false;
627*be93a35aSEnrico Granata                 }
628*be93a35aSEnrico Granata 
629*be93a35aSEnrico Granata                 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
630*be93a35aSEnrico Granata                                                                                cmd_name,
631*be93a35aSEnrico Granata                                                                                funct_name));
632*be93a35aSEnrico Granata 
633*be93a35aSEnrico Granata                 if (m_interpreter.AliasExists (cmd_name.c_str())
634*be93a35aSEnrico Granata                     || m_interpreter.UserCommandExists (cmd_name.c_str()))
635*be93a35aSEnrico Granata                 {
636*be93a35aSEnrico Granata                     result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
637*be93a35aSEnrico Granata                                                     cmd_name.c_str());
638*be93a35aSEnrico Granata                 }
639*be93a35aSEnrico Granata 
640*be93a35aSEnrico Granata                 m_interpreter.AddAlias(cmd_name.c_str(), command_obj_sp);
641*be93a35aSEnrico Granata 
642*be93a35aSEnrico Granata                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
643*be93a35aSEnrico Granata                 return result.Succeeded();
644*be93a35aSEnrico Granata             }
645*be93a35aSEnrico Granata         }
646*be93a35aSEnrico Granata 
647844d2303SCaroline Tice         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
648844d2303SCaroline Tice         // does the stripping itself.
649844d2303SCaroline Tice         size_t pos = raw_command_string.find (alias_command);
650844d2303SCaroline Tice         if (pos == 0)
651844d2303SCaroline Tice         {
652844d2303SCaroline Tice             raw_command_string = raw_command_string.substr (alias_command.size());
653844d2303SCaroline Tice             pos = raw_command_string.find_first_not_of (' ');
654844d2303SCaroline Tice             if ((pos != std::string::npos) && (pos > 0))
655844d2303SCaroline Tice                 raw_command_string = raw_command_string.substr (pos);
656844d2303SCaroline Tice         }
657844d2303SCaroline Tice         else
658844d2303SCaroline Tice         {
659844d2303SCaroline Tice             result.AppendError ("Error parsing command string.  No alias created.");
660844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
661844d2303SCaroline Tice             return false;
662844d2303SCaroline Tice         }
663844d2303SCaroline Tice 
664844d2303SCaroline Tice 
665844d2303SCaroline Tice         // Verify that the command is alias-able.
666844d2303SCaroline Tice         if (m_interpreter.CommandExists (alias_command.c_str()))
667844d2303SCaroline Tice         {
668844d2303SCaroline Tice             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
669844d2303SCaroline Tice                                           alias_command.c_str());
670844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
671844d2303SCaroline Tice             return false;
672844d2303SCaroline Tice         }
673844d2303SCaroline Tice 
674844d2303SCaroline Tice         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
675844d2303SCaroline Tice         // raw_command_string is returned with the name of the command object stripped off the front.
676844d2303SCaroline Tice         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
677844d2303SCaroline Tice 
678844d2303SCaroline Tice         if (!cmd_obj)
679844d2303SCaroline Tice         {
680844d2303SCaroline Tice             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
681844d2303SCaroline Tice                                           "  No alias created.", raw_command_string.c_str());
682844d2303SCaroline Tice             result.SetStatus (eReturnStatusFailed);
683844d2303SCaroline Tice             return false;
684844d2303SCaroline Tice         }
685844d2303SCaroline Tice         else if (!cmd_obj->WantsRawCommandString ())
686844d2303SCaroline Tice         {
687844d2303SCaroline Tice             // Note that args was initialized with the original command, and has not been updated to this point.
688844d2303SCaroline Tice             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
689844d2303SCaroline Tice             return Execute (args, result);
690844d2303SCaroline Tice         }
691844d2303SCaroline Tice         else
692844d2303SCaroline Tice         {
693844d2303SCaroline Tice             // Verify & handle any options/arguments passed to the alias command
694844d2303SCaroline Tice 
695844d2303SCaroline Tice             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
696844d2303SCaroline Tice             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
697844d2303SCaroline Tice 
698ca90c47eSCaroline Tice             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
699844d2303SCaroline Tice 
700ca90c47eSCaroline Tice             if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
701844d2303SCaroline Tice             {
702844d2303SCaroline Tice                 result.AppendError ("Unable to create requested alias.\n");
703ca90c47eSCaroline Tice                 result.SetStatus (eReturnStatusFailed);
704844d2303SCaroline Tice                 return false;
705844d2303SCaroline Tice             }
706844d2303SCaroline Tice 
707844d2303SCaroline Tice             // Create the alias
708844d2303SCaroline Tice             if (m_interpreter.AliasExists (alias_command.c_str())
709844d2303SCaroline Tice                 || m_interpreter.UserCommandExists (alias_command.c_str()))
710844d2303SCaroline Tice             {
711844d2303SCaroline Tice                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
712844d2303SCaroline Tice                 if (temp_option_arg_sp.get())
713844d2303SCaroline Tice                 {
714844d2303SCaroline Tice                     if (option_arg_vector->size() == 0)
715844d2303SCaroline Tice                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
716844d2303SCaroline Tice                 }
717844d2303SCaroline Tice                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
718844d2303SCaroline Tice                                                 alias_command.c_str());
719844d2303SCaroline Tice             }
720844d2303SCaroline Tice 
721472362e6SCaroline Tice             if (cmd_obj_sp)
722472362e6SCaroline Tice             {
723844d2303SCaroline Tice                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
724844d2303SCaroline Tice                 if (option_arg_vector->size() > 0)
725844d2303SCaroline Tice                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
726844d2303SCaroline Tice                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
727844d2303SCaroline Tice             }
728472362e6SCaroline Tice             else
729472362e6SCaroline Tice             {
730472362e6SCaroline Tice                 result.AppendError ("Unable to create requested alias.\n");
731472362e6SCaroline Tice                 result.SetStatus (eReturnStatusFailed);
732472362e6SCaroline Tice             }
733472362e6SCaroline Tice         }
734844d2303SCaroline Tice         return result.Succeeded();
735844d2303SCaroline Tice     }
736ebc09c36SJim Ingham 
737ebc09c36SJim Ingham     bool
738ebc09c36SJim Ingham     Execute
739ebc09c36SJim Ingham     (
740ebc09c36SJim Ingham         Args& args,
741ebc09c36SJim Ingham         CommandReturnObject &result
742ebc09c36SJim Ingham     )
743ebc09c36SJim Ingham     {
744867b185dSCaroline Tice         size_t argc = args.GetArgumentCount();
745ebc09c36SJim Ingham 
746ebc09c36SJim Ingham         if (argc < 2)
747ebc09c36SJim Ingham         {
748ebc09c36SJim Ingham             result.AppendError ("'alias' requires at least two arguments");
749ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
750ebc09c36SJim Ingham             return false;
751ebc09c36SJim Ingham         }
752ebc09c36SJim Ingham 
753ebc09c36SJim Ingham         const std::string alias_command = args.GetArgumentAtIndex(0);
754ebc09c36SJim Ingham         const std::string actual_command = args.GetArgumentAtIndex(1);
755ebc09c36SJim Ingham 
756ebc09c36SJim Ingham         args.Shift();  // Shift the alias command word off the argument vector.
757ebc09c36SJim Ingham         args.Shift();  // Shift the old command word off the argument vector.
758ebc09c36SJim Ingham 
759ebc09c36SJim Ingham         // Verify that the command is alias'able, and get the appropriate command object.
760ebc09c36SJim Ingham 
761a7015092SGreg Clayton         if (m_interpreter.CommandExists (alias_command.c_str()))
762ebc09c36SJim Ingham         {
763ebc09c36SJim Ingham             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
764ebc09c36SJim Ingham                                          alias_command.c_str());
765ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
766ebc09c36SJim Ingham         }
767ebc09c36SJim Ingham         else
768ebc09c36SJim Ingham         {
769a7015092SGreg Clayton              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
770ebc09c36SJim Ingham              CommandObjectSP subcommand_obj_sp;
771ebc09c36SJim Ingham              bool use_subcommand = false;
772ebc09c36SJim Ingham              if (command_obj_sp.get())
773ebc09c36SJim Ingham              {
774ebc09c36SJim Ingham                  CommandObject *cmd_obj = command_obj_sp.get();
775c982c768SGreg Clayton                  CommandObject *sub_cmd_obj = NULL;
776ebc09c36SJim Ingham                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
777ebc09c36SJim Ingham                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
778ebc09c36SJim Ingham 
779844d2303SCaroline Tice                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
780ebc09c36SJim Ingham                  {
781ebc09c36SJim Ingham                      if (argc >= 3)
782ebc09c36SJim Ingham                      {
783ebc09c36SJim Ingham                          const std::string sub_command = args.GetArgumentAtIndex(0);
784ebc09c36SJim Ingham                          assert (sub_command.length() != 0);
785ebc09c36SJim Ingham                          subcommand_obj_sp =
786ebc09c36SJim Ingham                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
787ebc09c36SJim Ingham                          if (subcommand_obj_sp.get())
788ebc09c36SJim Ingham                          {
789ebc09c36SJim Ingham                              sub_cmd_obj = subcommand_obj_sp.get();
790ebc09c36SJim Ingham                              use_subcommand = true;
791ebc09c36SJim Ingham                              args.Shift();  // Shift the sub_command word off the argument vector.
792844d2303SCaroline Tice                              cmd_obj = sub_cmd_obj;
793ebc09c36SJim Ingham                          }
794ebc09c36SJim Ingham                          else
795ebc09c36SJim Ingham                          {
796f415eeb4SCaroline Tice                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
797f415eeb4SCaroline Tice                                                           "Unable to create alias.\n",
798f415eeb4SCaroline Tice                                                           sub_command.c_str(), actual_command.c_str());
799ebc09c36SJim Ingham                              result.SetStatus (eReturnStatusFailed);
800ebc09c36SJim Ingham                              return false;
801ebc09c36SJim Ingham                          }
802ebc09c36SJim Ingham                      }
803ebc09c36SJim Ingham                  }
804ebc09c36SJim Ingham 
805ebc09c36SJim Ingham                  // Verify & handle any options/arguments passed to the alias command
806ebc09c36SJim Ingham 
807ebc09c36SJim Ingham                  if (args.GetArgumentCount () > 0)
808ebc09c36SJim Ingham                  {
809ca90c47eSCaroline Tice                     CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
810ebc09c36SJim Ingham                     if (use_subcommand)
811ca90c47eSCaroline Tice                         tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
812ca90c47eSCaroline Tice 
813ca90c47eSCaroline Tice                     std::string args_string;
814ca90c47eSCaroline Tice                     args.GetCommandString (args_string);
815ca90c47eSCaroline Tice 
816ca90c47eSCaroline Tice                     if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
817ebc09c36SJim Ingham                     {
818ca90c47eSCaroline Tice                         result.AppendError ("Unable to create requested alias.\n");
819ca90c47eSCaroline Tice                         result.SetStatus (eReturnStatusFailed);
820e7941795SCaroline Tice                         return false;
821867b185dSCaroline Tice                     }
822867b185dSCaroline Tice                  }
823867b185dSCaroline Tice 
824ebc09c36SJim Ingham                  // Create the alias.
825ebc09c36SJim Ingham 
826a7015092SGreg Clayton                  if (m_interpreter.AliasExists (alias_command.c_str())
827a7015092SGreg Clayton                      || m_interpreter.UserCommandExists (alias_command.c_str()))
828ebc09c36SJim Ingham                  {
829a7015092SGreg Clayton                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
830ebc09c36SJim Ingham                      if (tmp_option_arg_sp.get())
831ebc09c36SJim Ingham                      {
832ebc09c36SJim Ingham                          if (option_arg_vector->size() == 0)
833a7015092SGreg Clayton                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
834ebc09c36SJim Ingham                      }
835ebc09c36SJim Ingham                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
836ebc09c36SJim Ingham                                                      alias_command.c_str());
837ebc09c36SJim Ingham                  }
838ebc09c36SJim Ingham 
839ebc09c36SJim Ingham                  if (use_subcommand)
840a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
841ebc09c36SJim Ingham                  else
842a7015092SGreg Clayton                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
843ebc09c36SJim Ingham                  if (option_arg_vector->size() > 0)
844a7015092SGreg Clayton                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
845ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
846ebc09c36SJim Ingham              }
847ebc09c36SJim Ingham              else
848ebc09c36SJim Ingham              {
849ebc09c36SJim Ingham                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
850ebc09c36SJim Ingham                  result.SetStatus (eReturnStatusFailed);
851e7941795SCaroline Tice                  return false;
852ebc09c36SJim Ingham              }
853ebc09c36SJim Ingham         }
854ebc09c36SJim Ingham 
855ebc09c36SJim Ingham         return result.Succeeded();
856ebc09c36SJim Ingham     }
857ebc09c36SJim Ingham };
858ebc09c36SJim Ingham 
859ebc09c36SJim Ingham #pragma mark CommandObjectCommandsUnalias
860ebc09c36SJim Ingham //-------------------------------------------------------------------------
861ebc09c36SJim Ingham // CommandObjectCommandsUnalias
862ebc09c36SJim Ingham //-------------------------------------------------------------------------
863ebc09c36SJim Ingham 
864ebc09c36SJim Ingham class CommandObjectCommandsUnalias : public CommandObject
865ebc09c36SJim Ingham {
866ebc09c36SJim Ingham public:
867a7015092SGreg Clayton     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
868a7015092SGreg Clayton         CommandObject (interpreter,
8690e5e5a79SGreg Clayton                        "command unalias",
87086ddae50SCaroline Tice                        "Allow the user to remove/delete a user-defined command abbreviation.",
871405fe67fSCaroline Tice                        NULL)
872ebc09c36SJim Ingham     {
873405fe67fSCaroline Tice         CommandArgumentEntry arg;
874405fe67fSCaroline Tice         CommandArgumentData alias_arg;
875405fe67fSCaroline Tice 
876405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
877405fe67fSCaroline Tice         alias_arg.arg_type = eArgTypeAliasName;
878405fe67fSCaroline Tice         alias_arg.arg_repetition = eArgRepeatPlain;
879405fe67fSCaroline Tice 
880405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
881405fe67fSCaroline Tice         arg.push_back (alias_arg);
882405fe67fSCaroline Tice 
883405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
884405fe67fSCaroline Tice         m_arguments.push_back (arg);
885ebc09c36SJim Ingham     }
886ebc09c36SJim Ingham 
887ebc09c36SJim Ingham     ~CommandObjectCommandsUnalias()
888ebc09c36SJim Ingham     {
889ebc09c36SJim Ingham     }
890ebc09c36SJim Ingham 
891ebc09c36SJim Ingham 
892ebc09c36SJim Ingham     bool
893ebc09c36SJim Ingham     Execute
894ebc09c36SJim Ingham     (
895ebc09c36SJim Ingham         Args& args,
896ebc09c36SJim Ingham         CommandReturnObject &result
897ebc09c36SJim Ingham     )
898ebc09c36SJim Ingham     {
899ebc09c36SJim Ingham         CommandObject::CommandMap::iterator pos;
900ebc09c36SJim Ingham         CommandObject *cmd_obj;
901ebc09c36SJim Ingham 
902ebc09c36SJim Ingham         if (args.GetArgumentCount() != 0)
903ebc09c36SJim Ingham         {
904ebc09c36SJim Ingham             const char *command_name = args.GetArgumentAtIndex(0);
905a7015092SGreg Clayton             cmd_obj = m_interpreter.GetCommandObject(command_name);
906ebc09c36SJim Ingham             if (cmd_obj)
907ebc09c36SJim Ingham             {
908a7015092SGreg Clayton                 if (m_interpreter.CommandExists (command_name))
909ebc09c36SJim Ingham                 {
910ebc09c36SJim Ingham                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
911ebc09c36SJim Ingham                                                   command_name);
912ebc09c36SJim Ingham                     result.SetStatus (eReturnStatusFailed);
913ebc09c36SJim Ingham                 }
914ebc09c36SJim Ingham                 else
915ebc09c36SJim Ingham                 {
916ebc09c36SJim Ingham 
917a7015092SGreg Clayton                     if (m_interpreter.RemoveAlias (command_name) == false)
918ebc09c36SJim Ingham                     {
919a7015092SGreg Clayton                         if (m_interpreter.AliasExists (command_name))
920ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
921ebc09c36SJim Ingham                                                           command_name);
922ebc09c36SJim Ingham                         else
923ebc09c36SJim Ingham                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
924ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusFailed);
925ebc09c36SJim Ingham                     }
926ebc09c36SJim Ingham                     else
927ebc09c36SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
928ebc09c36SJim Ingham                 }
929ebc09c36SJim Ingham             }
930ebc09c36SJim Ingham             else
931ebc09c36SJim Ingham             {
932ebc09c36SJim Ingham                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
933ebc09c36SJim Ingham                                               "current list of commands.\n",
934ebc09c36SJim Ingham                                              command_name);
935ebc09c36SJim Ingham                 result.SetStatus (eReturnStatusFailed);
936ebc09c36SJim Ingham             }
937ebc09c36SJim Ingham         }
938ebc09c36SJim Ingham         else
939ebc09c36SJim Ingham         {
940ebc09c36SJim Ingham             result.AppendError ("must call 'unalias' with a valid alias");
941ebc09c36SJim Ingham             result.SetStatus (eReturnStatusFailed);
942ebc09c36SJim Ingham         }
943ebc09c36SJim Ingham 
944ebc09c36SJim Ingham         return result.Succeeded();
945ebc09c36SJim Ingham     }
946ebc09c36SJim Ingham };
947ebc09c36SJim Ingham 
948de164aaaSGreg Clayton #pragma mark CommandObjectCommandsAddRegex
949de164aaaSGreg Clayton //-------------------------------------------------------------------------
950de164aaaSGreg Clayton // CommandObjectCommandsAddRegex
951de164aaaSGreg Clayton //-------------------------------------------------------------------------
952de164aaaSGreg Clayton 
953de164aaaSGreg Clayton class CommandObjectCommandsAddRegex : public CommandObject
954de164aaaSGreg Clayton {
955de164aaaSGreg Clayton public:
956de164aaaSGreg Clayton     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
957de164aaaSGreg Clayton         CommandObject (interpreter,
9580e5e5a79SGreg Clayton                        "command regex",
959de164aaaSGreg Clayton                        "Allow the user to create a regular expression command.",
9600e5e5a79SGreg Clayton                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
961de164aaaSGreg Clayton         m_options (interpreter)
962de164aaaSGreg Clayton     {
9630e5e5a79SGreg Clayton         SetHelpLong(
9640e5e5a79SGreg Clayton "This command allows the user to create powerful regular expression commands\n"
9650e5e5a79SGreg Clayton "with substitutions. The regular expressions and substitutions are specified\n"
9660e5e5a79SGreg Clayton "using the regular exression substitution format of:\n"
9670e5e5a79SGreg Clayton "\n"
9680e5e5a79SGreg Clayton "    s/<regex>/<subst>/\n"
9690e5e5a79SGreg Clayton "\n"
9700e5e5a79SGreg Clayton "<regex> is a regular expression that can use parenthesis to capture regular\n"
9710e5e5a79SGreg Clayton "expression input and substitute the captured matches in the output using %1\n"
9720e5e5a79SGreg Clayton "for the first match, %2 for the second, and so on.\n"
9730e5e5a79SGreg Clayton "\n"
9740e5e5a79SGreg Clayton "The regular expressions can all be specified on the command line if more than\n"
9750e5e5a79SGreg Clayton "one argument is provided. If just the command name is provided on the command\n"
9760e5e5a79SGreg Clayton "line, then the regular expressions and substitutions can be entered on separate\n"
9770e5e5a79SGreg Clayton " lines, followed by an empty line to terminate the command definition.\n"
9780e5e5a79SGreg Clayton "\n"
9790e5e5a79SGreg Clayton "EXAMPLES\n"
9800e5e5a79SGreg Clayton "\n"
9810e5e5a79SGreg Clayton "The following example with define a regular expression command named 'f' that\n"
9820e5e5a79SGreg Clayton "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
9830e5e5a79SGreg Clayton "a number follows 'f':\n"
9840e5e5a79SGreg Clayton "(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
9850e5e5a79SGreg Clayton                     );
986de164aaaSGreg Clayton     }
987de164aaaSGreg Clayton 
988de164aaaSGreg Clayton     ~CommandObjectCommandsAddRegex()
989de164aaaSGreg Clayton     {
990de164aaaSGreg Clayton     }
991de164aaaSGreg Clayton 
992de164aaaSGreg Clayton 
993de164aaaSGreg Clayton     bool
994de164aaaSGreg Clayton     Execute (Args& args, CommandReturnObject &result)
995de164aaaSGreg Clayton     {
9960e5e5a79SGreg Clayton         const size_t argc = args.GetArgumentCount();
9970e5e5a79SGreg Clayton         if (argc == 0)
998de164aaaSGreg Clayton         {
9990e5e5a79SGreg Clayton             result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
10000e5e5a79SGreg Clayton             result.SetStatus (eReturnStatusFailed);
10010e5e5a79SGreg Clayton         }
10020e5e5a79SGreg Clayton         else
10030e5e5a79SGreg Clayton         {
10040e5e5a79SGreg Clayton             Error error;
1005de164aaaSGreg Clayton             const char *name = args.GetArgumentAtIndex(0);
1006de164aaaSGreg Clayton             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
1007de164aaaSGreg Clayton                                                                  name,
1008de164aaaSGreg Clayton                                                                  m_options.GetHelp (),
1009de164aaaSGreg Clayton                                                                  m_options.GetSyntax (),
1010de164aaaSGreg Clayton                                                                  10));
10110e5e5a79SGreg Clayton 
10120e5e5a79SGreg Clayton             if (argc == 1)
10130e5e5a79SGreg Clayton             {
10140e5e5a79SGreg Clayton                 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
1015de164aaaSGreg Clayton                 if (reader_sp)
1016de164aaaSGreg Clayton                 {
10170e5e5a79SGreg Clayton                     error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
1018de164aaaSGreg Clayton                                                   this,                         // baton
1019de164aaaSGreg Clayton                                                   eInputReaderGranularityLine,  // token size, to pass to callback function
10200e5e5a79SGreg Clayton                                                   NULL,                         // end token
1021de164aaaSGreg Clayton                                                   "> ",                         // prompt
10220e5e5a79SGreg Clayton                                                   true);                        // echo input
10230e5e5a79SGreg Clayton                     if (error.Success())
1024de164aaaSGreg Clayton                     {
1025de164aaaSGreg Clayton                         m_interpreter.GetDebugger().PushInputReader (reader_sp);
1026de164aaaSGreg Clayton                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
10270e5e5a79SGreg Clayton                         return true;
1028de164aaaSGreg Clayton                     }
1029de164aaaSGreg Clayton                 }
1030de164aaaSGreg Clayton             }
1031de164aaaSGreg Clayton             else
1032de164aaaSGreg Clayton             {
10330e5e5a79SGreg Clayton                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
10340e5e5a79SGreg Clayton                 {
10350e5e5a79SGreg Clayton                     llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
10360e5e5a79SGreg Clayton                     error = AppendRegexSubstitution (arg_strref);
10370e5e5a79SGreg Clayton                     if (error.Fail())
10380e5e5a79SGreg Clayton                         break;
10390e5e5a79SGreg Clayton                 }
10400e5e5a79SGreg Clayton 
10410e5e5a79SGreg Clayton                 if (error.Success())
10420e5e5a79SGreg Clayton                 {
10430e5e5a79SGreg Clayton                     AddRegexCommandToInterpreter();
10440e5e5a79SGreg Clayton                 }
10450e5e5a79SGreg Clayton             }
10460e5e5a79SGreg Clayton             if (error.Fail())
10470e5e5a79SGreg Clayton             {
10480e5e5a79SGreg Clayton                 result.AppendError (error.AsCString());
1049de164aaaSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
1050de164aaaSGreg Clayton             }
10510e5e5a79SGreg Clayton         }
10520e5e5a79SGreg Clayton 
1053de164aaaSGreg Clayton         return result.Succeeded();
1054de164aaaSGreg Clayton     }
1055de164aaaSGreg Clayton 
10560e5e5a79SGreg Clayton     Error
10570e5e5a79SGreg Clayton     AppendRegexSubstitution (const llvm::StringRef &regex_sed)
1058de164aaaSGreg Clayton     {
10590e5e5a79SGreg Clayton         Error error;
10600e5e5a79SGreg Clayton 
10610e5e5a79SGreg Clayton         if (m_regex_cmd_ap.get() == NULL)
1062de164aaaSGreg Clayton         {
10630e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
10640e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
10650e5e5a79SGreg Clayton                                            regex_sed.data());
10660e5e5a79SGreg Clayton             return error;
1067de164aaaSGreg Clayton         }
10680e5e5a79SGreg Clayton 
10690e5e5a79SGreg Clayton         size_t regex_sed_size = regex_sed.size();
10700e5e5a79SGreg Clayton 
10710e5e5a79SGreg Clayton         if (regex_sed_size <= 1)
10720e5e5a79SGreg Clayton         {
10730e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
10740e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
10750e5e5a79SGreg Clayton                                            regex_sed.data());
10760e5e5a79SGreg Clayton             return error;
10770e5e5a79SGreg Clayton         }
10780e5e5a79SGreg Clayton 
10790e5e5a79SGreg Clayton         if (regex_sed[0] != 's')
10800e5e5a79SGreg Clayton         {
10810e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
10820e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
10830e5e5a79SGreg Clayton                                            regex_sed.data());
10840e5e5a79SGreg Clayton             return error;
10850e5e5a79SGreg Clayton         }
10860e5e5a79SGreg Clayton         const size_t first_separator_char_pos = 1;
10870e5e5a79SGreg Clayton         // use the char that follows 's' as the regex separator character
10880e5e5a79SGreg Clayton         // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
10890e5e5a79SGreg Clayton         const char separator_char = regex_sed[first_separator_char_pos];
10900e5e5a79SGreg Clayton         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
10910e5e5a79SGreg Clayton 
10920e5e5a79SGreg Clayton         if (second_separator_char_pos == std::string::npos)
10930e5e5a79SGreg Clayton         {
10940e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
10950e5e5a79SGreg Clayton                                            separator_char,
10960e5e5a79SGreg Clayton                                            (int)(regex_sed.size() - first_separator_char_pos - 1),
10970e5e5a79SGreg Clayton                                            regex_sed.data() + (first_separator_char_pos + 1));
10980e5e5a79SGreg Clayton             return error;
10990e5e5a79SGreg Clayton         }
11000e5e5a79SGreg Clayton 
11010e5e5a79SGreg Clayton         const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
11020e5e5a79SGreg Clayton 
11030e5e5a79SGreg Clayton         if (third_separator_char_pos == std::string::npos)
11040e5e5a79SGreg Clayton         {
11050e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
11060e5e5a79SGreg Clayton                                            separator_char,
11070e5e5a79SGreg Clayton                                            (int)(regex_sed.size() - second_separator_char_pos - 1),
11080e5e5a79SGreg Clayton                                            regex_sed.data() + (second_separator_char_pos + 1));
11090e5e5a79SGreg Clayton             return error;
11100e5e5a79SGreg Clayton         }
11110e5e5a79SGreg Clayton 
11120e5e5a79SGreg Clayton         if (third_separator_char_pos != regex_sed_size - 1)
11130e5e5a79SGreg Clayton         {
11140e5e5a79SGreg Clayton             // Make sure that everything that follows the last regex
11150e5e5a79SGreg Clayton             // separator char
11160e5e5a79SGreg Clayton             if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
11170e5e5a79SGreg Clayton             {
11180e5e5a79SGreg Clayton                 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
11190e5e5a79SGreg Clayton                                                (int)third_separator_char_pos + 1,
11200e5e5a79SGreg Clayton                                                regex_sed.data(),
11210e5e5a79SGreg Clayton                                                (int)(regex_sed.size() - third_separator_char_pos - 1),
11220e5e5a79SGreg Clayton                                                regex_sed.data() + (third_separator_char_pos + 1));
11230e5e5a79SGreg Clayton                 return error;
11240e5e5a79SGreg Clayton             }
11250e5e5a79SGreg Clayton 
11260e5e5a79SGreg Clayton         }
11270e5e5a79SGreg Clayton         else if (first_separator_char_pos + 1 == second_separator_char_pos)
11280e5e5a79SGreg Clayton         {
11290e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
11300e5e5a79SGreg Clayton                                            separator_char,
11310e5e5a79SGreg Clayton                                            separator_char,
11320e5e5a79SGreg Clayton                                            separator_char,
11330e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
11340e5e5a79SGreg Clayton                                            regex_sed.data());
11350e5e5a79SGreg Clayton             return error;
11360e5e5a79SGreg Clayton         }
11370e5e5a79SGreg Clayton         else if (second_separator_char_pos + 1 == third_separator_char_pos)
11380e5e5a79SGreg Clayton         {
11390e5e5a79SGreg Clayton             error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
11400e5e5a79SGreg Clayton                                            separator_char,
11410e5e5a79SGreg Clayton                                            separator_char,
11420e5e5a79SGreg Clayton                                            separator_char,
11430e5e5a79SGreg Clayton                                            (int)regex_sed.size(),
11440e5e5a79SGreg Clayton                                            regex_sed.data());
11450e5e5a79SGreg Clayton             return error;
11460e5e5a79SGreg Clayton         }
11470e5e5a79SGreg Clayton         std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
11480e5e5a79SGreg Clayton         std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
11490e5e5a79SGreg Clayton         m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
11500e5e5a79SGreg Clayton                                          subst.c_str());
11510e5e5a79SGreg Clayton         return error;
1152de164aaaSGreg Clayton     }
1153de164aaaSGreg Clayton 
1154de164aaaSGreg Clayton     void
11550e5e5a79SGreg Clayton     AddRegexCommandToInterpreter()
1156de164aaaSGreg Clayton     {
1157de164aaaSGreg Clayton         if (m_regex_cmd_ap.get())
1158de164aaaSGreg Clayton         {
1159de164aaaSGreg Clayton             if (m_regex_cmd_ap->HasRegexEntries())
1160de164aaaSGreg Clayton             {
1161de164aaaSGreg Clayton                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1162de164aaaSGreg Clayton                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1163de164aaaSGreg Clayton             }
1164de164aaaSGreg Clayton         }
1165de164aaaSGreg Clayton     }
1166de164aaaSGreg Clayton 
11670e5e5a79SGreg Clayton     void
11680e5e5a79SGreg Clayton     InputReaderDidCancel()
11690e5e5a79SGreg Clayton     {
11700e5e5a79SGreg Clayton         m_regex_cmd_ap.reset();
11710e5e5a79SGreg Clayton     }
11720e5e5a79SGreg Clayton 
1173de164aaaSGreg Clayton     static size_t
1174de164aaaSGreg Clayton     InputReaderCallback (void *baton,
1175de164aaaSGreg Clayton                          InputReader &reader,
1176de164aaaSGreg Clayton                          lldb::InputReaderAction notification,
1177de164aaaSGreg Clayton                          const char *bytes,
1178de164aaaSGreg Clayton                          size_t bytes_len);
1179de164aaaSGreg Clayton private:
1180de164aaaSGreg Clayton     std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1181de164aaaSGreg Clayton 
1182de164aaaSGreg Clayton      class CommandOptions : public Options
1183de164aaaSGreg Clayton      {
1184de164aaaSGreg Clayton      public:
1185de164aaaSGreg Clayton 
1186de164aaaSGreg Clayton          CommandOptions (CommandInterpreter &interpreter) :
1187de164aaaSGreg Clayton             Options (interpreter)
1188de164aaaSGreg Clayton          {
1189de164aaaSGreg Clayton          }
1190de164aaaSGreg Clayton 
1191de164aaaSGreg Clayton          virtual
1192de164aaaSGreg Clayton          ~CommandOptions (){}
1193de164aaaSGreg Clayton 
1194de164aaaSGreg Clayton          virtual Error
1195de164aaaSGreg Clayton          SetOptionValue (uint32_t option_idx, const char *option_arg)
1196de164aaaSGreg Clayton          {
1197de164aaaSGreg Clayton              Error error;
1198de164aaaSGreg Clayton              char short_option = (char) m_getopt_table[option_idx].val;
1199de164aaaSGreg Clayton 
1200de164aaaSGreg Clayton              switch (short_option)
1201de164aaaSGreg Clayton              {
1202de164aaaSGreg Clayton                  case 'h':
1203de164aaaSGreg Clayton                      m_help.assign (option_arg);
1204de164aaaSGreg Clayton                      break;
1205de164aaaSGreg Clayton                  case 's':
1206de164aaaSGreg Clayton                      m_syntax.assign (option_arg);
1207de164aaaSGreg Clayton                      break;
1208de164aaaSGreg Clayton 
1209de164aaaSGreg Clayton                  default:
1210de164aaaSGreg Clayton                      error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1211de164aaaSGreg Clayton                      break;
1212de164aaaSGreg Clayton              }
1213de164aaaSGreg Clayton 
1214de164aaaSGreg Clayton              return error;
1215de164aaaSGreg Clayton          }
1216de164aaaSGreg Clayton 
1217de164aaaSGreg Clayton          void
1218de164aaaSGreg Clayton          OptionParsingStarting ()
1219de164aaaSGreg Clayton          {
1220de164aaaSGreg Clayton              m_help.clear();
1221de164aaaSGreg Clayton              m_syntax.clear();
1222de164aaaSGreg Clayton          }
1223de164aaaSGreg Clayton 
1224de164aaaSGreg Clayton          const OptionDefinition*
1225de164aaaSGreg Clayton          GetDefinitions ()
1226de164aaaSGreg Clayton          {
1227de164aaaSGreg Clayton              return g_option_table;
1228de164aaaSGreg Clayton          }
1229de164aaaSGreg Clayton 
1230de164aaaSGreg Clayton          // Options table: Required for subclasses of Options.
1231de164aaaSGreg Clayton 
1232de164aaaSGreg Clayton          static OptionDefinition g_option_table[];
1233de164aaaSGreg Clayton 
1234de164aaaSGreg Clayton          const char *
1235de164aaaSGreg Clayton          GetHelp ()
1236de164aaaSGreg Clayton          {
1237de164aaaSGreg Clayton              if (m_help.empty())
1238de164aaaSGreg Clayton                  return NULL;
1239de164aaaSGreg Clayton              return m_help.c_str();
1240de164aaaSGreg Clayton          }
1241de164aaaSGreg Clayton          const char *
1242de164aaaSGreg Clayton          GetSyntax ()
1243de164aaaSGreg Clayton          {
1244de164aaaSGreg Clayton              if (m_syntax.empty())
1245de164aaaSGreg Clayton                  return NULL;
1246de164aaaSGreg Clayton              return m_syntax.c_str();
1247de164aaaSGreg Clayton          }
1248de164aaaSGreg Clayton          // Instance variables to hold the values for command options.
1249de164aaaSGreg Clayton      protected:
1250de164aaaSGreg Clayton          std::string m_help;
1251de164aaaSGreg Clayton          std::string m_syntax;
1252de164aaaSGreg Clayton      };
1253de164aaaSGreg Clayton 
1254de164aaaSGreg Clayton      CommandOptions m_options;
1255de164aaaSGreg Clayton 
1256de164aaaSGreg Clayton      virtual Options *
1257de164aaaSGreg Clayton      GetOptions ()
1258de164aaaSGreg Clayton      {
1259de164aaaSGreg Clayton          return &m_options;
1260de164aaaSGreg Clayton      }
1261de164aaaSGreg Clayton 
1262de164aaaSGreg Clayton };
1263de164aaaSGreg Clayton 
1264de164aaaSGreg Clayton size_t
1265de164aaaSGreg Clayton CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1266de164aaaSGreg Clayton                                                     InputReader &reader,
1267de164aaaSGreg Clayton                                                     lldb::InputReaderAction notification,
1268de164aaaSGreg Clayton                                                     const char *bytes,
1269de164aaaSGreg Clayton                                                     size_t bytes_len)
1270de164aaaSGreg Clayton {
1271de164aaaSGreg Clayton     CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
1272d61c10bcSCaroline Tice     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
1273de164aaaSGreg Clayton 
1274de164aaaSGreg Clayton     switch (notification)
1275de164aaaSGreg Clayton     {
1276de164aaaSGreg Clayton         case eInputReaderActivate:
1277d61c10bcSCaroline Tice             if (!batch_mode)
127815356e7fSCaroline Tice             {
127915356e7fSCaroline Tice                 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
128015356e7fSCaroline Tice                 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
128115356e7fSCaroline Tice                 out_stream->Flush();
128215356e7fSCaroline Tice             }
1283de164aaaSGreg Clayton             break;
1284de164aaaSGreg Clayton         case eInputReaderReactivate:
1285de164aaaSGreg Clayton             break;
1286de164aaaSGreg Clayton 
1287de164aaaSGreg Clayton         case eInputReaderDeactivate:
1288de164aaaSGreg Clayton             break;
1289de164aaaSGreg Clayton 
1290969ed3d1SCaroline Tice         case eInputReaderAsynchronousOutputWritten:
1291969ed3d1SCaroline Tice             break;
1292969ed3d1SCaroline Tice 
1293de164aaaSGreg Clayton         case eInputReaderGotToken:
12940e5e5a79SGreg Clayton             while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
12950e5e5a79SGreg Clayton                 --bytes_len;
1296de164aaaSGreg Clayton             if (bytes_len == 0)
1297de164aaaSGreg Clayton                 reader.SetIsDone(true);
1298de164aaaSGreg Clayton             else if (bytes)
1299de164aaaSGreg Clayton             {
13000e5e5a79SGreg Clayton                 llvm::StringRef bytes_strref (bytes, bytes_len);
13010e5e5a79SGreg Clayton                 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
13020e5e5a79SGreg Clayton                 if (error.Fail())
1303de164aaaSGreg Clayton                 {
1304d61c10bcSCaroline Tice                     if (!batch_mode)
1305d61c10bcSCaroline Tice                     {
130615356e7fSCaroline Tice                         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
130715356e7fSCaroline Tice                         out_stream->Printf("error: %s\n", error.AsCString());
130815356e7fSCaroline Tice                         out_stream->Flush();
1309d61c10bcSCaroline Tice                     }
13100e5e5a79SGreg Clayton                     add_regex_cmd->InputReaderDidCancel ();
13110e5e5a79SGreg Clayton                     reader.SetIsDone (true);
1312de164aaaSGreg Clayton                 }
1313de164aaaSGreg Clayton             }
1314de164aaaSGreg Clayton             break;
1315de164aaaSGreg Clayton 
1316de164aaaSGreg Clayton         case eInputReaderInterrupt:
131715356e7fSCaroline Tice             {
1318de164aaaSGreg Clayton                 reader.SetIsDone (true);
1319d61c10bcSCaroline Tice                 if (!batch_mode)
1320d61c10bcSCaroline Tice                 {
132115356e7fSCaroline Tice                     StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
132215356e7fSCaroline Tice                     out_stream->PutCString("Regular expression command creations was cancelled.\n");
132315356e7fSCaroline Tice                     out_stream->Flush();
1324d61c10bcSCaroline Tice                 }
13250e5e5a79SGreg Clayton                 add_regex_cmd->InputReaderDidCancel ();
132615356e7fSCaroline Tice             }
1327de164aaaSGreg Clayton             break;
1328de164aaaSGreg Clayton 
1329de164aaaSGreg Clayton         case eInputReaderEndOfFile:
1330de164aaaSGreg Clayton             reader.SetIsDone (true);
1331de164aaaSGreg Clayton             break;
1332de164aaaSGreg Clayton 
1333de164aaaSGreg Clayton         case eInputReaderDone:
13340e5e5a79SGreg Clayton             add_regex_cmd->AddRegexCommandToInterpreter();
1335de164aaaSGreg Clayton             break;
1336de164aaaSGreg Clayton     }
1337de164aaaSGreg Clayton 
1338de164aaaSGreg Clayton     return bytes_len;
1339de164aaaSGreg Clayton }
1340de164aaaSGreg Clayton 
1341de164aaaSGreg Clayton 
1342de164aaaSGreg Clayton OptionDefinition
1343de164aaaSGreg Clayton CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1344de164aaaSGreg Clayton {
1345de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "help"  , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
1346de164aaaSGreg Clayton { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1347de164aaaSGreg Clayton { 0             , false,  NULL   , 0  , 0                , NULL, 0, eArgTypeNone, NULL }
1348de164aaaSGreg Clayton };
1349de164aaaSGreg Clayton 
1350de164aaaSGreg Clayton 
1351ebc09c36SJim Ingham #pragma mark CommandObjectMultiwordCommands
1352ebc09c36SJim Ingham 
1353ebc09c36SJim Ingham //-------------------------------------------------------------------------
1354ebc09c36SJim Ingham // CommandObjectMultiwordCommands
1355ebc09c36SJim Ingham //-------------------------------------------------------------------------
1356ebc09c36SJim Ingham 
1357ebc09c36SJim Ingham CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
1358a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
13590e5e5a79SGreg Clayton                             "command",
13603f4c09c1SCaroline Tice                             "A set of commands for managing or customizing the debugger commands.",
13610e5e5a79SGreg Clayton                             "command <subcommand> [<subcommand-options>]")
1362ebc09c36SJim Ingham {
1363a7015092SGreg Clayton     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1364a7015092SGreg Clayton     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1365a7015092SGreg Clayton     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
1366de164aaaSGreg Clayton     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
1367a5a97ebeSJim Ingham     LoadSubCommand ("history",   CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
1368ebc09c36SJim Ingham }
1369ebc09c36SJim Ingham 
1370ebc09c36SJim Ingham CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1371ebc09c36SJim Ingham {
1372ebc09c36SJim Ingham }
1373ebc09c36SJim Ingham 
1374