1 //===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CommandObjectCommands.h"
11 
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 #include "llvm/ADT/StringRef.h"
16 
17 // Project includes
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/InputReader.h"
20 #include "lldb/Interpreter/Args.h"
21 #include "lldb/Interpreter/CommandInterpreter.h"
22 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Interpreter/Options.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //-------------------------------------------------------------------------
30 // CommandObjectCommandsSource
31 //-------------------------------------------------------------------------
32 
33 class CommandObjectCommandsHistory : public CommandObject
34 {
35 private:
36 
37     class CommandOptions : public Options
38     {
39     public:
40 
41         CommandOptions (CommandInterpreter &interpreter) :
42             Options (interpreter)
43         {
44         }
45 
46         virtual
47         ~CommandOptions (){}
48 
49         virtual Error
50         SetOptionValue (uint32_t option_idx, const char *option_arg)
51         {
52             Error error;
53             char short_option = (char) m_getopt_table[option_idx].val;
54             bool success;
55 
56             switch (short_option)
57             {
58                 case 'c':
59                     m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
60                     if (!success)
61                         error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
62                     if (m_end_idx != 0)
63                         m_end_idx--;
64                     m_start_idx = 0;
65                     break;
66                 case 'e':
67                     m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
68                     if (!success)
69                         error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
70                     break;
71                 case 's':
72                     m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
73                     if (!success)
74                         error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
75                     break;
76                 default:
77                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
78                     break;
79             }
80 
81             return error;
82         }
83 
84         void
85         OptionParsingStarting ()
86         {
87             m_start_idx = 0;
88             m_end_idx = UINT_MAX;
89         }
90 
91         const OptionDefinition*
92         GetDefinitions ()
93         {
94             return g_option_table;
95         }
96 
97         // Options table: Required for subclasses of Options.
98 
99         static OptionDefinition g_option_table[];
100 
101         // Instance variables to hold the values for command options.
102 
103         uint32_t m_start_idx;
104         uint32_t m_end_idx;
105     };
106 
107     CommandOptions m_options;
108 
109     virtual Options *
110     GetOptions ()
111     {
112         return &m_options;
113     }
114 
115 public:
116     CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
117         CommandObject (interpreter,
118                        "command history",
119                        "Dump the history of commands in this session.",
120                        NULL),
121         m_options (interpreter)
122     {
123     }
124 
125     ~CommandObjectCommandsHistory ()
126     {
127     }
128 
129     bool
130     Execute
131     (
132         Args& args,
133         CommandReturnObject &result
134     )
135     {
136 
137         m_interpreter.DumpHistory (result.GetOutputStream(),
138                                    m_options.m_start_idx,
139                                    m_options.m_end_idx);
140         return result.Succeeded();
141 
142     }
143 };
144 
145 OptionDefinition
146 CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
147 {
148 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger,        "How many history commands to print."},
149 { LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger,  "Index at which to start printing history commands."},
150 { LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger,    "Index at which to stop printing history commands."},
151 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
152 };
153 
154 
155 //-------------------------------------------------------------------------
156 // CommandObjectCommandsSource
157 //-------------------------------------------------------------------------
158 
159 class CommandObjectCommandsSource : public CommandObject
160 {
161 private:
162 
163     class CommandOptions : public Options
164     {
165     public:
166 
167         CommandOptions (CommandInterpreter &interpreter) :
168             Options (interpreter)
169         {
170         }
171 
172         virtual
173         ~CommandOptions (){}
174 
175         virtual Error
176         SetOptionValue (uint32_t option_idx, const char *option_arg)
177         {
178             Error error;
179             char short_option = (char) m_getopt_table[option_idx].val;
180             bool success;
181 
182             switch (short_option)
183             {
184                 case 'e':
185                     m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
186                     if (!success)
187                         error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
188                     break;
189                 case 'c':
190                     m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
191                     if (!success)
192                         error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
193                     break;
194                 default:
195                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
196                     break;
197             }
198 
199             return error;
200         }
201 
202         void
203         OptionParsingStarting ()
204         {
205             m_stop_on_error = true;
206             m_stop_on_continue = true;
207         }
208 
209         const OptionDefinition*
210         GetDefinitions ()
211         {
212             return g_option_table;
213         }
214 
215         // Options table: Required for subclasses of Options.
216 
217         static OptionDefinition g_option_table[];
218 
219         // Instance variables to hold the values for command options.
220 
221         bool m_stop_on_error;
222         bool m_stop_on_continue;
223     };
224 
225     CommandOptions m_options;
226 
227     virtual Options *
228     GetOptions ()
229     {
230         return &m_options;
231     }
232 
233 public:
234     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
235         CommandObject (interpreter,
236                        "command source",
237                        "Read in debugger commands from the file <filename> and execute them.",
238                        NULL),
239         m_options (interpreter)
240     {
241         CommandArgumentEntry arg;
242         CommandArgumentData file_arg;
243 
244         // Define the first (and only) variant of this arg.
245         file_arg.arg_type = eArgTypeFilename;
246         file_arg.arg_repetition = eArgRepeatPlain;
247 
248         // There is only one variant this argument could be; put it into the argument entry.
249         arg.push_back (file_arg);
250 
251         // Push the data for the first argument into the m_arguments vector.
252         m_arguments.push_back (arg);
253     }
254 
255     ~CommandObjectCommandsSource ()
256     {
257     }
258 
259     bool
260     Execute
261     (
262         Args& args,
263         CommandReturnObject &result
264     )
265     {
266         const int argc = args.GetArgumentCount();
267         if (argc == 1)
268         {
269             const char *filename = args.GetArgumentAtIndex(0);
270 
271             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
272 
273             FileSpec cmd_file (filename, true);
274             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
275             bool echo_commands    = true;
276             bool print_results    = true;
277 
278             m_interpreter.HandleCommandsFromFile (cmd_file,
279                                                   exe_ctx,
280                                                   m_options.m_stop_on_continue,
281                                                   m_options.m_stop_on_error,
282                                                   echo_commands,
283                                                   print_results,
284                                                   result);
285         }
286         else
287         {
288             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
289             result.SetStatus (eReturnStatusFailed);
290         }
291         return result.Succeeded();
292 
293     }
294 };
295 
296 OptionDefinition
297 CommandObjectCommandsSource::CommandOptions::g_option_table[] =
298 {
299 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
300 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
301 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
302 };
303 
304 #pragma mark CommandObjectCommandsAlias
305 //-------------------------------------------------------------------------
306 // CommandObjectCommandsAlias
307 //-------------------------------------------------------------------------
308 
309 class CommandObjectCommandsAlias : public CommandObject
310 {
311 public:
312     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
313         CommandObject (interpreter,
314                        "command alias",
315                        "Allow users to define their own debugger command abbreviations.",
316                        NULL)
317     {
318         SetHelpLong(
319     "'alias' allows the user to create a short-cut or abbreviation for long \n\
320     commands, multi-word commands, and commands that take particular options. \n\
321     Below are some simple examples of how one might use the 'alias' command: \n\
322     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
323                                          // command. \n\
324     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
325                                          // command.  Since breakpoint commands are two-word \n\
326                                          // commands, the user will still need to enter the \n\
327                                          // second word after 'bp', e.g. 'bp enable' or \n\
328                                          // 'bp delete'. \n\
329     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
330                                          // two-word command 'breakpoint list'. \n\
331     \nAn alias can include some options for the command, with the values either \n\
332     filled in at the time the alias is created, or specified as positional \n\
333     arguments, to be filled in when the alias is invoked.  The following example \n\
334     shows how to create aliases with options: \n\
335     \n\
336     'commands alias bfl breakpoint set -f %1 -l %2' \n\
337     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
338     options already part of the alias.  So if the user wants to set a breakpoint \n\
339     by file and line without explicitly having to use the -f and -l options, the \n\
340     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
341     for the actual arguments that will be passed when the alias command is used. \n\
342     The number in the placeholder refers to the position/order the actual value \n\
343     occupies when the alias is used.  So all the occurrences of '%1' in the alias \n\
344     will be replaced with the first argument, all the occurrences of '%2' in the \n\
345     alias will be replaced with the second argument, and so on.  This also allows \n\
346     actual arguments to be used multiple times within an alias (see 'process \n\
347     launch' example below).  So in the 'bfl' case, the actual file value will be \n\
348     filled in with the first argument following 'bfl' and the actual line number \n\
349     value will be filled in with the second argument.  The user would use this \n\
350     alias as follows: \n\
351     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
352     <... some time later ...> \n\
353     (lldb)  bfl my-file.c 137 \n\
354     \nThis would be the same as if the user had entered \n\
355     'breakpoint set -f my-file.c -l 137'. \n\
356     \nAnother example: \n\
357     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
358     (lldb)  pltty /dev/tty0 \n\
359            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
360     \nIf the user always wanted to pass the same value to a particular option, the \n\
361     alias could be defined with that value directly in the alias as a constant, \n\
362     rather than using a positional placeholder: \n\
363     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
364                                                    // 3 of whatever file is indicated. \n");
365 
366         CommandArgumentEntry arg1;
367         CommandArgumentEntry arg2;
368         CommandArgumentEntry arg3;
369         CommandArgumentData alias_arg;
370         CommandArgumentData cmd_arg;
371         CommandArgumentData options_arg;
372 
373         // Define the first (and only) variant of this arg.
374         alias_arg.arg_type = eArgTypeAliasName;
375         alias_arg.arg_repetition = eArgRepeatPlain;
376 
377         // There is only one variant this argument could be; put it into the argument entry.
378         arg1.push_back (alias_arg);
379 
380         // Define the first (and only) variant of this arg.
381         cmd_arg.arg_type = eArgTypeCommandName;
382         cmd_arg.arg_repetition = eArgRepeatPlain;
383 
384         // There is only one variant this argument could be; put it into the argument entry.
385         arg2.push_back (cmd_arg);
386 
387         // Define the first (and only) variant of this arg.
388         options_arg.arg_type = eArgTypeAliasOptions;
389         options_arg.arg_repetition = eArgRepeatOptional;
390 
391         // There is only one variant this argument could be; put it into the argument entry.
392         arg3.push_back (options_arg);
393 
394         // Push the data for the first argument into the m_arguments vector.
395         m_arguments.push_back (arg1);
396         m_arguments.push_back (arg2);
397         m_arguments.push_back (arg3);
398     }
399 
400     ~CommandObjectCommandsAlias ()
401     {
402     }
403 
404     bool
405     WantsRawCommandString ()
406     {
407         return true;
408     }
409 
410     bool
411     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
412     {
413         Args args (raw_command_line);
414         std::string raw_command_string (raw_command_line);
415 
416         size_t argc = args.GetArgumentCount();
417 
418         if (argc < 2)
419         {
420             result.AppendError ("'alias' requires at least two arguments");
421             result.SetStatus (eReturnStatusFailed);
422             return false;
423         }
424 
425         // Get the alias command.
426 
427         const std::string alias_command = args.GetArgumentAtIndex (0);
428 
429         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
430         // does the stripping itself.
431         size_t pos = raw_command_string.find (alias_command);
432         if (pos == 0)
433         {
434             raw_command_string = raw_command_string.substr (alias_command.size());
435             pos = raw_command_string.find_first_not_of (' ');
436             if ((pos != std::string::npos) && (pos > 0))
437                 raw_command_string = raw_command_string.substr (pos);
438         }
439         else
440         {
441             result.AppendError ("Error parsing command string.  No alias created.");
442             result.SetStatus (eReturnStatusFailed);
443             return false;
444         }
445 
446 
447         // Verify that the command is alias-able.
448         if (m_interpreter.CommandExists (alias_command.c_str()))
449         {
450             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
451                                           alias_command.c_str());
452             result.SetStatus (eReturnStatusFailed);
453             return false;
454         }
455 
456         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
457         // raw_command_string is returned with the name of the command object stripped off the front.
458         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
459 
460         if (!cmd_obj)
461         {
462             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
463                                           "  No alias created.", raw_command_string.c_str());
464             result.SetStatus (eReturnStatusFailed);
465             return false;
466         }
467         else if (!cmd_obj->WantsRawCommandString ())
468         {
469             // Note that args was initialized with the original command, and has not been updated to this point.
470             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
471             return Execute (args, result);
472         }
473         else
474         {
475             // Verify & handle any options/arguments passed to the alias command
476 
477             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
478             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
479 
480             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
481 
482             if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
483             {
484                 result.AppendError ("Unable to create requested alias.\n");
485                 result.SetStatus (eReturnStatusFailed);
486                 return false;
487             }
488 
489             // Create the alias
490             if (m_interpreter.AliasExists (alias_command.c_str())
491                 || m_interpreter.UserCommandExists (alias_command.c_str()))
492             {
493                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
494                 if (temp_option_arg_sp.get())
495                 {
496                     if (option_arg_vector->size() == 0)
497                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
498                 }
499                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
500                                                 alias_command.c_str());
501             }
502 
503             if (cmd_obj_sp)
504             {
505                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
506                 if (option_arg_vector->size() > 0)
507                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
508                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
509             }
510             else
511             {
512                 result.AppendError ("Unable to create requested alias.\n");
513                 result.SetStatus (eReturnStatusFailed);
514             }
515         }
516         return result.Succeeded();
517     }
518 
519     bool
520     Execute
521     (
522         Args& args,
523         CommandReturnObject &result
524     )
525     {
526         size_t argc = args.GetArgumentCount();
527 
528         if (argc < 2)
529         {
530             result.AppendError ("'alias' requires at least two arguments");
531             result.SetStatus (eReturnStatusFailed);
532             return false;
533         }
534 
535         const std::string alias_command = args.GetArgumentAtIndex(0);
536         const std::string actual_command = args.GetArgumentAtIndex(1);
537 
538         args.Shift();  // Shift the alias command word off the argument vector.
539         args.Shift();  // Shift the old command word off the argument vector.
540 
541         // Verify that the command is alias'able, and get the appropriate command object.
542 
543         if (m_interpreter.CommandExists (alias_command.c_str()))
544         {
545             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
546                                          alias_command.c_str());
547             result.SetStatus (eReturnStatusFailed);
548         }
549         else
550         {
551              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
552              CommandObjectSP subcommand_obj_sp;
553              bool use_subcommand = false;
554              if (command_obj_sp.get())
555              {
556                  CommandObject *cmd_obj = command_obj_sp.get();
557                  CommandObject *sub_cmd_obj = NULL;
558                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
559                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
560 
561                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
562                  {
563                      if (argc >= 3)
564                      {
565                          const std::string sub_command = args.GetArgumentAtIndex(0);
566                          assert (sub_command.length() != 0);
567                          subcommand_obj_sp =
568                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
569                          if (subcommand_obj_sp.get())
570                          {
571                              sub_cmd_obj = subcommand_obj_sp.get();
572                              use_subcommand = true;
573                              args.Shift();  // Shift the sub_command word off the argument vector.
574                              cmd_obj = sub_cmd_obj;
575                          }
576                          else
577                          {
578                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
579                                                           "Unable to create alias.\n",
580                                                           sub_command.c_str(), actual_command.c_str());
581                              result.SetStatus (eReturnStatusFailed);
582                              return false;
583                          }
584                      }
585                  }
586 
587                  // Verify & handle any options/arguments passed to the alias command
588 
589                  if (args.GetArgumentCount () > 0)
590                  {
591                     CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
592                     if (use_subcommand)
593                         tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
594 
595                     std::string args_string;
596                     args.GetCommandString (args_string);
597 
598                     if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
599                     {
600                         result.AppendError ("Unable to create requested alias.\n");
601                         result.SetStatus (eReturnStatusFailed);
602                         return false;
603                     }
604                  }
605 
606                  // Create the alias.
607 
608                  if (m_interpreter.AliasExists (alias_command.c_str())
609                      || m_interpreter.UserCommandExists (alias_command.c_str()))
610                  {
611                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
612                      if (tmp_option_arg_sp.get())
613                      {
614                          if (option_arg_vector->size() == 0)
615                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
616                      }
617                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
618                                                      alias_command.c_str());
619                  }
620 
621                  if (use_subcommand)
622                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
623                  else
624                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
625                  if (option_arg_vector->size() > 0)
626                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
627                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
628              }
629              else
630              {
631                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
632                  result.SetStatus (eReturnStatusFailed);
633                  return false;
634              }
635         }
636 
637         return result.Succeeded();
638     }
639 };
640 
641 #pragma mark CommandObjectCommandsUnalias
642 //-------------------------------------------------------------------------
643 // CommandObjectCommandsUnalias
644 //-------------------------------------------------------------------------
645 
646 class CommandObjectCommandsUnalias : public CommandObject
647 {
648 public:
649     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
650         CommandObject (interpreter,
651                        "command unalias",
652                        "Allow the user to remove/delete a user-defined command abbreviation.",
653                        NULL)
654     {
655         CommandArgumentEntry arg;
656         CommandArgumentData alias_arg;
657 
658         // Define the first (and only) variant of this arg.
659         alias_arg.arg_type = eArgTypeAliasName;
660         alias_arg.arg_repetition = eArgRepeatPlain;
661 
662         // There is only one variant this argument could be; put it into the argument entry.
663         arg.push_back (alias_arg);
664 
665         // Push the data for the first argument into the m_arguments vector.
666         m_arguments.push_back (arg);
667     }
668 
669     ~CommandObjectCommandsUnalias()
670     {
671     }
672 
673 
674     bool
675     Execute
676     (
677         Args& args,
678         CommandReturnObject &result
679     )
680     {
681         CommandObject::CommandMap::iterator pos;
682         CommandObject *cmd_obj;
683 
684         if (args.GetArgumentCount() != 0)
685         {
686             const char *command_name = args.GetArgumentAtIndex(0);
687             cmd_obj = m_interpreter.GetCommandObject(command_name);
688             if (cmd_obj)
689             {
690                 if (m_interpreter.CommandExists (command_name))
691                 {
692                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
693                                                   command_name);
694                     result.SetStatus (eReturnStatusFailed);
695                 }
696                 else
697                 {
698 
699                     if (m_interpreter.RemoveAlias (command_name) == false)
700                     {
701                         if (m_interpreter.AliasExists (command_name))
702                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
703                                                           command_name);
704                         else
705                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
706                         result.SetStatus (eReturnStatusFailed);
707                     }
708                     else
709                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
710                 }
711             }
712             else
713             {
714                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
715                                               "current list of commands.\n",
716                                              command_name);
717                 result.SetStatus (eReturnStatusFailed);
718             }
719         }
720         else
721         {
722             result.AppendError ("must call 'unalias' with a valid alias");
723             result.SetStatus (eReturnStatusFailed);
724         }
725 
726         return result.Succeeded();
727     }
728 };
729 
730 #pragma mark CommandObjectCommandsAddRegex
731 //-------------------------------------------------------------------------
732 // CommandObjectCommandsAddRegex
733 //-------------------------------------------------------------------------
734 
735 class CommandObjectCommandsAddRegex : public CommandObject
736 {
737 public:
738     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
739         CommandObject (interpreter,
740                        "command regex",
741                        "Allow the user to create a regular expression command.",
742                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
743         m_options (interpreter)
744     {
745         SetHelpLong(
746 "This command allows the user to create powerful regular expression commands\n"
747 "with substitutions. The regular expressions and substitutions are specified\n"
748 "using the regular exression substitution format of:\n"
749 "\n"
750 "    s/<regex>/<subst>/\n"
751 "\n"
752 "<regex> is a regular expression that can use parenthesis to capture regular\n"
753 "expression input and substitute the captured matches in the output using %1\n"
754 "for the first match, %2 for the second, and so on.\n"
755 "\n"
756 "The regular expressions can all be specified on the command line if more than\n"
757 "one argument is provided. If just the command name is provided on the command\n"
758 "line, then the regular expressions and substitutions can be entered on separate\n"
759 " lines, followed by an empty line to terminate the command definition.\n"
760 "\n"
761 "EXAMPLES\n"
762 "\n"
763 "The following example with define a regular expression command named 'f' that\n"
764 "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
765 "a number follows 'f':\n"
766 "(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
767                     );
768     }
769 
770     ~CommandObjectCommandsAddRegex()
771     {
772     }
773 
774 
775     bool
776     Execute (Args& args, CommandReturnObject &result)
777     {
778         const size_t argc = args.GetArgumentCount();
779         if (argc == 0)
780         {
781             result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
782             result.SetStatus (eReturnStatusFailed);
783         }
784         else
785         {
786             Error error;
787             const char *name = args.GetArgumentAtIndex(0);
788             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
789                                                                  name,
790                                                                  m_options.GetHelp (),
791                                                                  m_options.GetSyntax (),
792                                                                  10));
793 
794             if (argc == 1)
795             {
796                 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
797                 if (reader_sp)
798                 {
799                     error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
800                                                   this,                         // baton
801                                                   eInputReaderGranularityLine,  // token size, to pass to callback function
802                                                   NULL,                         // end token
803                                                   "> ",                         // prompt
804                                                   true);                        // echo input
805                     if (error.Success())
806                     {
807                         m_interpreter.GetDebugger().PushInputReader (reader_sp);
808                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
809                         return true;
810                     }
811                 }
812             }
813             else
814             {
815                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
816                 {
817                     llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
818                     error = AppendRegexSubstitution (arg_strref);
819                     if (error.Fail())
820                         break;
821                 }
822 
823                 if (error.Success())
824                 {
825                     AddRegexCommandToInterpreter();
826                 }
827             }
828             if (error.Fail())
829             {
830                 result.AppendError (error.AsCString());
831                 result.SetStatus (eReturnStatusFailed);
832             }
833         }
834 
835         return result.Succeeded();
836     }
837 
838     Error
839     AppendRegexSubstitution (const llvm::StringRef &regex_sed)
840     {
841         Error error;
842 
843         if (m_regex_cmd_ap.get() == NULL)
844         {
845             error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
846                                            (int)regex_sed.size(),
847                                            regex_sed.data());
848             return error;
849         }
850 
851         size_t regex_sed_size = regex_sed.size();
852 
853         if (regex_sed_size <= 1)
854         {
855             error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
856                                            (int)regex_sed.size(),
857                                            regex_sed.data());
858             return error;
859         }
860 
861         if (regex_sed[0] != 's')
862         {
863             error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
864                                            (int)regex_sed.size(),
865                                            regex_sed.data());
866             return error;
867         }
868         const size_t first_separator_char_pos = 1;
869         // use the char that follows 's' as the regex separator character
870         // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
871         const char separator_char = regex_sed[first_separator_char_pos];
872         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
873 
874         if (second_separator_char_pos == std::string::npos)
875         {
876             error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
877                                            separator_char,
878                                            (int)(regex_sed.size() - first_separator_char_pos - 1),
879                                            regex_sed.data() + (first_separator_char_pos + 1));
880             return error;
881         }
882 
883         const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
884 
885         if (third_separator_char_pos == std::string::npos)
886         {
887             error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
888                                            separator_char,
889                                            (int)(regex_sed.size() - second_separator_char_pos - 1),
890                                            regex_sed.data() + (second_separator_char_pos + 1));
891             return error;
892         }
893 
894         if (third_separator_char_pos != regex_sed_size - 1)
895         {
896             // Make sure that everything that follows the last regex
897             // separator char
898             if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
899             {
900                 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
901                                                (int)third_separator_char_pos + 1,
902                                                regex_sed.data(),
903                                                (int)(regex_sed.size() - third_separator_char_pos - 1),
904                                                regex_sed.data() + (third_separator_char_pos + 1));
905                 return error;
906             }
907 
908         }
909         else if (first_separator_char_pos + 1 == second_separator_char_pos)
910         {
911             error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
912                                            separator_char,
913                                            separator_char,
914                                            separator_char,
915                                            (int)regex_sed.size(),
916                                            regex_sed.data());
917             return error;
918         }
919         else if (second_separator_char_pos + 1 == third_separator_char_pos)
920         {
921             error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
922                                            separator_char,
923                                            separator_char,
924                                            separator_char,
925                                            (int)regex_sed.size(),
926                                            regex_sed.data());
927             return error;
928         }
929         std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
930         std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
931         m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
932                                          subst.c_str());
933         return error;
934     }
935 
936     void
937     AddRegexCommandToInterpreter()
938     {
939         if (m_regex_cmd_ap.get())
940         {
941             if (m_regex_cmd_ap->HasRegexEntries())
942             {
943                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
944                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
945             }
946         }
947     }
948 
949     void
950     InputReaderDidCancel()
951     {
952         m_regex_cmd_ap.reset();
953     }
954 
955     static size_t
956     InputReaderCallback (void *baton,
957                          InputReader &reader,
958                          lldb::InputReaderAction notification,
959                          const char *bytes,
960                          size_t bytes_len);
961 private:
962     std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
963 
964      class CommandOptions : public Options
965      {
966      public:
967 
968          CommandOptions (CommandInterpreter &interpreter) :
969             Options (interpreter)
970          {
971          }
972 
973          virtual
974          ~CommandOptions (){}
975 
976          virtual Error
977          SetOptionValue (uint32_t option_idx, const char *option_arg)
978          {
979              Error error;
980              char short_option = (char) m_getopt_table[option_idx].val;
981 
982              switch (short_option)
983              {
984                  case 'h':
985                      m_help.assign (option_arg);
986                      break;
987                  case 's':
988                      m_syntax.assign (option_arg);
989                      break;
990 
991                  default:
992                      error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
993                      break;
994              }
995 
996              return error;
997          }
998 
999          void
1000          OptionParsingStarting ()
1001          {
1002              m_help.clear();
1003              m_syntax.clear();
1004          }
1005 
1006          const OptionDefinition*
1007          GetDefinitions ()
1008          {
1009              return g_option_table;
1010          }
1011 
1012          // Options table: Required for subclasses of Options.
1013 
1014          static OptionDefinition g_option_table[];
1015 
1016          const char *
1017          GetHelp ()
1018          {
1019              if (m_help.empty())
1020                  return NULL;
1021              return m_help.c_str();
1022          }
1023          const char *
1024          GetSyntax ()
1025          {
1026              if (m_syntax.empty())
1027                  return NULL;
1028              return m_syntax.c_str();
1029          }
1030          // Instance variables to hold the values for command options.
1031      protected:
1032          std::string m_help;
1033          std::string m_syntax;
1034      };
1035 
1036      CommandOptions m_options;
1037 
1038      virtual Options *
1039      GetOptions ()
1040      {
1041          return &m_options;
1042      }
1043 
1044 };
1045 
1046 size_t
1047 CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1048                                                     InputReader &reader,
1049                                                     lldb::InputReaderAction notification,
1050                                                     const char *bytes,
1051                                                     size_t bytes_len)
1052 {
1053     CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
1054     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
1055 
1056     switch (notification)
1057     {
1058         case eInputReaderActivate:
1059             if (!batch_mode)
1060             {
1061                 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1062                 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1063                 out_stream->Flush();
1064             }
1065             break;
1066         case eInputReaderReactivate:
1067             break;
1068 
1069         case eInputReaderDeactivate:
1070             break;
1071 
1072         case eInputReaderAsynchronousOutputWritten:
1073             break;
1074 
1075         case eInputReaderGotToken:
1076             while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1077                 --bytes_len;
1078             if (bytes_len == 0)
1079                 reader.SetIsDone(true);
1080             else if (bytes)
1081             {
1082                 llvm::StringRef bytes_strref (bytes, bytes_len);
1083                 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1084                 if (error.Fail())
1085                 {
1086                     if (!batch_mode)
1087                     {
1088                         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1089                         out_stream->Printf("error: %s\n", error.AsCString());
1090                         out_stream->Flush();
1091                     }
1092                     add_regex_cmd->InputReaderDidCancel ();
1093                     reader.SetIsDone (true);
1094                 }
1095             }
1096             break;
1097 
1098         case eInputReaderInterrupt:
1099             {
1100                 reader.SetIsDone (true);
1101                 if (!batch_mode)
1102                 {
1103                     StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1104                     out_stream->PutCString("Regular expression command creations was cancelled.\n");
1105                     out_stream->Flush();
1106                 }
1107                 add_regex_cmd->InputReaderDidCancel ();
1108             }
1109             break;
1110 
1111         case eInputReaderEndOfFile:
1112             reader.SetIsDone (true);
1113             break;
1114 
1115         case eInputReaderDone:
1116             add_regex_cmd->AddRegexCommandToInterpreter();
1117             break;
1118     }
1119 
1120     return bytes_len;
1121 }
1122 
1123 
1124 OptionDefinition
1125 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1126 {
1127 { LLDB_OPT_SET_1, false, "help"  , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
1128 { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1129 { 0             , false,  NULL   , 0  , 0                , NULL, 0, eArgTypeNone, NULL }
1130 };
1131 
1132 
1133 #pragma mark CommandObjectMultiwordCommands
1134 
1135 //-------------------------------------------------------------------------
1136 // CommandObjectMultiwordCommands
1137 //-------------------------------------------------------------------------
1138 
1139 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
1140     CommandObjectMultiword (interpreter,
1141                             "command",
1142                             "A set of commands for managing or customizing the debugger commands.",
1143                             "command <subcommand> [<subcommand-options>]")
1144 {
1145     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1146     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1147     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
1148     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
1149     LoadSubCommand ("history",   CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
1150 }
1151 
1152 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1153 {
1154 }
1155 
1156