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