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