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