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