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