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