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/IOHandler.h"
20 #include "lldb/Core/StringList.h"
21 #include "lldb/Interpreter/Args.h"
22 #include "lldb/Interpreter/CommandHistory.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandObjectRegexCommand.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/OptionValueBoolean.h"
27 #include "lldb/Interpreter/OptionValueUInt64.h"
28 #include "lldb/Interpreter/Options.h"
29 #include "lldb/Interpreter/ScriptInterpreter.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 //-------------------------------------------------------------------------
35 // CommandObjectCommandsSource
36 //-------------------------------------------------------------------------
37 
38 class CommandObjectCommandsHistory : public CommandObjectParsed
39 {
40 public:
41     CommandObjectCommandsHistory(CommandInterpreter &interpreter) :
42         CommandObjectParsed (interpreter,
43                              "command history",
44                              "Dump the history of commands in this session.",
45                              NULL),
46         m_options (interpreter)
47     {
48     }
49 
50     ~CommandObjectCommandsHistory () {}
51 
52     virtual Options *
53     GetOptions ()
54     {
55         return &m_options;
56     }
57 
58 protected:
59 
60     class CommandOptions : public Options
61     {
62     public:
63 
64         CommandOptions (CommandInterpreter &interpreter) :
65             Options (interpreter),
66             m_start_idx(0),
67             m_stop_idx(0),
68             m_count(0),
69             m_clear(false)
70         {
71         }
72 
73         virtual
74         ~CommandOptions (){}
75 
76         virtual Error
77         SetOptionValue (uint32_t option_idx, const char *option_arg)
78         {
79             Error error;
80             const int short_option = m_getopt_table[option_idx].val;
81 
82             switch (short_option)
83             {
84                 case 'c':
85                     error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign);
86                     break;
87                 case 's':
88                     if (option_arg && strcmp("end", option_arg) == 0)
89                     {
90                         m_start_idx.SetCurrentValue(UINT64_MAX);
91                         m_start_idx.SetOptionWasSet();
92                     }
93                     else
94                         error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
95                     break;
96                 case 'e':
97                     error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
98                     break;
99                 case 'C':
100                     m_clear.SetCurrentValue(true);
101                     m_clear.SetOptionWasSet();
102                     break;
103                 default:
104                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
105                     break;
106             }
107 
108             return error;
109         }
110 
111         void
112         OptionParsingStarting ()
113         {
114             m_start_idx.Clear();
115             m_stop_idx.Clear();
116             m_count.Clear();
117             m_clear.Clear();
118         }
119 
120         const OptionDefinition*
121         GetDefinitions ()
122         {
123             return g_option_table;
124         }
125 
126         // Options table: Required for subclasses of Options.
127 
128         static OptionDefinition g_option_table[];
129 
130         // Instance variables to hold the values for command options.
131 
132         OptionValueUInt64 m_start_idx;
133         OptionValueUInt64 m_stop_idx;
134         OptionValueUInt64 m_count;
135         OptionValueBoolean m_clear;
136     };
137 
138     bool
139     DoExecute (Args& command, CommandReturnObject &result)
140     {
141         if (m_options.m_clear.GetCurrentValue() && m_options.m_clear.OptionWasSet())
142         {
143             m_interpreter.GetCommandHistory().Clear();
144             result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
145         }
146         else
147         {
148             if (m_options.m_start_idx.OptionWasSet() && m_options.m_stop_idx.OptionWasSet() && m_options.m_count.OptionWasSet())
149             {
150                 result.AppendError("--count, --start-index and --end-index cannot be all specified in the same invocation");
151                 result.SetStatus(lldb::eReturnStatusFailed);
152             }
153             else
154             {
155                 std::pair<bool,uint64_t> start_idx(m_options.m_start_idx.OptionWasSet(),m_options.m_start_idx.GetCurrentValue());
156                 std::pair<bool,uint64_t> stop_idx(m_options.m_stop_idx.OptionWasSet(),m_options.m_stop_idx.GetCurrentValue());
157                 std::pair<bool,uint64_t> count(m_options.m_count.OptionWasSet(),m_options.m_count.GetCurrentValue());
158 
159                 const CommandHistory& history(m_interpreter.GetCommandHistory());
160 
161                 if (start_idx.first && start_idx.second == UINT64_MAX)
162                 {
163                     if (count.first)
164                     {
165                         start_idx.second = history.GetSize() - count.second;
166                         stop_idx.second = history.GetSize() - 1;
167                     }
168                     else if (stop_idx.first)
169                     {
170                         start_idx.second = stop_idx.second;
171                         stop_idx.second = history.GetSize() - 1;
172                     }
173                     else
174                     {
175                         start_idx.second = 0;
176                         stop_idx.second = history.GetSize() - 1;
177                     }
178                 }
179                 else
180                 {
181                     if (!start_idx.first && !stop_idx.first && !count.first)
182                     {
183                         start_idx.second = 0;
184                         stop_idx.second = history.GetSize() - 1;
185                     }
186                     else if (start_idx.first)
187                     {
188                         if (count.first)
189                         {
190                             stop_idx.second = start_idx.second + count.second - 1;
191                         }
192                         else if (!stop_idx.first)
193                         {
194                             stop_idx.second = history.GetSize() - 1;
195                         }
196                     }
197                     else if (stop_idx.first)
198                     {
199                         if (count.first)
200                         {
201                             if (stop_idx.second >= count.second)
202                                 start_idx.second = stop_idx.second - count.second + 1;
203                             else
204                                 start_idx.second = 0;
205                         }
206                     }
207                     else /* if (count.first) */
208                     {
209                         start_idx.second = 0;
210                         stop_idx.second = count.second - 1;
211                     }
212                 }
213                 history.Dump(result.GetOutputStream(), start_idx.second, stop_idx.second);
214             }
215         }
216         return result.Succeeded();
217 
218     }
219 
220     CommandOptions m_options;
221 };
222 
223 OptionDefinition
224 CommandObjectCommandsHistory::CommandOptions::g_option_table[] =
225 {
226 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger,        "How many history commands to print."},
227 { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger,  "Index at which to start printing history commands (or end to mean tail mode)."},
228 { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeUnsignedInteger,    "Index at which to stop printing history commands."},
229 { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeBoolean,    "Clears the current command history."},
230 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
231 };
232 
233 
234 //-------------------------------------------------------------------------
235 // CommandObjectCommandsSource
236 //-------------------------------------------------------------------------
237 
238 class CommandObjectCommandsSource : public CommandObjectParsed
239 {
240 public:
241     CommandObjectCommandsSource(CommandInterpreter &interpreter) :
242         CommandObjectParsed (interpreter,
243                              "command source",
244                              "Read in debugger commands from the file <filename> and execute them.",
245                              NULL),
246         m_options (interpreter)
247     {
248         CommandArgumentEntry arg;
249         CommandArgumentData file_arg;
250 
251         // Define the first (and only) variant of this arg.
252         file_arg.arg_type = eArgTypeFilename;
253         file_arg.arg_repetition = eArgRepeatPlain;
254 
255         // There is only one variant this argument could be; put it into the argument entry.
256         arg.push_back (file_arg);
257 
258         // Push the data for the first argument into the m_arguments vector.
259         m_arguments.push_back (arg);
260     }
261 
262     ~CommandObjectCommandsSource () {}
263 
264     virtual const char*
265     GetRepeatCommand (Args &current_command_args, uint32_t index)
266     {
267         return "";
268     }
269 
270     virtual int
271     HandleArgumentCompletion (Args &input,
272                               int &cursor_index,
273                               int &cursor_char_position,
274                               OptionElementVector &opt_element_vector,
275                               int match_start_point,
276                               int max_return_elements,
277                               bool &word_complete,
278                               StringList &matches)
279     {
280         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
281         completion_str.erase (cursor_char_position);
282 
283         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
284                                                              CommandCompletions::eDiskFileCompletion,
285                                                              completion_str.c_str(),
286                                                              match_start_point,
287                                                              max_return_elements,
288                                                              NULL,
289                                                              word_complete,
290                                                              matches);
291         return matches.GetSize();
292     }
293 
294     virtual Options *
295     GetOptions ()
296     {
297         return &m_options;
298     }
299 
300 protected:
301 
302     class CommandOptions : public Options
303     {
304     public:
305 
306         CommandOptions (CommandInterpreter &interpreter) :
307             Options (interpreter),
308             m_stop_on_error (true),
309             m_silent_run (false),
310             m_stop_on_continue (true)
311         {
312         }
313 
314         virtual
315         ~CommandOptions (){}
316 
317         virtual Error
318         SetOptionValue (uint32_t option_idx, const char *option_arg)
319         {
320             Error error;
321             const int short_option = m_getopt_table[option_idx].val;
322 
323             switch (short_option)
324             {
325                 case 'e':
326                     error = m_stop_on_error.SetValueFromString(option_arg);
327                     break;
328 
329                 case 'c':
330                     error = m_stop_on_continue.SetValueFromString(option_arg);
331                     break;
332 
333                 case 's':
334                     error = m_silent_run.SetValueFromString(option_arg);
335                     break;
336 
337                 default:
338                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
339                     break;
340             }
341 
342             return error;
343         }
344 
345         void
346         OptionParsingStarting ()
347         {
348             m_stop_on_error.Clear();
349             m_silent_run.Clear();
350             m_stop_on_continue.Clear();
351         }
352 
353         const OptionDefinition*
354         GetDefinitions ()
355         {
356             return g_option_table;
357         }
358 
359         // Options table: Required for subclasses of Options.
360 
361         static OptionDefinition g_option_table[];
362 
363         // Instance variables to hold the values for command options.
364 
365         OptionValueBoolean m_stop_on_error;
366         OptionValueBoolean m_silent_run;
367         OptionValueBoolean m_stop_on_continue;
368     };
369 
370     bool
371     DoExecute(Args& command, CommandReturnObject &result)
372     {
373         const size_t argc = command.GetArgumentCount();
374         if (argc == 1)
375         {
376             const char *filename = command.GetArgumentAtIndex(0);
377 
378             FileSpec cmd_file (filename, true);
379             ExecutionContext *exe_ctx = NULL;  // Just use the default context.
380 
381             // If any options were set, then use them
382             if (m_options.m_stop_on_error.OptionWasSet()    ||
383                 m_options.m_silent_run.OptionWasSet()       ||
384                 m_options.m_stop_on_continue.OptionWasSet())
385             {
386                 // Use user set settings
387                 CommandInterpreterRunOptions options;
388                 options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
389                 options.SetStopOnError (m_options.m_stop_on_error.GetCurrentValue());
390                 options.SetEchoCommands (!m_options.m_silent_run.GetCurrentValue());
391                 options.SetPrintResults (!m_options.m_silent_run.GetCurrentValue());
392 
393                 m_interpreter.HandleCommandsFromFile (cmd_file,
394                                                       exe_ctx,
395                                                       options,
396                                                       result);
397 
398             }
399             else
400             {
401                 // No options were set, inherit any settings from nested "command source" commands,
402                 // or set to sane default settings...
403                 CommandInterpreterRunOptions options;
404                 m_interpreter.HandleCommandsFromFile (cmd_file,
405                                                       exe_ctx,
406                                                       options,
407                                                       result);
408 
409             }
410         }
411         else
412         {
413             result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
414             result.SetStatus (eReturnStatusFailed);
415         }
416         return result.Succeeded();
417 
418     }
419     CommandOptions m_options;
420 };
421 
422 OptionDefinition
423 CommandObjectCommandsSource::CommandOptions::g_option_table[] =
424 {
425 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,    "If true, stop executing commands on error."},
426 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true, stop executing commands on continue."},
427 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean, "If true don't echo commands while executing."},
428 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
429 };
430 
431 #pragma mark CommandObjectCommandsAlias
432 //-------------------------------------------------------------------------
433 // CommandObjectCommandsAlias
434 //-------------------------------------------------------------------------
435 
436 static const char *g_python_command_instructions =   "Enter your Python command(s). Type 'DONE' to end.\n"
437                                                      "You must define a Python function with this signature:\n"
438                                                      "def my_command_impl(debugger, args, result, internal_dict):\n";
439 
440 
441 class CommandObjectCommandsAlias : public CommandObjectRaw
442 {
443 
444 
445 public:
446     CommandObjectCommandsAlias (CommandInterpreter &interpreter) :
447         CommandObjectRaw (interpreter,
448                        "command alias",
449                        "Allow users to define their own debugger command abbreviations.",
450                        NULL)
451     {
452         SetHelpLong(
453     "'alias' allows the user to create a short-cut or abbreviation for long \n\
454     commands, multi-word commands, and commands that take particular options. \n\
455     Below are some simple examples of how one might use the 'alias' command: \n\
456     \n    'command alias sc script'            // Creates the abbreviation 'sc' for the 'script' \n\
457                                          // command. \n\
458     'command alias bp breakpoint'        // Creates the abbreviation 'bp' for the 'breakpoint' \n\
459                                          // command.  Since breakpoint commands are two-word \n\
460                                          // commands, the user will still need to enter the \n\
461                                          // second word after 'bp', e.g. 'bp enable' or \n\
462                                          // 'bp delete'. \n\
463     'command alias bpl breakpoint list'  // Creates the abbreviation 'bpl' for the \n\
464                                          // two-word command 'breakpoint list'. \n\
465     \nAn alias can include some options for the command, with the values either \n\
466     filled in at the time the alias is created, or specified as positional \n\
467     arguments, to be filled in when the alias is invoked.  The following example \n\
468     shows how to create aliases with options: \n\
469     \n\
470     'command alias bfl breakpoint set -f %1 -l %2' \n\
471     \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
472     options already part of the alias.  So if the user wants to set a breakpoint \n\
473     by file and line without explicitly having to use the -f and -l options, the \n\
474     user can now use 'bfl' instead.  The '%1' and '%2' are positional placeholders \n\
475     for the actual arguments that will be passed when the alias command is used. \n\
476     The number in the placeholder refers to the position/order the actual value \n\
477     occupies when the alias is used.  All the occurrences of '%1' in the alias \n\
478     will be replaced with the first argument, all the occurrences of '%2' in the \n\
479     alias will be replaced with the second argument, and so on.  This also allows \n\
480     actual arguments to be used multiple times within an alias (see 'process \n\
481     launch' example below).  \n\
482     Note: the positional arguments must substitute as whole words in the resultant\n\
483     command, so you can't at present do something like:\n\
484     \n\
485     command alias bcppfl breakpoint set -f %1.cpp -l %2\n\
486     \n\
487     to get the file extension \".cpp\" automatically appended.  For more complex\n\
488     aliasing, use the \"command regex\" command instead.\n\
489     \nSo in the 'bfl' case, the actual file value will be \n\
490     filled in with the first argument following 'bfl' and the actual line number \n\
491     value will be filled in with the second argument.  The user would use this \n\
492     alias as follows: \n\
493     \n    (lldb)  command alias bfl breakpoint set -f %1 -l %2 \n\
494     <... some time later ...> \n\
495     (lldb)  bfl my-file.c 137 \n\
496     \nThis would be the same as if the user had entered \n\
497     'breakpoint set -f my-file.c -l 137'. \n\
498     \nAnother example: \n\
499     \n    (lldb)  command alias pltty  process launch -s -o %1 -e %1 \n\
500     (lldb)  pltty /dev/tty0 \n\
501            // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
502     \nIf the user always wanted to pass the same value to a particular option, the \n\
503     alias could be defined with that value directly in the alias as a constant, \n\
504     rather than using a positional placeholder: \n\
505     \n    command alias bl3  breakpoint set -f %1 -l 3  // Always sets a breakpoint on line \n\
506                                                    // 3 of whatever file is indicated. \n");
507 
508         CommandArgumentEntry arg1;
509         CommandArgumentEntry arg2;
510         CommandArgumentEntry arg3;
511         CommandArgumentData alias_arg;
512         CommandArgumentData cmd_arg;
513         CommandArgumentData options_arg;
514 
515         // Define the first (and only) variant of this arg.
516         alias_arg.arg_type = eArgTypeAliasName;
517         alias_arg.arg_repetition = eArgRepeatPlain;
518 
519         // There is only one variant this argument could be; put it into the argument entry.
520         arg1.push_back (alias_arg);
521 
522         // Define the first (and only) variant of this arg.
523         cmd_arg.arg_type = eArgTypeCommandName;
524         cmd_arg.arg_repetition = eArgRepeatPlain;
525 
526         // There is only one variant this argument could be; put it into the argument entry.
527         arg2.push_back (cmd_arg);
528 
529         // Define the first (and only) variant of this arg.
530         options_arg.arg_type = eArgTypeAliasOptions;
531         options_arg.arg_repetition = eArgRepeatOptional;
532 
533         // There is only one variant this argument could be; put it into the argument entry.
534         arg3.push_back (options_arg);
535 
536         // Push the data for the first argument into the m_arguments vector.
537         m_arguments.push_back (arg1);
538         m_arguments.push_back (arg2);
539         m_arguments.push_back (arg3);
540     }
541 
542     ~CommandObjectCommandsAlias ()
543     {
544     }
545 
546 protected:
547     virtual bool
548     DoExecute (const char *raw_command_line, CommandReturnObject &result)
549     {
550         Args args (raw_command_line);
551         std::string raw_command_string (raw_command_line);
552 
553         size_t argc = args.GetArgumentCount();
554 
555         if (argc < 2)
556         {
557             result.AppendError ("'alias' requires at least two arguments");
558             result.SetStatus (eReturnStatusFailed);
559             return false;
560         }
561 
562         // Get the alias command.
563 
564         const std::string alias_command = args.GetArgumentAtIndex (0);
565 
566         // Strip the new alias name off 'raw_command_string'  (leave it on args, which gets passed to 'Execute', which
567         // does the stripping itself.
568         size_t pos = raw_command_string.find (alias_command);
569         if (pos == 0)
570         {
571             raw_command_string = raw_command_string.substr (alias_command.size());
572             pos = raw_command_string.find_first_not_of (' ');
573             if ((pos != std::string::npos) && (pos > 0))
574                 raw_command_string = raw_command_string.substr (pos);
575         }
576         else
577         {
578             result.AppendError ("Error parsing command string.  No alias created.");
579             result.SetStatus (eReturnStatusFailed);
580             return false;
581         }
582 
583 
584         // Verify that the command is alias-able.
585         if (m_interpreter.CommandExists (alias_command.c_str()))
586         {
587             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
588                                           alias_command.c_str());
589             result.SetStatus (eReturnStatusFailed);
590             return false;
591         }
592 
593         // Get CommandObject that is being aliased. The command name is read from the front of raw_command_string.
594         // raw_command_string is returned with the name of the command object stripped off the front.
595         CommandObject *cmd_obj = m_interpreter.GetCommandObjectForCommand (raw_command_string);
596 
597         if (!cmd_obj)
598         {
599             result.AppendErrorWithFormat ("invalid command given to 'alias'. '%s' does not begin with a valid command."
600                                           "  No alias created.", raw_command_string.c_str());
601             result.SetStatus (eReturnStatusFailed);
602             return false;
603         }
604         else if (!cmd_obj->WantsRawCommandString ())
605         {
606             // Note that args was initialized with the original command, and has not been updated to this point.
607             // Therefore can we pass it to the version of Execute that does not need/expect raw input in the alias.
608             return HandleAliasingNormalCommand (args, result);
609         }
610         else
611         {
612             return HandleAliasingRawCommand (alias_command, raw_command_string, *cmd_obj, result);
613         }
614         return result.Succeeded();
615     }
616 
617     bool
618     HandleAliasingRawCommand (const std::string &alias_command, std::string &raw_command_string, CommandObject &cmd_obj, CommandReturnObject &result)
619     {
620             // Verify & handle any options/arguments passed to the alias command
621 
622             OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
623             OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
624 
625             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false);
626 
627             if (!m_interpreter.ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
628             {
629                 result.AppendError ("Unable to create requested alias.\n");
630                 result.SetStatus (eReturnStatusFailed);
631                 return false;
632             }
633 
634             // Create the alias
635             if (m_interpreter.AliasExists (alias_command.c_str())
636                 || m_interpreter.UserCommandExists (alias_command.c_str()))
637             {
638                 OptionArgVectorSP temp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
639                 if (temp_option_arg_sp.get())
640                 {
641                     if (option_arg_vector->size() == 0)
642                         m_interpreter.RemoveAliasOptions (alias_command.c_str());
643                 }
644                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
645                                                 alias_command.c_str());
646             }
647 
648             if (cmd_obj_sp)
649             {
650                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp);
651                 if (option_arg_vector->size() > 0)
652                     m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
653                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
654             }
655             else
656             {
657                 result.AppendError ("Unable to create requested alias.\n");
658                 result.SetStatus (eReturnStatusFailed);
659             }
660             return result.Succeeded ();
661     }
662 
663     bool
664     HandleAliasingNormalCommand (Args& args, CommandReturnObject &result)
665     {
666         size_t argc = args.GetArgumentCount();
667 
668         if (argc < 2)
669         {
670             result.AppendError ("'alias' requires at least two arguments");
671             result.SetStatus (eReturnStatusFailed);
672             return false;
673         }
674 
675         const std::string alias_command = args.GetArgumentAtIndex(0);
676         const std::string actual_command = args.GetArgumentAtIndex(1);
677 
678         args.Shift();  // Shift the alias command word off the argument vector.
679         args.Shift();  // Shift the old command word off the argument vector.
680 
681         // Verify that the command is alias'able, and get the appropriate command object.
682 
683         if (m_interpreter.CommandExists (alias_command.c_str()))
684         {
685             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
686                                          alias_command.c_str());
687             result.SetStatus (eReturnStatusFailed);
688         }
689         else
690         {
691              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
692              CommandObjectSP subcommand_obj_sp;
693              bool use_subcommand = false;
694              if (command_obj_sp.get())
695              {
696                  CommandObject *cmd_obj = command_obj_sp.get();
697                  CommandObject *sub_cmd_obj = NULL;
698                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
699                  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
700 
701                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
702                  {
703                      if (argc >= 3)
704                      {
705                          const std::string sub_command = args.GetArgumentAtIndex(0);
706                          assert (sub_command.length() != 0);
707                          subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str());
708                          if (subcommand_obj_sp.get())
709                          {
710                              sub_cmd_obj = subcommand_obj_sp.get();
711                              use_subcommand = true;
712                              args.Shift();  // Shift the sub_command word off the argument vector.
713                              cmd_obj = sub_cmd_obj;
714                          }
715                          else
716                          {
717                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
718                                                           "Unable to create alias.\n",
719                                                           sub_command.c_str(), actual_command.c_str());
720                              result.SetStatus (eReturnStatusFailed);
721                              return false;
722                          }
723                      }
724                  }
725 
726                  // Verify & handle any options/arguments passed to the alias command
727 
728                  if (args.GetArgumentCount () > 0)
729                  {
730                     CommandObjectSP tmp_sp = m_interpreter.GetCommandSPExact (cmd_obj->GetCommandName(), false);
731                     if (use_subcommand)
732                         tmp_sp = m_interpreter.GetCommandSPExact (sub_cmd_obj->GetCommandName(), false);
733 
734                     std::string args_string;
735                     args.GetCommandString (args_string);
736 
737                     if (!m_interpreter.ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
738                     {
739                         result.AppendError ("Unable to create requested alias.\n");
740                         result.SetStatus (eReturnStatusFailed);
741                         return false;
742                     }
743                  }
744 
745                  // Create the alias.
746 
747                  if (m_interpreter.AliasExists (alias_command.c_str())
748                      || m_interpreter.UserCommandExists (alias_command.c_str()))
749                  {
750                      OptionArgVectorSP tmp_option_arg_sp (m_interpreter.GetAliasOptions (alias_command.c_str()));
751                      if (tmp_option_arg_sp.get())
752                      {
753                          if (option_arg_vector->size() == 0)
754                              m_interpreter.RemoveAliasOptions (alias_command.c_str());
755                      }
756                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
757                                                      alias_command.c_str());
758                  }
759 
760                  if (use_subcommand)
761                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp);
762                  else
763                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp);
764                  if (option_arg_vector->size() > 0)
765                      m_interpreter.AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
766                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
767              }
768              else
769              {
770                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
771                  result.SetStatus (eReturnStatusFailed);
772                  return false;
773              }
774         }
775 
776         return result.Succeeded();
777     }
778 
779 };
780 
781 #pragma mark CommandObjectCommandsUnalias
782 //-------------------------------------------------------------------------
783 // CommandObjectCommandsUnalias
784 //-------------------------------------------------------------------------
785 
786 class CommandObjectCommandsUnalias : public CommandObjectParsed
787 {
788 public:
789     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
790         CommandObjectParsed (interpreter,
791                        "command unalias",
792                        "Allow the user to remove/delete a user-defined command abbreviation.",
793                        NULL)
794     {
795         CommandArgumentEntry arg;
796         CommandArgumentData alias_arg;
797 
798         // Define the first (and only) variant of this arg.
799         alias_arg.arg_type = eArgTypeAliasName;
800         alias_arg.arg_repetition = eArgRepeatPlain;
801 
802         // There is only one variant this argument could be; put it into the argument entry.
803         arg.push_back (alias_arg);
804 
805         // Push the data for the first argument into the m_arguments vector.
806         m_arguments.push_back (arg);
807     }
808 
809     ~CommandObjectCommandsUnalias()
810     {
811     }
812 
813 protected:
814     bool
815     DoExecute (Args& args, CommandReturnObject &result)
816     {
817         CommandObject::CommandMap::iterator pos;
818         CommandObject *cmd_obj;
819 
820         if (args.GetArgumentCount() != 0)
821         {
822             const char *command_name = args.GetArgumentAtIndex(0);
823             cmd_obj = m_interpreter.GetCommandObject(command_name);
824             if (cmd_obj)
825             {
826                 if (m_interpreter.CommandExists (command_name))
827                 {
828                     if (cmd_obj->IsRemovable())
829                     {
830                         result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n",
831                                                       command_name);
832                     }
833                     else
834                     {
835                         result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
836                                                       command_name);
837                     }
838                     result.SetStatus (eReturnStatusFailed);
839                 }
840                 else
841                 {
842 
843                     if (m_interpreter.RemoveAlias (command_name) == false)
844                     {
845                         if (m_interpreter.AliasExists (command_name))
846                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
847                                                           command_name);
848                         else
849                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
850                         result.SetStatus (eReturnStatusFailed);
851                     }
852                     else
853                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
854                 }
855             }
856             else
857             {
858                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
859                                               "current list of commands.\n",
860                                              command_name);
861                 result.SetStatus (eReturnStatusFailed);
862             }
863         }
864         else
865         {
866             result.AppendError ("must call 'unalias' with a valid alias");
867             result.SetStatus (eReturnStatusFailed);
868         }
869 
870         return result.Succeeded();
871     }
872 };
873 
874 #pragma mark CommandObjectCommandsDelete
875 //-------------------------------------------------------------------------
876 // CommandObjectCommandsDelete
877 //-------------------------------------------------------------------------
878 
879 class CommandObjectCommandsDelete : public CommandObjectParsed
880 {
881 public:
882     CommandObjectCommandsDelete (CommandInterpreter &interpreter) :
883     CommandObjectParsed (interpreter,
884                          "command delete",
885                          "Allow the user to delete user-defined regular expression, python or multi-word commands.",
886                          NULL)
887     {
888         CommandArgumentEntry arg;
889         CommandArgumentData alias_arg;
890 
891         // Define the first (and only) variant of this arg.
892         alias_arg.arg_type = eArgTypeCommandName;
893         alias_arg.arg_repetition = eArgRepeatPlain;
894 
895         // There is only one variant this argument could be; put it into the argument entry.
896         arg.push_back (alias_arg);
897 
898         // Push the data for the first argument into the m_arguments vector.
899         m_arguments.push_back (arg);
900     }
901 
902     ~CommandObjectCommandsDelete()
903     {
904     }
905 
906 protected:
907     bool
908     DoExecute (Args& args, CommandReturnObject &result)
909     {
910         CommandObject::CommandMap::iterator pos;
911 
912         if (args.GetArgumentCount() != 0)
913         {
914             const char *command_name = args.GetArgumentAtIndex(0);
915             if (m_interpreter.CommandExists (command_name))
916             {
917                 if (m_interpreter.RemoveCommand (command_name))
918                 {
919                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
920                 }
921                 else
922                 {
923                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
924                                                   command_name);
925                     result.SetStatus (eReturnStatusFailed);
926                 }
927             }
928             else
929             {
930                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
931                                               command_name);
932                 result.SetStatus (eReturnStatusFailed);
933             }
934         }
935         else
936         {
937             result.AppendErrorWithFormat ("must call '%s' with one or more valid user defined regular expression, python or multi-word command names", GetCommandName ());
938             result.SetStatus (eReturnStatusFailed);
939         }
940 
941         return result.Succeeded();
942     }
943 };
944 
945 //-------------------------------------------------------------------------
946 // CommandObjectCommandsAddRegex
947 //-------------------------------------------------------------------------
948 #pragma mark CommandObjectCommandsAddRegex
949 
950 class CommandObjectCommandsAddRegex :
951     public CommandObjectParsed,
952     public IOHandlerDelegateMultiline
953 {
954 public:
955     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
956         CommandObjectParsed (interpreter,
957                        "command regex",
958                        "Allow the user to create a regular expression command.",
959                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
960         IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
961         m_options (interpreter)
962     {
963         SetHelpLong(
964 "This command allows the user to create powerful regular expression commands\n"
965 "with substitutions. The regular expressions and substitutions are specified\n"
966 "using the regular expression substitution format of:\n"
967 "\n"
968 "    s/<regex>/<subst>/\n"
969 "\n"
970 "<regex> is a regular expression that can use parenthesis to capture regular\n"
971 "expression input and substitute the captured matches in the output using %1\n"
972 "for the first match, %2 for the second, and so on.\n"
973 "\n"
974 "The regular expressions can all be specified on the command line if more than\n"
975 "one argument is provided. If just the command name is provided on the command\n"
976 "line, then the regular expressions and substitutions can be entered on separate\n"
977 " lines, followed by an empty line to terminate the command definition.\n"
978 "\n"
979 "EXAMPLES\n"
980 "\n"
981 "The following example will define a regular expression command named 'f' that\n"
982 "will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
983 "a number follows 'f':\n"
984 "\n"
985 "    (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
986 "\n"
987                     );
988     }
989 
990     ~CommandObjectCommandsAddRegex()
991     {
992     }
993 
994 
995 protected:
996 
997     void
998     IOHandlerActivated (IOHandler &io_handler) override
999     {
1000         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1001         if (output_sp)
1002         {
1003             output_sp->PutCString("Enter one of more sed substitution commands in the form: 's/<regex>/<subst>/'.\nTerminate the substitution list with an empty line.\n");
1004             output_sp->Flush();
1005         }
1006     }
1007 
1008     void
1009     IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
1010     {
1011         io_handler.SetIsDone(true);
1012         if (m_regex_cmd_ap.get())
1013         {
1014             StringList lines;
1015             if (lines.SplitIntoLines (data))
1016             {
1017                 const size_t num_lines = lines.GetSize();
1018                 bool check_only = false;
1019                 for (size_t i=0; i<num_lines; ++i)
1020                 {
1021                     llvm::StringRef bytes_strref (lines[i]);
1022                     Error error = AppendRegexSubstitution (bytes_strref, check_only);
1023                     if (error.Fail())
1024                     {
1025                         if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
1026                         {
1027                             StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream();
1028                             out_stream->Printf("error: %s\n", error.AsCString());
1029                         }
1030                     }
1031                 }
1032             }
1033             if (m_regex_cmd_ap->HasRegexEntries())
1034             {
1035                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1036                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1037             }
1038         }
1039     }
1040 
1041     bool
1042     DoExecute (Args& command, CommandReturnObject &result) override
1043     {
1044         const size_t argc = command.GetArgumentCount();
1045         if (argc == 0)
1046         {
1047             result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1048             result.SetStatus (eReturnStatusFailed);
1049         }
1050         else
1051         {
1052             Error error;
1053             const char *name = command.GetArgumentAtIndex(0);
1054             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
1055                                                                  name,
1056                                                                  m_options.GetHelp (),
1057                                                                  m_options.GetSyntax (),
1058                                                                  10,
1059                                                                  0,
1060                                                                  true));
1061 
1062             if (argc == 1)
1063             {
1064                 Debugger &debugger = m_interpreter.GetDebugger();
1065                 bool color_prompt = debugger.GetUseColor();
1066                 const bool multiple_lines = true; // Get multiple lines
1067                 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger,
1068                                                                   IOHandler::Type::Other,
1069                                                                   "lldb-regex", // Name of input reader for history
1070                                                                   "> ",         // Prompt
1071                                                                   NULL,         // Continuation prompt
1072                                                                   multiple_lines,
1073                                                                   color_prompt,
1074                                                                   0,            // Don't show line numbers
1075                                                                   *this));
1076 
1077                 if (io_handler_sp)
1078                 {
1079                     debugger.PushIOHandler(io_handler_sp);
1080                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1081                 }
1082             }
1083             else
1084             {
1085                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
1086                 {
1087                     llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
1088                     bool check_only = false;
1089                     error = AppendRegexSubstitution (arg_strref, check_only);
1090                     if (error.Fail())
1091                         break;
1092                 }
1093 
1094                 if (error.Success())
1095                 {
1096                     AddRegexCommandToInterpreter();
1097                 }
1098             }
1099             if (error.Fail())
1100             {
1101                 result.AppendError (error.AsCString());
1102                 result.SetStatus (eReturnStatusFailed);
1103             }
1104         }
1105 
1106         return result.Succeeded();
1107     }
1108 
1109     Error
1110     AppendRegexSubstitution (const llvm::StringRef &regex_sed, bool check_only)
1111     {
1112         Error error;
1113 
1114         if (m_regex_cmd_ap.get() == NULL)
1115         {
1116             error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
1117                                            (int)regex_sed.size(),
1118                                            regex_sed.data());
1119             return error;
1120         }
1121 
1122         size_t regex_sed_size = regex_sed.size();
1123 
1124         if (regex_sed_size <= 1)
1125         {
1126             error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
1127                                            (int)regex_sed.size(),
1128                                            regex_sed.data());
1129             return error;
1130         }
1131 
1132         if (regex_sed[0] != 's')
1133         {
1134             error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
1135                                            (int)regex_sed.size(),
1136                                            regex_sed.data());
1137             return error;
1138         }
1139         const size_t first_separator_char_pos = 1;
1140         // use the char that follows 's' as the regex separator character
1141         // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1142         const char separator_char = regex_sed[first_separator_char_pos];
1143         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
1144 
1145         if (second_separator_char_pos == std::string::npos)
1146         {
1147             error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'",
1148                                            separator_char,
1149                                            (int)(regex_sed.size() - first_separator_char_pos - 1),
1150                                            regex_sed.data() + (first_separator_char_pos + 1),
1151                                            (int)regex_sed.size(),
1152                                            regex_sed.data());
1153             return error;
1154         }
1155 
1156         const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
1157 
1158         if (third_separator_char_pos == std::string::npos)
1159         {
1160             error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'",
1161                                            separator_char,
1162                                            (int)(regex_sed.size() - second_separator_char_pos - 1),
1163                                            regex_sed.data() + (second_separator_char_pos + 1),
1164                                            (int)regex_sed.size(),
1165                                            regex_sed.data());
1166             return error;
1167         }
1168 
1169         if (third_separator_char_pos != regex_sed_size - 1)
1170         {
1171             // Make sure that everything that follows the last regex
1172             // separator char
1173             if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
1174             {
1175                 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
1176                                                (int)third_separator_char_pos + 1,
1177                                                regex_sed.data(),
1178                                                (int)(regex_sed.size() - third_separator_char_pos - 1),
1179                                                regex_sed.data() + (third_separator_char_pos + 1));
1180                 return error;
1181             }
1182 
1183         }
1184         else if (first_separator_char_pos + 1 == second_separator_char_pos)
1185         {
1186             error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1187                                            separator_char,
1188                                            separator_char,
1189                                            separator_char,
1190                                            (int)regex_sed.size(),
1191                                            regex_sed.data());
1192             return error;
1193         }
1194         else if (second_separator_char_pos + 1 == third_separator_char_pos)
1195         {
1196             error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1197                                            separator_char,
1198                                            separator_char,
1199                                            separator_char,
1200                                            (int)regex_sed.size(),
1201                                            regex_sed.data());
1202             return error;
1203         }
1204 
1205         if (check_only == false)
1206         {
1207             std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
1208             std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
1209             m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
1210                                              subst.c_str());
1211         }
1212         return error;
1213     }
1214 
1215     void
1216     AddRegexCommandToInterpreter()
1217     {
1218         if (m_regex_cmd_ap.get())
1219         {
1220             if (m_regex_cmd_ap->HasRegexEntries())
1221             {
1222                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1223                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1224             }
1225         }
1226     }
1227 
1228 private:
1229     std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1230 
1231      class CommandOptions : public Options
1232      {
1233      public:
1234 
1235          CommandOptions (CommandInterpreter &interpreter) :
1236             Options (interpreter)
1237          {
1238          }
1239 
1240          virtual
1241          ~CommandOptions (){}
1242 
1243          virtual Error
1244          SetOptionValue (uint32_t option_idx, const char *option_arg)
1245          {
1246              Error error;
1247              const int short_option = m_getopt_table[option_idx].val;
1248 
1249              switch (short_option)
1250              {
1251                  case 'h':
1252                      m_help.assign (option_arg);
1253                      break;
1254                  case 's':
1255                      m_syntax.assign (option_arg);
1256                      break;
1257 
1258                  default:
1259                      error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1260                      break;
1261              }
1262 
1263              return error;
1264          }
1265 
1266          void
1267          OptionParsingStarting ()
1268          {
1269              m_help.clear();
1270              m_syntax.clear();
1271          }
1272 
1273          const OptionDefinition*
1274          GetDefinitions ()
1275          {
1276              return g_option_table;
1277          }
1278 
1279          // Options table: Required for subclasses of Options.
1280 
1281          static OptionDefinition g_option_table[];
1282 
1283          const char *
1284          GetHelp ()
1285          {
1286              if (m_help.empty())
1287                  return NULL;
1288              return m_help.c_str();
1289          }
1290          const char *
1291          GetSyntax ()
1292          {
1293              if (m_syntax.empty())
1294                  return NULL;
1295              return m_syntax.c_str();
1296          }
1297          // Instance variables to hold the values for command options.
1298      protected:
1299          std::string m_help;
1300          std::string m_syntax;
1301      };
1302 
1303      Options *
1304      GetOptions () override
1305      {
1306          return &m_options;
1307      }
1308 
1309      CommandOptions m_options;
1310 };
1311 
1312 OptionDefinition
1313 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1314 {
1315 { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone, "The help text to display for this command."},
1316 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1317 { 0             , false,  NULL   , 0  , 0                , NULL, NULL, 0, eArgTypeNone, NULL }
1318 };
1319 
1320 
1321 class CommandObjectPythonFunction : public CommandObjectRaw
1322 {
1323 private:
1324     std::string m_function_name;
1325     ScriptedCommandSynchronicity m_synchro;
1326     bool m_fetched_help_long;
1327 
1328 public:
1329 
1330     CommandObjectPythonFunction (CommandInterpreter &interpreter,
1331                                  std::string name,
1332                                  std::string funct,
1333                                  std::string help,
1334                                  ScriptedCommandSynchronicity synch) :
1335         CommandObjectRaw (interpreter,
1336                           name.c_str(),
1337                           NULL,
1338                           NULL),
1339         m_function_name(funct),
1340         m_synchro(synch),
1341         m_fetched_help_long(false)
1342     {
1343         if (!help.empty())
1344             SetHelp(help.c_str());
1345         else
1346         {
1347             StreamString stream;
1348             stream.Printf("For more information run 'help %s'",name.c_str());
1349             SetHelp(stream.GetData());
1350         }
1351     }
1352 
1353     virtual
1354     ~CommandObjectPythonFunction ()
1355     {
1356     }
1357 
1358     virtual bool
1359     IsRemovable () const
1360     {
1361         return true;
1362     }
1363 
1364     const std::string&
1365     GetFunctionName ()
1366     {
1367         return m_function_name;
1368     }
1369 
1370     ScriptedCommandSynchronicity
1371     GetSynchronicity ()
1372     {
1373         return m_synchro;
1374     }
1375 
1376     virtual const char *
1377     GetHelpLong ()
1378     {
1379         if (!m_fetched_help_long)
1380         {
1381             ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1382             if (scripter)
1383             {
1384                 std::string docstring;
1385                 m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring);
1386                 if (!docstring.empty())
1387                     SetHelpLong(docstring);
1388             }
1389         }
1390         return CommandObjectRaw::GetHelpLong();
1391     }
1392 
1393 protected:
1394     virtual bool
1395     DoExecute (const char *raw_command_line, CommandReturnObject &result)
1396     {
1397         ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1398 
1399         Error error;
1400 
1401         result.SetStatus(eReturnStatusInvalid);
1402 
1403         if (!scripter || scripter->RunScriptBasedCommand(m_function_name.c_str(),
1404                                                          raw_command_line,
1405                                                          m_synchro,
1406                                                          result,
1407                                                          error,
1408                                                          m_exe_ctx) == false)
1409         {
1410             result.AppendError(error.AsCString());
1411             result.SetStatus(eReturnStatusFailed);
1412         }
1413         else
1414         {
1415             // Don't change the status if the command already set it...
1416             if (result.GetStatus() == eReturnStatusInvalid)
1417             {
1418                 if (result.GetOutputData() == NULL || result.GetOutputData()[0] == '\0')
1419                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1420                 else
1421                     result.SetStatus(eReturnStatusSuccessFinishResult);
1422             }
1423         }
1424 
1425         return result.Succeeded();
1426     }
1427 
1428 };
1429 
1430 class CommandObjectScriptingObject : public CommandObjectRaw
1431 {
1432 private:
1433     StructuredData::GenericSP m_cmd_obj_sp;
1434     ScriptedCommandSynchronicity m_synchro;
1435     bool m_fetched_help_short:1;
1436     bool m_fetched_help_long:1;
1437 
1438 public:
1439 
1440     CommandObjectScriptingObject (CommandInterpreter &interpreter,
1441                                   std::string name,
1442                                   StructuredData::GenericSP cmd_obj_sp,
1443                                   ScriptedCommandSynchronicity synch) :
1444     CommandObjectRaw (interpreter,
1445                       name.c_str(),
1446                       NULL,
1447                       NULL),
1448     m_cmd_obj_sp(cmd_obj_sp),
1449     m_synchro(synch),
1450     m_fetched_help_short(false),
1451     m_fetched_help_long(false)
1452     {
1453         StreamString stream;
1454         stream.Printf("For more information run 'help %s'",name.c_str());
1455         SetHelp(stream.GetData());
1456         if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter())
1457             GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1458     }
1459 
1460     virtual
1461     ~CommandObjectScriptingObject ()
1462     {
1463     }
1464 
1465     virtual bool
1466     IsRemovable () const
1467     {
1468         return true;
1469     }
1470 
1471     StructuredData::GenericSP
1472     GetImplementingObject ()
1473     {
1474         return m_cmd_obj_sp;
1475     }
1476 
1477     ScriptedCommandSynchronicity
1478     GetSynchronicity ()
1479     {
1480         return m_synchro;
1481     }
1482 
1483     virtual const char *
1484     GetHelp ()
1485     {
1486         if (!m_fetched_help_short)
1487         {
1488             ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1489             if (scripter)
1490             {
1491                 std::string docstring;
1492                 m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring);
1493                 if (!docstring.empty())
1494                     SetHelp(docstring);
1495             }
1496         }
1497         return CommandObjectRaw::GetHelp();
1498     }
1499 
1500     virtual const char *
1501     GetHelpLong ()
1502     {
1503         if (!m_fetched_help_long)
1504         {
1505             ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1506             if (scripter)
1507             {
1508                 std::string docstring;
1509                 m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring);
1510                 if (!docstring.empty())
1511                     SetHelpLong(docstring);
1512             }
1513         }
1514         return CommandObjectRaw::GetHelpLong();
1515     }
1516 
1517 protected:
1518     virtual bool
1519     DoExecute (const char *raw_command_line, CommandReturnObject &result)
1520     {
1521         ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1522 
1523         Error error;
1524 
1525         result.SetStatus(eReturnStatusInvalid);
1526 
1527         if (!scripter || scripter->RunScriptBasedCommand(m_cmd_obj_sp,
1528                                                          raw_command_line,
1529                                                          m_synchro,
1530                                                          result,
1531                                                          error,
1532                                                          m_exe_ctx) == false)
1533         {
1534             result.AppendError(error.AsCString());
1535             result.SetStatus(eReturnStatusFailed);
1536         }
1537         else
1538         {
1539             // Don't change the status if the command already set it...
1540             if (result.GetStatus() == eReturnStatusInvalid)
1541             {
1542                 if (result.GetOutputData() == NULL || result.GetOutputData()[0] == '\0')
1543                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1544                 else
1545                     result.SetStatus(eReturnStatusSuccessFinishResult);
1546             }
1547         }
1548 
1549         return result.Succeeded();
1550     }
1551 
1552 };
1553 
1554 //-------------------------------------------------------------------------
1555 // CommandObjectCommandsScriptImport
1556 //-------------------------------------------------------------------------
1557 
1558 class CommandObjectCommandsScriptImport : public CommandObjectParsed
1559 {
1560 public:
1561     CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
1562         CommandObjectParsed (interpreter,
1563                              "command script import",
1564                              "Import a scripting module in LLDB.",
1565                              NULL),
1566         m_options(interpreter)
1567     {
1568         CommandArgumentEntry arg1;
1569         CommandArgumentData cmd_arg;
1570 
1571         // Define the first (and only) variant of this arg.
1572         cmd_arg.arg_type = eArgTypeFilename;
1573         cmd_arg.arg_repetition = eArgRepeatPlus;
1574 
1575         // There is only one variant this argument could be; put it into the argument entry.
1576         arg1.push_back (cmd_arg);
1577 
1578         // Push the data for the first argument into the m_arguments vector.
1579         m_arguments.push_back (arg1);
1580     }
1581 
1582     ~CommandObjectCommandsScriptImport ()
1583     {
1584     }
1585 
1586     virtual int
1587     HandleArgumentCompletion (Args &input,
1588                               int &cursor_index,
1589                               int &cursor_char_position,
1590                               OptionElementVector &opt_element_vector,
1591                               int match_start_point,
1592                               int max_return_elements,
1593                               bool &word_complete,
1594                               StringList &matches)
1595     {
1596         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1597         completion_str.erase (cursor_char_position);
1598 
1599         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
1600                                                              CommandCompletions::eDiskFileCompletion,
1601                                                              completion_str.c_str(),
1602                                                              match_start_point,
1603                                                              max_return_elements,
1604                                                              NULL,
1605                                                              word_complete,
1606                                                              matches);
1607         return matches.GetSize();
1608     }
1609 
1610     virtual Options *
1611     GetOptions ()
1612     {
1613         return &m_options;
1614     }
1615 
1616 protected:
1617 
1618     class CommandOptions : public Options
1619     {
1620     public:
1621 
1622         CommandOptions (CommandInterpreter &interpreter) :
1623             Options (interpreter)
1624         {
1625         }
1626 
1627         virtual
1628         ~CommandOptions (){}
1629 
1630         virtual Error
1631         SetOptionValue (uint32_t option_idx, const char *option_arg)
1632         {
1633             Error error;
1634             const int short_option = m_getopt_table[option_idx].val;
1635 
1636             switch (short_option)
1637             {
1638                 case 'r':
1639                     m_allow_reload = true;
1640                     break;
1641                 default:
1642                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1643                     break;
1644             }
1645 
1646             return error;
1647         }
1648 
1649         void
1650         OptionParsingStarting ()
1651         {
1652             m_allow_reload = true;
1653         }
1654 
1655         const OptionDefinition*
1656         GetDefinitions ()
1657         {
1658             return g_option_table;
1659         }
1660 
1661         // Options table: Required for subclasses of Options.
1662 
1663         static OptionDefinition g_option_table[];
1664 
1665         // Instance variables to hold the values for command options.
1666 
1667         bool m_allow_reload;
1668     };
1669 
1670     bool
1671     DoExecute (Args& command, CommandReturnObject &result)
1672     {
1673         if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1674         {
1675             result.AppendError ("only scripting language supported for module importing is currently Python");
1676             result.SetStatus (eReturnStatusFailed);
1677             return false;
1678         }
1679 
1680         size_t argc = command.GetArgumentCount();
1681         if (0 == argc)
1682         {
1683             result.AppendError("command script import needs one or more arguments");
1684             result.SetStatus (eReturnStatusFailed);
1685             return false;
1686         }
1687 
1688         for (size_t i = 0;
1689              i < argc;
1690              i++)
1691         {
1692             std::string path = command.GetArgumentAtIndex(i);
1693             Error error;
1694 
1695             const bool init_session = true;
1696             // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
1697             // commands won't ever be recursively invoked, but it's actually possible to craft
1698             // a Python script that does other "command script imports" in __lldb_init_module
1699             // the real fix is to have recursive commands possible with a CommandInvocation object
1700             // separate from the CommandObject itself, so that recursive command invocations
1701             // won't stomp on each other (wrt to execution contents, options, and more)
1702             m_exe_ctx.Clear();
1703             if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
1704                                                                           m_options.m_allow_reload,
1705                                                                           init_session,
1706                                                                           error))
1707             {
1708                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1709             }
1710             else
1711             {
1712                 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
1713                 result.SetStatus (eReturnStatusFailed);
1714             }
1715         }
1716 
1717         return result.Succeeded();
1718     }
1719 
1720     CommandOptions m_options;
1721 };
1722 
1723 OptionDefinition
1724 CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
1725 {
1726     { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,        "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."},
1727     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
1728 };
1729 
1730 
1731 //-------------------------------------------------------------------------
1732 // CommandObjectCommandsScriptAdd
1733 //-------------------------------------------------------------------------
1734 
1735 class CommandObjectCommandsScriptAdd :
1736     public CommandObjectParsed,
1737     public IOHandlerDelegateMultiline
1738 {
1739 public:
1740     CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1741         CommandObjectParsed (interpreter,
1742                              "command script add",
1743                              "Add a scripted function as an LLDB command.",
1744                              NULL),
1745         IOHandlerDelegateMultiline ("DONE"),
1746         m_options (interpreter)
1747     {
1748         CommandArgumentEntry arg1;
1749         CommandArgumentData cmd_arg;
1750 
1751         // Define the first (and only) variant of this arg.
1752         cmd_arg.arg_type = eArgTypeCommandName;
1753         cmd_arg.arg_repetition = eArgRepeatPlain;
1754 
1755         // There is only one variant this argument could be; put it into the argument entry.
1756         arg1.push_back (cmd_arg);
1757 
1758         // Push the data for the first argument into the m_arguments vector.
1759         m_arguments.push_back (arg1);
1760     }
1761 
1762     ~CommandObjectCommandsScriptAdd ()
1763     {
1764     }
1765 
1766     virtual Options *
1767     GetOptions ()
1768     {
1769         return &m_options;
1770     }
1771 
1772 protected:
1773 
1774     class CommandOptions : public Options
1775     {
1776     public:
1777 
1778         CommandOptions (CommandInterpreter &interpreter) :
1779             Options (interpreter),
1780             m_class_name(),
1781             m_funct_name(),
1782             m_short_help(),
1783             m_synchronicity(eScriptedCommandSynchronicitySynchronous)
1784         {
1785         }
1786 
1787         virtual
1788         ~CommandOptions (){}
1789 
1790         virtual Error
1791         SetOptionValue (uint32_t option_idx, const char *option_arg)
1792         {
1793             Error error;
1794             const int short_option = m_getopt_table[option_idx].val;
1795 
1796             switch (short_option)
1797             {
1798                 case 'f':
1799                     if (option_arg)
1800                         m_funct_name.assign(option_arg);
1801                     break;
1802                 case 'c':
1803                     if (option_arg)
1804                         m_class_name.assign(option_arg);
1805                     break;
1806                 case 'h':
1807                     if (option_arg)
1808                         m_short_help.assign(option_arg);
1809                     break;
1810                 case 's':
1811                     m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
1812                     if (!error.Success())
1813                         error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
1814                     break;
1815                 default:
1816                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1817                     break;
1818             }
1819 
1820             return error;
1821         }
1822 
1823         void
1824         OptionParsingStarting ()
1825         {
1826             m_class_name.clear();
1827             m_funct_name.clear();
1828             m_short_help.clear();
1829             m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1830         }
1831 
1832         const OptionDefinition*
1833         GetDefinitions ()
1834         {
1835             return g_option_table;
1836         }
1837 
1838         // Options table: Required for subclasses of Options.
1839 
1840         static OptionDefinition g_option_table[];
1841 
1842         // Instance variables to hold the values for command options.
1843 
1844         std::string m_class_name;
1845         std::string m_funct_name;
1846         std::string m_short_help;
1847         ScriptedCommandSynchronicity m_synchronicity;
1848     };
1849 
1850     virtual void
1851     IOHandlerActivated (IOHandler &io_handler)
1852     {
1853         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1854         if (output_sp)
1855         {
1856             output_sp->PutCString(g_python_command_instructions);
1857             output_sp->Flush();
1858         }
1859     }
1860 
1861 
1862     virtual void
1863     IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
1864     {
1865         StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1866 
1867         ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1868         if (interpreter)
1869         {
1870 
1871             StringList lines;
1872             lines.SplitIntoLines(data);
1873             if (lines.GetSize() > 0)
1874             {
1875                 std::string funct_name_str;
1876                 if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str))
1877                 {
1878                     if (funct_name_str.empty())
1879                     {
1880                         error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n");
1881                         error_sp->Flush();
1882                     }
1883                     else
1884                     {
1885                         // everything should be fine now, let's add this alias
1886 
1887                         CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
1888                                                                                         m_cmd_name,
1889                                                                                         funct_name_str.c_str(),
1890                                                                                         m_short_help,
1891                                                                                         m_synchronicity));
1892 
1893                         if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
1894                         {
1895                             error_sp->Printf ("error: unable to add selected command, didn't add python command.\n");
1896                             error_sp->Flush();
1897                         }
1898                     }
1899                 }
1900                 else
1901                 {
1902                     error_sp->Printf ("error: unable to create function, didn't add python command.\n");
1903                     error_sp->Flush();
1904                 }
1905             }
1906             else
1907             {
1908                 error_sp->Printf ("error: empty function, didn't add python command.\n");
1909                 error_sp->Flush();
1910             }
1911         }
1912         else
1913         {
1914             error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
1915             error_sp->Flush();
1916         }
1917 
1918         io_handler.SetIsDone(true);
1919 
1920 
1921     }
1922 
1923 protected:
1924     bool
1925     DoExecute (Args& command, CommandReturnObject &result)
1926     {
1927 
1928         if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1929         {
1930             result.AppendError ("only scripting language supported for scripted commands is currently Python");
1931             result.SetStatus (eReturnStatusFailed);
1932             return false;
1933         }
1934 
1935         size_t argc = command.GetArgumentCount();
1936 
1937         if (argc != 1)
1938         {
1939             result.AppendError ("'command script add' requires one argument");
1940             result.SetStatus (eReturnStatusFailed);
1941             return false;
1942         }
1943 
1944         // Store the options in case we get multi-line input
1945         m_cmd_name = command.GetArgumentAtIndex(0);
1946         m_short_help.assign(m_options.m_short_help);
1947         m_synchronicity = m_options.m_synchronicity;
1948 
1949         if (m_options.m_class_name.empty())
1950         {
1951             if (m_options.m_funct_name.empty())
1952             {
1953                 m_interpreter.GetPythonCommandsFromIOHandler ("     ",  // Prompt
1954                                                               *this,    // IOHandlerDelegate
1955                                                               true,     // Run IOHandler in async mode
1956                                                               NULL);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
1957             }
1958             else
1959             {
1960                 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
1961                                                                         m_cmd_name,
1962                                                                         m_options.m_funct_name,
1963                                                                         m_options.m_short_help,
1964                                                                         m_synchronicity));
1965                 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
1966                 {
1967                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1968                 }
1969                 else
1970                 {
1971                     result.AppendError("cannot add command");
1972                     result.SetStatus (eReturnStatusFailed);
1973                 }
1974             }
1975         }
1976         else
1977         {
1978             ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter();
1979             if (!interpreter)
1980             {
1981                 result.AppendError("cannot find ScriptInterpreter");
1982                 result.SetStatus(eReturnStatusFailed);
1983                 return false;
1984             }
1985 
1986             auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str());
1987             if (!cmd_obj_sp)
1988             {
1989                 result.AppendError("cannot create helper object");
1990                 result.SetStatus(eReturnStatusFailed);
1991                 return false;
1992             }
1993 
1994             CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter,
1995                                                                      m_cmd_name,
1996                                                                      cmd_obj_sp,
1997                                                                      m_synchronicity));
1998             if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
1999             {
2000                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
2001             }
2002             else
2003             {
2004                 result.AppendError("cannot add command");
2005                 result.SetStatus (eReturnStatusFailed);
2006             }
2007         }
2008 
2009         return result.Succeeded();
2010 
2011     }
2012 
2013     CommandOptions m_options;
2014     std::string m_cmd_name;
2015     std::string m_short_help;
2016     ScriptedCommandSynchronicity m_synchronicity;
2017 };
2018 
2019 static OptionEnumValueElement g_script_synchro_type[] =
2020 {
2021     { eScriptedCommandSynchronicitySynchronous,      "synchronous",       "Run synchronous"},
2022     { eScriptedCommandSynchronicityAsynchronous,     "asynchronous",      "Run asynchronous"},
2023     { eScriptedCommandSynchronicityCurrentValue,     "current",           "Do not alter current setting"},
2024     { 0, NULL, NULL }
2025 };
2026 
2027 OptionDefinition
2028 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
2029 {
2030     { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,        "Name of the Python function to bind to this command name."},
2031     { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass,        "Name of the Python class to bind to this command name."},
2032     { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."},
2033     { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity,        "Set the synchronicity of this command's executions with regard to LLDB event system."},
2034     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2035 };
2036 
2037 //-------------------------------------------------------------------------
2038 // CommandObjectCommandsScriptList
2039 //-------------------------------------------------------------------------
2040 
2041 class CommandObjectCommandsScriptList : public CommandObjectParsed
2042 {
2043 private:
2044 
2045 public:
2046     CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
2047     CommandObjectParsed (interpreter,
2048                    "command script list",
2049                    "List defined scripted commands.",
2050                    NULL)
2051     {
2052     }
2053 
2054     ~CommandObjectCommandsScriptList ()
2055     {
2056     }
2057 
2058     bool
2059     DoExecute (Args& command, CommandReturnObject &result)
2060     {
2061 
2062         m_interpreter.GetHelp(result,
2063                               CommandInterpreter::eCommandTypesUserDef);
2064 
2065         result.SetStatus (eReturnStatusSuccessFinishResult);
2066 
2067         return true;
2068 
2069 
2070     }
2071 };
2072 
2073 //-------------------------------------------------------------------------
2074 // CommandObjectCommandsScriptClear
2075 //-------------------------------------------------------------------------
2076 
2077 class CommandObjectCommandsScriptClear : public CommandObjectParsed
2078 {
2079 private:
2080 
2081 public:
2082     CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
2083         CommandObjectParsed (interpreter,
2084                              "command script clear",
2085                              "Delete all scripted commands.",
2086                              NULL)
2087     {
2088     }
2089 
2090     ~CommandObjectCommandsScriptClear ()
2091     {
2092     }
2093 
2094 protected:
2095     bool
2096     DoExecute (Args& command, CommandReturnObject &result)
2097     {
2098 
2099         m_interpreter.RemoveAllUser();
2100 
2101         result.SetStatus (eReturnStatusSuccessFinishResult);
2102 
2103         return true;
2104     }
2105 };
2106 
2107 //-------------------------------------------------------------------------
2108 // CommandObjectCommandsScriptDelete
2109 //-------------------------------------------------------------------------
2110 
2111 class CommandObjectCommandsScriptDelete : public CommandObjectParsed
2112 {
2113 public:
2114     CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
2115         CommandObjectParsed (interpreter,
2116                              "command script delete",
2117                              "Delete a scripted command.",
2118                              NULL)
2119     {
2120         CommandArgumentEntry arg1;
2121         CommandArgumentData cmd_arg;
2122 
2123         // Define the first (and only) variant of this arg.
2124         cmd_arg.arg_type = eArgTypeCommandName;
2125         cmd_arg.arg_repetition = eArgRepeatPlain;
2126 
2127         // There is only one variant this argument could be; put it into the argument entry.
2128         arg1.push_back (cmd_arg);
2129 
2130         // Push the data for the first argument into the m_arguments vector.
2131         m_arguments.push_back (arg1);
2132     }
2133 
2134     ~CommandObjectCommandsScriptDelete ()
2135     {
2136     }
2137 
2138 protected:
2139     bool
2140     DoExecute (Args& command, CommandReturnObject &result)
2141     {
2142 
2143         size_t argc = command.GetArgumentCount();
2144 
2145         if (argc != 1)
2146         {
2147             result.AppendError ("'command script delete' requires one argument");
2148             result.SetStatus (eReturnStatusFailed);
2149             return false;
2150         }
2151 
2152         const char* cmd_name = command.GetArgumentAtIndex(0);
2153 
2154         if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
2155         {
2156             m_interpreter.RemoveUser(cmd_name);
2157             result.SetStatus (eReturnStatusSuccessFinishResult);
2158         }
2159         else
2160         {
2161             result.AppendErrorWithFormat ("command %s not found", cmd_name);
2162             result.SetStatus (eReturnStatusFailed);
2163         }
2164 
2165         return result.Succeeded();
2166 
2167     }
2168 };
2169 
2170 #pragma mark CommandObjectMultiwordCommandsScript
2171 
2172 //-------------------------------------------------------------------------
2173 // CommandObjectMultiwordCommandsScript
2174 //-------------------------------------------------------------------------
2175 
2176 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
2177 {
2178 public:
2179     CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
2180     CommandObjectMultiword (interpreter,
2181                             "command script",
2182                             "A set of commands for managing or customizing script commands.",
2183                             "command script <subcommand> [<subcommand-options>]")
2184     {
2185         LoadSubCommand ("add",    CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
2186         LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
2187         LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
2188         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
2189         LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
2190     }
2191 
2192     ~CommandObjectMultiwordCommandsScript ()
2193     {
2194     }
2195 
2196 };
2197 
2198 
2199 #pragma mark CommandObjectMultiwordCommands
2200 
2201 //-------------------------------------------------------------------------
2202 // CommandObjectMultiwordCommands
2203 //-------------------------------------------------------------------------
2204 
2205 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
2206     CommandObjectMultiword (interpreter,
2207                             "command",
2208                             "A set of commands for managing or customizing the debugger commands.",
2209                             "command <subcommand> [<subcommand-options>]")
2210 {
2211     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
2212     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
2213     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
2214     LoadSubCommand ("delete",  CommandObjectSP (new CommandObjectCommandsDelete (interpreter)));
2215     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
2216     LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
2217     LoadSubCommand ("script",  CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
2218 }
2219 
2220 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands ()
2221 {
2222 }
2223 
2224