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