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