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