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/Core/InputReaderEZ.h"
21 #include "lldb/Core/StringList.h"
22 #include "lldb/Interpreter/Args.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/Options.h"
27 #include "lldb/Interpreter/ScriptInterpreter.h"
28 #include "lldb/Interpreter/ScriptInterpreterPython.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 //-------------------------------------------------------------------------
34 // CommandObjectCommandsSource
35 //-------------------------------------------------------------------------
36 
37 class CommandObjectCommandsHistory : public CommandObject
38 {
39 private:
40 
41     class CommandOptions : public Options
42     {
43     public:
44 
45         CommandOptions (CommandInterpreter &interpreter) :
46             Options (interpreter)
47         {
48         }
49 
50         virtual
51         ~CommandOptions (){}
52 
53         virtual Error
54         SetOptionValue (uint32_t option_idx, const char *option_arg)
55         {
56             Error error;
57             char short_option = (char) m_getopt_table[option_idx].val;
58             bool success;
59 
60             switch (short_option)
61             {
62                 case 'c':
63                     m_end_idx = Args::StringToUInt32(option_arg, UINT_MAX, 0, &success);
64                     if (!success)
65                         error.SetErrorStringWithFormat("Invalid value for count: %s.\n", option_arg);
66                     if (m_end_idx != 0)
67                         m_end_idx--;
68                     m_start_idx = 0;
69                     break;
70                 case 'e':
71                     m_end_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
72                     if (!success)
73                         error.SetErrorStringWithFormat("Invalid value for end index: %s.\n", option_arg);
74                     break;
75                 case 's':
76                     m_start_idx = Args::StringToUInt32(option_arg, 0, 0, &success);
77                     if (!success)
78                         error.SetErrorStringWithFormat("Invalid value for start index: %s.\n", option_arg);
79                     break;
80                 default:
81                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
82                     break;
83             }
84 
85             return error;
86         }
87 
88         void
89         OptionParsingStarting ()
90         {
91             m_start_idx = 0;
92             m_end_idx = UINT_MAX;
93         }
94 
95         const OptionDefinition*
96         GetDefinitions ()
97         {
98             return g_option_table;
99         }
100 
101         // Options table: Required for subclasses of Options.
102 
103         static OptionDefinition g_option_table[];
104 
105         // Instance variables to hold the values for command options.
106 
107         uint32_t m_start_idx;
108         uint32_t m_end_idx;
109     };
110 
111     CommandOptions m_options;
112 
113     virtual Options *
114     GetOptions ()
115     {
116         return &m_options;
117     }
118 
119 public:
120     CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
121         CommandObject (interpreter,
122                        "command history",
123                        "Dump the history of commands in this session.",
124                        NULL),
125         m_options (interpreter)
126     {
127     }
128 
129     ~CommandObjectCommandsHistory ()
130     {
131     }
132 
133     bool
134     Execute
135     (
136         Args& args,
137         CommandReturnObject &result
138     )
139     {
140 
141         m_interpreter.DumpHistory (result.GetOutputStream(),
142                                    m_options.m_start_idx,
143                                    m_options.m_end_idx);
144         return result.Succeeded();
145 
146     }
147 };
148 
149 OptionDefinition
150 CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
151 {
152 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, eArgTypeUnsignedInteger,        "How many history commands to print."},
153 { LLDB_OPT_SET_1, false, "start-index", 's', required_argument, NULL, 0, eArgTypeUnsignedInteger,  "Index at which to start printing history commands."},
154 { LLDB_OPT_SET_1, false, "end-index", 'e', required_argument, NULL, 0, eArgTypeUnsignedInteger,    "Index at which to stop printing history commands."},
155 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
156 };
157 
158 
159 //-------------------------------------------------------------------------
160 // CommandObjectCommandsSource
161 //-------------------------------------------------------------------------
162 
163 class CommandObjectCommandsSource : public CommandObject
164 {
165 private:
166 
167     class CommandOptions : public Options
168     {
169     public:
170 
171         CommandOptions (CommandInterpreter &interpreter) :
172             Options (interpreter)
173         {
174         }
175 
176         virtual
177         ~CommandOptions (){}
178 
179         virtual Error
180         SetOptionValue (uint32_t option_idx, const char *option_arg)
181         {
182             Error error;
183             char short_option = (char) m_getopt_table[option_idx].val;
184             bool success;
185 
186             switch (short_option)
187             {
188                 case 'e':
189                     m_stop_on_error = Args::StringToBoolean(option_arg, true, &success);
190                     if (!success)
191                         error.SetErrorStringWithFormat("Invalid value for stop-on-error: %s.\n", option_arg);
192                     break;
193                 case 'c':
194                     m_stop_on_continue = Args::StringToBoolean(option_arg, true, &success);
195                     if (!success)
196                         error.SetErrorStringWithFormat("Invalid value for stop-on-continue: %s.\n", option_arg);
197                     break;
198                 default:
199                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
200                     break;
201             }
202 
203             return error;
204         }
205 
206         void
207         OptionParsingStarting ()
208         {
209             m_stop_on_error = true;
210             m_stop_on_continue = true;
211         }
212 
213         const OptionDefinition*
214         GetDefinitions ()
215         {
216             return g_option_table;
217         }
218 
219         // Options table: Required for subclasses of Options.
220 
221         static OptionDefinition g_option_table[];
222 
223         // Instance variables to hold the values for command options.
224 
225         bool m_stop_on_error;
226         bool m_stop_on_continue;
227     };
228 
229     CommandOptions m_options;
230 
231     virtual Options *
232     GetOptions ()
233     {
234         return &m_options;
235     }
236 
237 public:
238     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
239         CommandObject (interpreter,
240                        "command source",
241                        "Read in debugger commands from the file <filename> and execute them.",
242                        NULL),
243         m_options (interpreter)
244     {
245         CommandArgumentEntry arg;
246         CommandArgumentData file_arg;
247 
248         // Define the first (and only) variant of this arg.
249         file_arg.arg_type = eArgTypeFilename;
250         file_arg.arg_repetition = eArgRepeatPlain;
251 
252         // There is only one variant this argument could be; put it into the argument entry.
253         arg.push_back (file_arg);
254 
255         // Push the data for the first argument into the m_arguments vector.
256         m_arguments.push_back (arg);
257     }
258 
259     ~CommandObjectCommandsSource ()
260     {
261     }
262 
263     bool
264     Execute
265     (
266         Args& args,
267         CommandReturnObject &result
268     )
269     {
270         const int argc = args.GetArgumentCount();
271         if (argc == 1)
272         {
273             const char *filename = args.GetArgumentAtIndex(0);
274 
275             result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
276 
277             FileSpec cmd_file (filename, true);
278             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
279             bool echo_commands    = true;
280             bool print_results    = true;
281 
282             m_interpreter.HandleCommandsFromFile (cmd_file,
283                                                   exe_ctx,
284                                                   m_options.m_stop_on_continue,
285                                                   m_options.m_stop_on_error,
286                                                   echo_commands,
287                                                   print_results,
288                                                   result);
289         }
290         else
291         {
292             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
293             result.SetStatus (eReturnStatusFailed);
294         }
295         return result.Succeeded();
296 
297     }
298 };
299 
300 OptionDefinition
301 CommandObjectCommandsSource::CommandOptions::g_option_table[] =
302 {
303 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
304 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', required_argument, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
305 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
306 };
307 
308 #pragma mark CommandObjectCommandsAlias
309 //-------------------------------------------------------------------------
310 // CommandObjectCommandsAlias
311 //-------------------------------------------------------------------------
312 
313 static const char *g_python_command_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
314                                                      "You must define a Python function with this signature:\n"
315                                                      "def my_command_impl(debugger, args, result, dict):";
316 
317 
318 class CommandObjectCommandsAlias : public CommandObject
319 {
320 
321 
322 public:
323     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
324         CommandObject (interpreter,
325                        "command alias",
326                        "Allow users to define their own debugger command abbreviations.",
327                        NULL)
328     {
329         SetHelpLong(
330     "'alias' allows the user to create a short-cut or abbreviation for long \n\
331     commands, multi-word commands, and commands that take particular options. \n\
332     Below are some simple examples of how one might use the 'alias' command: \n\
333     \n    'commands alias sc script'           // Creates the abbreviation 'sc' for the 'script' \n\
334                                          // command. \n\
335     'commands alias bp breakpoint'       // Creates the abbreviation 'bp' for the 'breakpoint' \n\
336                                          // command.  Since breakpoint commands are two-word \n\
337                                          // commands, the user will still need to enter the \n\
338                                          // second word after 'bp', e.g. 'bp enable' or \n\
339                                          // 'bp delete'. \n\
340     'commands alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
341                                          // two-word command 'breakpoint list'. \n\
342     \nAn alias can include some options for the command, with the values either \n\
343     filled in at the time the alias is created, or specified as positional \n\
344     arguments, to be filled in when the alias is invoked.  The following example \n\
345     shows how to create aliases with options: \n\
346     \n\
347     'commands alias bfl breakpoint set -f %1 -l %2' \n\
348     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
349     options already part of the alias.  So if the user wants to set a breakpoint \n\
350     by file and line without explicitly having to use the -f and -l options, the \n\
351     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
352     for the actual arguments that will be passed when the alias command is used. \n\
353     The number in the placeholder refers to the position/order the actual value \n\
354     occupies when the alias is used.  All the occurrences of '%1' in the alias \n\
355     will be replaced with the first argument, all the occurrences of '%2' in the \n\
356     alias will be replaced with the second argument, and so on.  This also allows \n\
357     actual arguments to be used multiple times within an alias (see 'process \n\
358     launch' example below).  \n\
359     Note: the positional arguments must substitute as whole words in the resultant\n\
360     command, so you can't at present do something like:\n\
361     \n\
362     commands alias bcppfl breakpoint set -f %1.cpp -l %2\n\
363     \n\
364     to get the file extension \".cpp\" automatically appended.  For more complex\n\
365     aliasing, use the \"command regex\" command instead.\n\
366     \nSo in the 'bfl' case, the actual file value will be \n\
367     filled in with the first argument following 'bfl' and the actual line number \n\
368     value will be filled in with the second argument.  The user would use this \n\
369     alias as follows: \n\
370     \n    (lldb)  commands alias bfl breakpoint set -f %1 -l %2 \n\
371     <... some time later ...> \n\
372     (lldb)  bfl my-file.c 137 \n\
373     \nThis would be the same as if the user had entered \n\
374     'breakpoint set -f my-file.c -l 137'. \n\
375     \nAnother example: \n\
376     \n    (lldb)  commands alias pltty  process launch -s -o %1 -e %1 \n\
377     (lldb)  pltty /dev/tty0 \n\
378            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
379     \nIf the user always wanted to pass the same value to a particular option, the \n\
380     alias could be defined with that value directly in the alias as a constant, \n\
381     rather than using a positional placeholder: \n\
382     \n    commands alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
383                                                    // 3 of whatever file is indicated. \n");
384 
385         CommandArgumentEntry arg1;
386         CommandArgumentEntry arg2;
387         CommandArgumentEntry arg3;
388         CommandArgumentData alias_arg;
389         CommandArgumentData cmd_arg;
390         CommandArgumentData options_arg;
391 
392         // Define the first (and only) variant of this arg.
393         alias_arg.arg_type = eArgTypeAliasName;
394         alias_arg.arg_repetition = eArgRepeatPlain;
395 
396         // There is only one variant this argument could be; put it into the argument entry.
397         arg1.push_back (alias_arg);
398 
399         // Define the first (and only) variant of this arg.
400         cmd_arg.arg_type = eArgTypeCommandName;
401         cmd_arg.arg_repetition = eArgRepeatPlain;
402 
403         // There is only one variant this argument could be; put it into the argument entry.
404         arg2.push_back (cmd_arg);
405 
406         // Define the first (and only) variant of this arg.
407         options_arg.arg_type = eArgTypeAliasOptions;
408         options_arg.arg_repetition = eArgRepeatOptional;
409 
410         // There is only one variant this argument could be; put it into the argument entry.
411         arg3.push_back (options_arg);
412 
413         // Push the data for the first argument into the m_arguments vector.
414         m_arguments.push_back (arg1);
415         m_arguments.push_back (arg2);
416         m_arguments.push_back (arg3);
417     }
418 
419     ~CommandObjectCommandsAlias ()
420     {
421     }
422 
423     bool
424     WantsRawCommandString ()
425     {
426         return true;
427     }
428 
429     bool
430     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
431     {
432         Args args (raw_command_line);
433         std::string raw_command_string (raw_command_line);
434 
435         size_t argc = args.GetArgumentCount();
436 
437         if (argc < 2)
438         {
439             result.AppendError ("'alias' requires at least two arguments");
440             result.SetStatus (eReturnStatusFailed);
441             return false;
442         }
443 
444         // Get the alias command.
445 
446         const std::string alias_command = args.GetArgumentAtIndex (0);
447 
448         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
449         // does the stripping itself.
450         size_t pos = raw_command_string.find (alias_command);
451         if (pos == 0)
452         {
453             raw_command_string = raw_command_string.substr (alias_command.size());
454             pos = raw_command_string.find_first_not_of (' ');
455             if ((pos != std::string::npos) && (pos > 0))
456                 raw_command_string = raw_command_string.substr (pos);
457         }
458         else
459         {
460             result.AppendError ("Error parsing command string.  No alias created.");
461             result.SetStatus (eReturnStatusFailed);
462             return false;
463         }
464 
465 
466         // Verify that the command is alias-able.
467         if (m_interpreter.CommandExists (alias_command.c_str()))
468         {
469             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
470                                           alias_command.c_str());
471             result.SetStatus (eReturnStatusFailed);
472             return false;
473         }
474 
475         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
476         // raw_command_string is returned with the name of the command object stripped off the front.
477         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
478 
479         if (!cmd_obj)
480         {
481             result.AppendErrorWithFormat ("Invalid command given to 'alias'. '%s' does not begin with a valid command."
482                                           "  No alias created.", raw_command_string.c_str());
483             result.SetStatus (eReturnStatusFailed);
484             return false;
485         }
486         else if (!cmd_obj->WantsRawCommandString ())
487         {
488             // Note that args was initialized with the original command, and has not been updated to this point.
489             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
490             return Execute (args, result);
491         }
492         else
493         {
494             // Verify & handle any options/arguments passed to the alias command
495 
496             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
497             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
498 
499             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
500 
501             if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
502             {
503                 result.AppendError ("Unable to create requested alias.\n");
504                 result.SetStatus (eReturnStatusFailed);
505                 return false;
506             }
507 
508             // Create the alias
509             if (m_interpreter.AliasExists (alias_command.c_str())
510                 || m_interpreter.UserCommandExists (alias_command.c_str()))
511             {
512                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
513                 if (temp_option_arg_sp.get())
514                 {
515                     if (option_arg_vector->size() == 0)
516                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
517                 }
518                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
519                                                 alias_command.c_str());
520             }
521 
522             if (cmd_obj_sp)
523             {
524                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
525                 if (option_arg_vector->size() > 0)
526                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
527                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
528             }
529             else
530             {
531                 result.AppendError ("Unable to create requested alias.\n");
532                 result.SetStatus (eReturnStatusFailed);
533             }
534         }
535         return result.Succeeded();
536     }
537 
538     bool
539     Execute
540     (
541         Args& args,
542         CommandReturnObject &result
543     )
544     {
545         size_t argc = args.GetArgumentCount();
546 
547         if (argc < 2)
548         {
549             result.AppendError ("'alias' requires at least two arguments");
550             result.SetStatus (eReturnStatusFailed);
551             return false;
552         }
553 
554         const std::string alias_command = args.GetArgumentAtIndex(0);
555         const std::string actual_command = args.GetArgumentAtIndex(1);
556 
557         args.Shift();  // Shift the alias command word off the argument vector.
558         args.Shift();  // Shift the old command word off the argument vector.
559 
560         // Verify that the command is alias'able, and get the appropriate command object.
561 
562         if (m_interpreter.CommandExists (alias_command.c_str()))
563         {
564             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
565                                          alias_command.c_str());
566             result.SetStatus (eReturnStatusFailed);
567         }
568         else
569         {
570              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
571              CommandObjectSP subcommand_obj_sp;
572              bool use_subcommand = false;
573              if (command_obj_sp.get())
574              {
575                  CommandObject *cmd_obj = command_obj_sp.get();
576                  CommandObject *sub_cmd_obj = NULL;
577                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
578                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
579 
580                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
581                  {
582                      if (argc >= 3)
583                      {
584                          const std::string sub_command = args.GetArgumentAtIndex(0);
585                          assert (sub_command.length() != 0);
586                          subcommand_obj_sp =
587                                            (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
588                          if (subcommand_obj_sp.get())
589                          {
590                              sub_cmd_obj = subcommand_obj_sp.get();
591                              use_subcommand = true;
592                              args.Shift();  // Shift the sub_command word off the argument vector.
593                              cmd_obj = sub_cmd_obj;
594                          }
595                          else
596                          {
597                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
598                                                           "Unable to create alias.\n",
599                                                           sub_command.c_str(), actual_command.c_str());
600                              result.SetStatus (eReturnStatusFailed);
601                              return false;
602                          }
603                      }
604                  }
605 
606                  // Verify & handle any options/arguments passed to the alias command
607 
608                  if (args.GetArgumentCount () > 0)
609                  {
610                     CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
611                     if (use_subcommand)
612                         tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
613 
614                     std::string args_string;
615                     args.GetCommandString (args_string);
616 
617                     if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
618                     {
619                         result.AppendError ("Unable to create requested alias.\n");
620                         result.SetStatus (eReturnStatusFailed);
621                         return false;
622                     }
623                  }
624 
625                  // Create the alias.
626 
627                  if (m_interpreter.AliasExists (alias_command.c_str())
628                      || m_interpreter.UserCommandExists (alias_command.c_str()))
629                  {
630                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
631                      if (tmp_option_arg_sp.get())
632                      {
633                          if (option_arg_vector->size() == 0)
634                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
635                      }
636                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
637                                                      alias_command.c_str());
638                  }
639 
640                  if (use_subcommand)
641                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
642                  else
643                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
644                  if (option_arg_vector->size() > 0)
645                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
646                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
647              }
648              else
649              {
650                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
651                  result.SetStatus (eReturnStatusFailed);
652                  return false;
653              }
654         }
655 
656         return result.Succeeded();
657     }
658 };
659 
660 #pragma mark CommandObjectCommandsUnalias
661 //-------------------------------------------------------------------------
662 // CommandObjectCommandsUnalias
663 //-------------------------------------------------------------------------
664 
665 class CommandObjectCommandsUnalias : public CommandObject
666 {
667 public:
668     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
669         CommandObject (interpreter,
670                        "command unalias",
671                        "Allow the user to remove/delete a user-defined command abbreviation.",
672                        NULL)
673     {
674         CommandArgumentEntry arg;
675         CommandArgumentData alias_arg;
676 
677         // Define the first (and only) variant of this arg.
678         alias_arg.arg_type = eArgTypeAliasName;
679         alias_arg.arg_repetition = eArgRepeatPlain;
680 
681         // There is only one variant this argument could be; put it into the argument entry.
682         arg.push_back (alias_arg);
683 
684         // Push the data for the first argument into the m_arguments vector.
685         m_arguments.push_back (arg);
686     }
687 
688     ~CommandObjectCommandsUnalias()
689     {
690     }
691 
692 
693     bool
694     Execute
695     (
696         Args& args,
697         CommandReturnObject &result
698     )
699     {
700         CommandObject::CommandMap::iterator pos;
701         CommandObject *cmd_obj;
702 
703         if (args.GetArgumentCount() != 0)
704         {
705             const char *command_name = args.GetArgumentAtIndex(0);
706             cmd_obj = m_interpreter.GetCommandObject(command_name);
707             if (cmd_obj)
708             {
709                 if (m_interpreter.CommandExists (command_name))
710                 {
711                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
712                                                   command_name);
713                     result.SetStatus (eReturnStatusFailed);
714                 }
715                 else
716                 {
717 
718                     if (m_interpreter.RemoveAlias (command_name) == false)
719                     {
720                         if (m_interpreter.AliasExists (command_name))
721                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
722                                                           command_name);
723                         else
724                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
725                         result.SetStatus (eReturnStatusFailed);
726                     }
727                     else
728                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
729                 }
730             }
731             else
732             {
733                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
734                                               "current list of commands.\n",
735                                              command_name);
736                 result.SetStatus (eReturnStatusFailed);
737             }
738         }
739         else
740         {
741             result.AppendError ("must call 'unalias' with a valid alias");
742             result.SetStatus (eReturnStatusFailed);
743         }
744 
745         return result.Succeeded();
746     }
747 };
748 
749 #pragma mark CommandObjectCommandsAddRegex
750 //-------------------------------------------------------------------------
751 // CommandObjectCommandsAddRegex
752 //-------------------------------------------------------------------------
753 
754 class CommandObjectCommandsAddRegex : public CommandObject
755 {
756 public:
757     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
758         CommandObject (interpreter,
759                        "command regex",
760                        "Allow the user to create a regular expression command.",
761                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
762         m_options (interpreter)
763     {
764         SetHelpLong(
765 "This command allows the user to create powerful regular expression commands\n"
766 "with substitutions. The regular expressions and substitutions are specified\n"
767 "using the regular exression substitution format of:\n"
768 "\n"
769 "    s/<regex>/<subst>/\n"
770 "\n"
771 "<regex> is a regular expression that can use parenthesis to capture regular\n"
772 "expression input and substitute the captured matches in the output using %1\n"
773 "for the first match, %2 for the second, and so on.\n"
774 "\n"
775 "The regular expressions can all be specified on the command line if more than\n"
776 "one argument is provided. If just the command name is provided on the command\n"
777 "line, then the regular expressions and substitutions can be entered on separate\n"
778 " lines, followed by an empty line to terminate the command definition.\n"
779 "\n"
780 "EXAMPLES\n"
781 "\n"
782 "The following example with define a regular expression command named 'f' that\n"
783 "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
784 "a number follows 'f':\n"
785 "(lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
786                     );
787     }
788 
789     ~CommandObjectCommandsAddRegex()
790     {
791     }
792 
793 
794     bool
795     Execute (Args& args, CommandReturnObject &result)
796     {
797         const size_t argc = args.GetArgumentCount();
798         if (argc == 0)
799         {
800             result.AppendError ("usage: 'commands regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
801             result.SetStatus (eReturnStatusFailed);
802         }
803         else
804         {
805             Error error;
806             const char *name = args.GetArgumentAtIndex(0);
807             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
808                                                                  name,
809                                                                  m_options.GetHelp (),
810                                                                  m_options.GetSyntax (),
811                                                                  10));
812 
813             if (argc == 1)
814             {
815                 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
816                 if (reader_sp)
817                 {
818                     error =reader_sp->Initialize (CommandObjectCommandsAddRegex::InputReaderCallback,
819                                                   this,                         // baton
820                                                   eInputReaderGranularityLine,  // token size, to pass to callback function
821                                                   NULL,                         // end token
822                                                   "> ",                         // prompt
823                                                   true);                        // echo input
824                     if (error.Success())
825                     {
826                         m_interpreter.GetDebugger().PushInputReader (reader_sp);
827                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
828                         return true;
829                     }
830                 }
831             }
832             else
833             {
834                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
835                 {
836                     llvm::StringRef arg_strref (args.GetArgumentAtIndex(arg_idx));
837                     error = AppendRegexSubstitution (arg_strref);
838                     if (error.Fail())
839                         break;
840                 }
841 
842                 if (error.Success())
843                 {
844                     AddRegexCommandToInterpreter();
845                 }
846             }
847             if (error.Fail())
848             {
849                 result.AppendError (error.AsCString());
850                 result.SetStatus (eReturnStatusFailed);
851             }
852         }
853 
854         return result.Succeeded();
855     }
856 
857     Error
858     AppendRegexSubstitution (const llvm::StringRef &regex_sed)
859     {
860         Error error;
861 
862         if (m_regex_cmd_ap.get() == NULL)
863         {
864             error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
865                                            (int)regex_sed.size(),
866                                            regex_sed.data());
867             return error;
868         }
869 
870         size_t regex_sed_size = regex_sed.size();
871 
872         if (regex_sed_size <= 1)
873         {
874             error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
875                                            (int)regex_sed.size(),
876                                            regex_sed.data());
877             return error;
878         }
879 
880         if (regex_sed[0] != 's')
881         {
882             error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
883                                            (int)regex_sed.size(),
884                                            regex_sed.data());
885             return error;
886         }
887         const size_t first_separator_char_pos = 1;
888         // use the char that follows 's' as the regex separator character
889         // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
890         const char separator_char = regex_sed[first_separator_char_pos];
891         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
892 
893         if (second_separator_char_pos == std::string::npos)
894         {
895             error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s'",
896                                            separator_char,
897                                            (int)(regex_sed.size() - first_separator_char_pos - 1),
898                                            regex_sed.data() + (first_separator_char_pos + 1));
899             return error;
900         }
901 
902         const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
903 
904         if (third_separator_char_pos == std::string::npos)
905         {
906             error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s'",
907                                            separator_char,
908                                            (int)(regex_sed.size() - second_separator_char_pos - 1),
909                                            regex_sed.data() + (second_separator_char_pos + 1));
910             return error;
911         }
912 
913         if (third_separator_char_pos != regex_sed_size - 1)
914         {
915             // Make sure that everything that follows the last regex
916             // separator char
917             if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
918             {
919                 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
920                                                (int)third_separator_char_pos + 1,
921                                                regex_sed.data(),
922                                                (int)(regex_sed.size() - third_separator_char_pos - 1),
923                                                regex_sed.data() + (third_separator_char_pos + 1));
924                 return error;
925             }
926 
927         }
928         else if (first_separator_char_pos + 1 == second_separator_char_pos)
929         {
930             error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
931                                            separator_char,
932                                            separator_char,
933                                            separator_char,
934                                            (int)regex_sed.size(),
935                                            regex_sed.data());
936             return error;
937         }
938         else if (second_separator_char_pos + 1 == third_separator_char_pos)
939         {
940             error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
941                                            separator_char,
942                                            separator_char,
943                                            separator_char,
944                                            (int)regex_sed.size(),
945                                            regex_sed.data());
946             return error;
947         }
948         std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
949         std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
950         m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
951                                          subst.c_str());
952         return error;
953     }
954 
955     void
956     AddRegexCommandToInterpreter()
957     {
958         if (m_regex_cmd_ap.get())
959         {
960             if (m_regex_cmd_ap->HasRegexEntries())
961             {
962                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
963                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
964             }
965         }
966     }
967 
968     void
969     InputReaderDidCancel()
970     {
971         m_regex_cmd_ap.reset();
972     }
973 
974     static size_t
975     InputReaderCallback (void *baton,
976                          InputReader &reader,
977                          lldb::InputReaderAction notification,
978                          const char *bytes,
979                          size_t bytes_len);
980 private:
981     std::auto_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
982 
983      class CommandOptions : public Options
984      {
985      public:
986 
987          CommandOptions (CommandInterpreter &interpreter) :
988             Options (interpreter)
989          {
990          }
991 
992          virtual
993          ~CommandOptions (){}
994 
995          virtual Error
996          SetOptionValue (uint32_t option_idx, const char *option_arg)
997          {
998              Error error;
999              char short_option = (char) m_getopt_table[option_idx].val;
1000 
1001              switch (short_option)
1002              {
1003                  case 'h':
1004                      m_help.assign (option_arg);
1005                      break;
1006                  case 's':
1007                      m_syntax.assign (option_arg);
1008                      break;
1009 
1010                  default:
1011                      error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1012                      break;
1013              }
1014 
1015              return error;
1016          }
1017 
1018          void
1019          OptionParsingStarting ()
1020          {
1021              m_help.clear();
1022              m_syntax.clear();
1023          }
1024 
1025          const OptionDefinition*
1026          GetDefinitions ()
1027          {
1028              return g_option_table;
1029          }
1030 
1031          // Options table: Required for subclasses of Options.
1032 
1033          static OptionDefinition g_option_table[];
1034 
1035          const char *
1036          GetHelp ()
1037          {
1038              if (m_help.empty())
1039                  return NULL;
1040              return m_help.c_str();
1041          }
1042          const char *
1043          GetSyntax ()
1044          {
1045              if (m_syntax.empty())
1046                  return NULL;
1047              return m_syntax.c_str();
1048          }
1049          // Instance variables to hold the values for command options.
1050      protected:
1051          std::string m_help;
1052          std::string m_syntax;
1053      };
1054 
1055      CommandOptions m_options;
1056 
1057      virtual Options *
1058      GetOptions ()
1059      {
1060          return &m_options;
1061      }
1062 
1063 };
1064 
1065 size_t
1066 CommandObjectCommandsAddRegex::InputReaderCallback (void *baton,
1067                                                     InputReader &reader,
1068                                                     lldb::InputReaderAction notification,
1069                                                     const char *bytes,
1070                                                     size_t bytes_len)
1071 {
1072     CommandObjectCommandsAddRegex *add_regex_cmd = (CommandObjectCommandsAddRegex *) baton;
1073     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
1074 
1075     switch (notification)
1076     {
1077         case eInputReaderActivate:
1078             if (!batch_mode)
1079             {
1080                 StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream ();
1081                 out_stream->Printf("%s\n", "Enter regular expressions in the form 's/<regex>/<subst>/' and terminate with an empty line:");
1082                 out_stream->Flush();
1083             }
1084             break;
1085         case eInputReaderReactivate:
1086             break;
1087 
1088         case eInputReaderDeactivate:
1089             break;
1090 
1091         case eInputReaderAsynchronousOutputWritten:
1092             break;
1093 
1094         case eInputReaderGotToken:
1095             while (bytes_len > 0 && (bytes[bytes_len-1] == '\r' || bytes[bytes_len-1] == '\n'))
1096                 --bytes_len;
1097             if (bytes_len == 0)
1098                 reader.SetIsDone(true);
1099             else if (bytes)
1100             {
1101                 llvm::StringRef bytes_strref (bytes, bytes_len);
1102                 Error error (add_regex_cmd->AppendRegexSubstitution (bytes_strref));
1103                 if (error.Fail())
1104                 {
1105                     if (!batch_mode)
1106                     {
1107                         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1108                         out_stream->Printf("error: %s\n", error.AsCString());
1109                         out_stream->Flush();
1110                     }
1111                     add_regex_cmd->InputReaderDidCancel ();
1112                     reader.SetIsDone (true);
1113                 }
1114             }
1115             break;
1116 
1117         case eInputReaderInterrupt:
1118             {
1119                 reader.SetIsDone (true);
1120                 if (!batch_mode)
1121                 {
1122                     StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
1123                     out_stream->PutCString("Regular expression command creations was cancelled.\n");
1124                     out_stream->Flush();
1125                 }
1126                 add_regex_cmd->InputReaderDidCancel ();
1127             }
1128             break;
1129 
1130         case eInputReaderEndOfFile:
1131             reader.SetIsDone (true);
1132             break;
1133 
1134         case eInputReaderDone:
1135             add_regex_cmd->AddRegexCommandToInterpreter();
1136             break;
1137     }
1138 
1139     return bytes_len;
1140 }
1141 
1142 
1143 OptionDefinition
1144 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1145 {
1146 { LLDB_OPT_SET_1, false, "help"  , 'h', required_argument, NULL, 0, eArgTypeNone, "The help text to display for this command."},
1147 { LLDB_OPT_SET_1, false, "syntax", 's', required_argument, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1148 { 0             , false,  NULL   , 0  , 0                , NULL, 0, eArgTypeNone, NULL }
1149 };
1150 
1151 
1152 class CommandObjectPythonFunction : public CommandObject
1153 {
1154 private:
1155     std::string m_function_name;
1156 
1157 public:
1158 
1159     CommandObjectPythonFunction (CommandInterpreter &interpreter,
1160                                  std::string name,
1161                                  std::string funct) :
1162     CommandObject (interpreter,
1163                    name.c_str(),
1164                    (std::string("Run Python function ") + funct).c_str(),
1165                    NULL),
1166     m_function_name(funct)
1167     {
1168         ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1169         if (scripter)
1170         {
1171             std::string docstring = scripter->GetDocumentationForItem(funct.c_str());
1172             if (!docstring.empty())
1173                 SetHelpLong(docstring);
1174         }
1175     }
1176 
1177     virtual
1178     ~CommandObjectPythonFunction ()
1179     {
1180     }
1181 
1182     virtual bool
1183     ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
1184     {
1185         ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1186 
1187         Error error;
1188 
1189         if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(),
1190                                                          raw_command_line,
1191                                                          result,
1192                                                          error) == false)
1193         {
1194             result.AppendError(error.AsCString());
1195             result.SetStatus(eReturnStatusFailed);
1196         }
1197         else
1198             result.SetStatus(eReturnStatusSuccessFinishNoResult);
1199 
1200         return result.Succeeded();
1201     }
1202 
1203     virtual bool
1204     WantsRawCommandString ()
1205     {
1206         return true;
1207     }
1208 
1209     bool
1210     Execute (Args& command,
1211              CommandReturnObject &result)
1212     {
1213         std::string cmd_string;
1214         command.GetCommandString(cmd_string);
1215         return ExecuteRawCommandString(cmd_string.c_str(), result);
1216     }
1217 
1218     virtual bool
1219     IsRemovable() { return true; }
1220 
1221 };
1222 
1223 
1224 //-------------------------------------------------------------------------
1225 // CommandObjectCommandsScriptAdd
1226 //-------------------------------------------------------------------------
1227 
1228 class CommandObjectCommandsScriptAdd : public CommandObject
1229 {
1230 private:
1231 
1232     class CommandOptions : public Options
1233     {
1234     public:
1235 
1236         CommandOptions (CommandInterpreter &interpreter) :
1237         Options (interpreter)
1238         {
1239         }
1240 
1241         virtual
1242         ~CommandOptions (){}
1243 
1244         virtual Error
1245         SetOptionValue (uint32_t option_idx, const char *option_arg)
1246         {
1247             Error error;
1248             char short_option = (char) m_getopt_table[option_idx].val;
1249 
1250             switch (short_option)
1251             {
1252                 case 'f':
1253                     m_funct_name = std::string(option_arg);
1254                     break;
1255                 default:
1256                     error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
1257                     break;
1258             }
1259 
1260             return error;
1261         }
1262 
1263         void
1264         OptionParsingStarting ()
1265         {
1266             m_funct_name = "";
1267         }
1268 
1269         const OptionDefinition*
1270         GetDefinitions ()
1271         {
1272             return g_option_table;
1273         }
1274 
1275         // Options table: Required for subclasses of Options.
1276 
1277         static OptionDefinition g_option_table[];
1278 
1279         // Instance variables to hold the values for command options.
1280 
1281         std::string m_funct_name;
1282     };
1283 
1284     CommandOptions m_options;
1285 
1286     virtual Options *
1287     GetOptions ()
1288     {
1289         return &m_options;
1290     }
1291 
1292     class PythonAliasReader : public InputReaderEZ
1293     {
1294     private:
1295         CommandInterpreter& m_interpreter;
1296         std::string m_cmd_name;
1297         StringList m_user_input;
1298         DISALLOW_COPY_AND_ASSIGN (PythonAliasReader);
1299     public:
1300         PythonAliasReader(Debugger& debugger,
1301                           CommandInterpreter& interpreter,
1302                           std::string cmd_name) :
1303         InputReaderEZ(debugger),
1304         m_interpreter(interpreter),
1305         m_cmd_name(cmd_name),
1306         m_user_input()
1307         {}
1308 
1309         virtual
1310         ~PythonAliasReader()
1311         {
1312         }
1313 
1314         virtual void ActivateHandler(HandlerData& data)
1315         {
1316             StreamSP out_stream = data.GetOutStream();
1317             bool batch_mode = data.GetBatchMode();
1318             if (!batch_mode)
1319             {
1320                 out_stream->Printf ("%s\n", g_python_command_instructions);
1321                 if (data.reader.GetPrompt())
1322                     out_stream->Printf ("%s", data.reader.GetPrompt());
1323                 out_stream->Flush();
1324             }
1325         }
1326 
1327         virtual void ReactivateHandler(HandlerData& data)
1328         {
1329             StreamSP out_stream = data.GetOutStream();
1330             bool batch_mode = data.GetBatchMode();
1331             if (data.reader.GetPrompt() && !batch_mode)
1332             {
1333                 out_stream->Printf ("%s", data.reader.GetPrompt());
1334                 out_stream->Flush();
1335             }
1336         }
1337         virtual void GotTokenHandler(HandlerData& data)
1338         {
1339             StreamSP out_stream = data.GetOutStream();
1340             bool batch_mode = data.GetBatchMode();
1341             if (data.bytes && data.bytes_len)
1342             {
1343                 m_user_input.AppendString(data.bytes, data.bytes_len);
1344             }
1345             if (!data.reader.IsDone() && data.reader.GetPrompt() && !batch_mode)
1346             {
1347                 out_stream->Printf ("%s", data.reader.GetPrompt());
1348                 out_stream->Flush();
1349             }
1350         }
1351         virtual void InterruptHandler(HandlerData& data)
1352         {
1353             StreamSP out_stream = data.GetOutStream();
1354             bool batch_mode = data.GetBatchMode();
1355             data.reader.SetIsDone (true);
1356             if (!batch_mode)
1357             {
1358                 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
1359                 out_stream->Flush();
1360             }
1361         }
1362         virtual void EOFHandler(HandlerData& data)
1363         {
1364             data.reader.SetIsDone (true);
1365         }
1366         virtual void DoneHandler(HandlerData& data)
1367         {
1368             StreamSP out_stream = data.GetOutStream();
1369 
1370             ScriptInterpreter *interpreter = data.reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
1371             if (!interpreter)
1372             {
1373                 out_stream->Printf ("Internal error #1: no script attached.\n");
1374                 out_stream->Flush();
1375                 return;
1376             }
1377             StringList funct_name_sl;
1378             if (!interpreter->GenerateScriptAliasFunction (m_user_input,
1379                                                            funct_name_sl))
1380             {
1381                 out_stream->Printf ("Internal error #2: no script attached.\n");
1382                 out_stream->Flush();
1383                 return;
1384             }
1385             if (funct_name_sl.GetSize() == 0)
1386             {
1387                 out_stream->Printf ("Internal error #3: no script attached.\n");
1388                 out_stream->Flush();
1389                 return;
1390             }
1391             const char *funct_name = funct_name_sl.GetStringAtIndex(0);
1392             if (!funct_name || !funct_name[0])
1393             {
1394                 out_stream->Printf ("Internal error #4: no script attached.\n");
1395                 out_stream->Flush();
1396                 return;
1397             }
1398 
1399             // everything should be fine now, let's add this alias
1400 
1401             CommandObjectSP command_obj_sp(new CommandObjectPythonFunction(m_interpreter,
1402                                                                            m_cmd_name,
1403                                                                            funct_name));
1404 
1405             if (!m_interpreter.AddUserCommand(m_cmd_name.c_str(), command_obj_sp, true))
1406             {
1407                 out_stream->Printf ("Internal error #5: no script attached.\n");
1408                 out_stream->Flush();
1409                 return;
1410             }
1411         }
1412     };
1413 
1414 public:
1415     CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1416     CommandObject (interpreter,
1417                    "command script add",
1418                    "Add a scripted function as an LLDB command.",
1419                    NULL),
1420     m_options (interpreter)
1421     {
1422         CommandArgumentEntry arg1;
1423         CommandArgumentData cmd_arg;
1424 
1425         // Define the first (and only) variant of this arg.
1426         cmd_arg.arg_type = eArgTypeCommandName;
1427         cmd_arg.arg_repetition = eArgRepeatPlain;
1428 
1429         // There is only one variant this argument could be; put it into the argument entry.
1430         arg1.push_back (cmd_arg);
1431 
1432         // Push the data for the first argument into the m_arguments vector.
1433         m_arguments.push_back (arg1);
1434     }
1435 
1436     ~CommandObjectCommandsScriptAdd ()
1437     {
1438     }
1439 
1440     bool
1441     Execute
1442     (
1443      Args& args,
1444      CommandReturnObject &result
1445      )
1446     {
1447 
1448         if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1449         {
1450             result.AppendError ("only scripting language supported for scripted commands is currently Python");
1451             result.SetStatus (eReturnStatusFailed);
1452             return false;
1453         }
1454 
1455         size_t argc = args.GetArgumentCount();
1456 
1457         if (argc != 1)
1458         {
1459             result.AppendError ("'command script add' requires one argument");
1460             result.SetStatus (eReturnStatusFailed);
1461             return false;
1462         }
1463 
1464         std::string cmd_name = args.GetArgumentAtIndex(0);
1465 
1466         if (m_options.m_funct_name.empty())
1467         {
1468             InputReaderSP reader_sp (new PythonAliasReader (m_interpreter.GetDebugger(),
1469                                                             m_interpreter,
1470                                                             cmd_name));
1471 
1472             if (reader_sp)
1473             {
1474 
1475                 InputReaderEZ::InitializationParameters ipr;
1476 
1477                 Error err (reader_sp->Initialize (ipr.SetBaton(NULL).SetPrompt("     ")));
1478                 if (err.Success())
1479                 {
1480                     m_interpreter.GetDebugger().PushInputReader (reader_sp);
1481                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1482                 }
1483                 else
1484                 {
1485                     result.AppendError (err.AsCString());
1486                     result.SetStatus (eReturnStatusFailed);
1487                 }
1488             }
1489             else
1490             {
1491                 result.AppendError("out of memory");
1492                 result.SetStatus (eReturnStatusFailed);
1493             }
1494         }
1495         else
1496         {
1497             CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter, cmd_name, m_options.m_funct_name));
1498             if (m_interpreter.AddUserCommand(cmd_name.c_str(), new_cmd, true))
1499             {
1500                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1501             }
1502             else
1503             {
1504                 result.AppendError("cannot add command");
1505                 result.SetStatus (eReturnStatusFailed);
1506             }
1507         }
1508 
1509         return result.Succeeded();
1510 
1511     }
1512 };
1513 
1514 OptionDefinition
1515 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1516 {
1517     { LLDB_OPT_SET_1, false, "function", 'f', required_argument, NULL, 0, eArgTypePythonFunction,        "Name of the Python function to bind to this command name."},
1518     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1519 };
1520 
1521 //-------------------------------------------------------------------------
1522 // CommandObjectCommandsScriptList
1523 //-------------------------------------------------------------------------
1524 
1525 class CommandObjectCommandsScriptList : public CommandObject
1526 {
1527 private:
1528 
1529 public:
1530     CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1531     CommandObject (interpreter,
1532                    "command script list",
1533                    "List defined scripted commands.",
1534                    NULL)
1535     {
1536     }
1537 
1538     ~CommandObjectCommandsScriptList ()
1539     {
1540     }
1541 
1542     bool
1543     Execute
1544     (
1545      Args& args,
1546      CommandReturnObject &result
1547      )
1548     {
1549 
1550         m_interpreter.GetHelp(result,
1551                               CommandInterpreter::eCommandTypesUserDef);
1552 
1553         result.SetStatus (eReturnStatusSuccessFinishResult);
1554 
1555         return true;
1556 
1557 
1558     }
1559 };
1560 
1561 //-------------------------------------------------------------------------
1562 // CommandObjectCommandsScriptClear
1563 //-------------------------------------------------------------------------
1564 
1565 class CommandObjectCommandsScriptClear : public CommandObject
1566 {
1567 private:
1568 
1569 public:
1570     CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
1571     CommandObject (interpreter,
1572                    "command script clear",
1573                    "Delete all scripted commands.",
1574                    NULL)
1575     {
1576     }
1577 
1578     ~CommandObjectCommandsScriptClear ()
1579     {
1580     }
1581 
1582     bool
1583     Execute
1584     (
1585      Args& args,
1586      CommandReturnObject &result
1587      )
1588     {
1589 
1590         m_interpreter.RemoveAllUser();
1591 
1592         result.SetStatus (eReturnStatusSuccessFinishResult);
1593 
1594         return true;
1595 
1596 
1597     }
1598 };
1599 
1600 //-------------------------------------------------------------------------
1601 // CommandObjectCommandsScriptDelete
1602 //-------------------------------------------------------------------------
1603 
1604 class CommandObjectCommandsScriptDelete : public CommandObject
1605 {
1606 private:
1607 
1608 public:
1609     CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
1610     CommandObject (interpreter,
1611                    "command script delete",
1612                    "Delete a scripted command.",
1613                    NULL)
1614     {
1615         CommandArgumentEntry arg1;
1616         CommandArgumentData cmd_arg;
1617 
1618         // Define the first (and only) variant of this arg.
1619         cmd_arg.arg_type = eArgTypeCommandName;
1620         cmd_arg.arg_repetition = eArgRepeatPlain;
1621 
1622         // There is only one variant this argument could be; put it into the argument entry.
1623         arg1.push_back (cmd_arg);
1624 
1625         // Push the data for the first argument into the m_arguments vector.
1626         m_arguments.push_back (arg1);
1627     }
1628 
1629     ~CommandObjectCommandsScriptDelete ()
1630     {
1631     }
1632 
1633     bool
1634     Execute
1635     (
1636      Args& args,
1637      CommandReturnObject &result
1638      )
1639     {
1640 
1641         size_t argc = args.GetArgumentCount();
1642 
1643         if (argc != 1)
1644         {
1645             result.AppendError ("'command script delete' requires one argument");
1646             result.SetStatus (eReturnStatusFailed);
1647             return false;
1648         }
1649 
1650         const char* cmd_name = args.GetArgumentAtIndex(0);
1651 
1652         if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
1653         {
1654             m_interpreter.RemoveUser(cmd_name);
1655             result.SetStatus (eReturnStatusSuccessFinishResult);
1656         }
1657         else
1658         {
1659             result.AppendErrorWithFormat ("command %s not found", cmd_name);
1660             result.SetStatus (eReturnStatusFailed);
1661         }
1662 
1663         return result.Succeeded();
1664 
1665     }
1666 };
1667 
1668 #pragma mark CommandObjectMultiwordCommandsScript
1669 
1670 //-------------------------------------------------------------------------
1671 // CommandObjectMultiwordCommandsScript
1672 //-------------------------------------------------------------------------
1673 
1674 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
1675 {
1676 public:
1677     CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
1678     CommandObjectMultiword (interpreter,
1679                             "command script",
1680                             "A set of commands for managing or customizing script commands.",
1681                             "command script <subcommand> [<subcommand-options>]")
1682     {
1683         LoadSubCommand ("add",  CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
1684         LoadSubCommand ("delete",   CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
1685         LoadSubCommand ("clear", CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
1686         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
1687     }
1688 
1689     ~CommandObjectMultiwordCommandsScript ()
1690     {
1691     }
1692 
1693 };
1694 
1695 
1696 #pragma mark CommandObjectMultiwordCommands
1697 
1698 //-------------------------------------------------------------------------
1699 // CommandObjectMultiwordCommands
1700 //-------------------------------------------------------------------------
1701 
1702 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
1703     CommandObjectMultiword (interpreter,
1704                             "command",
1705                             "A set of commands for managing or customizing the debugger commands.",
1706                             "command <subcommand> [<subcommand-options>]")
1707 {
1708     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
1709     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
1710     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
1711     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
1712     LoadSubCommand ("history",   CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
1713     LoadSubCommand ("script",   CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
1714 }
1715 
1716 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
1717 {
1718 }
1719 
1720