xref: /llvm-project/lldb/source/Commands/CommandObjectCommands.cpp (revision 5e5503099b7ecceb88189444f1491970442db113)
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             CommandObjectSP cmd_obj_sp = m_interpreter.GetCommandSPExact (cmd_obj.GetCommandName(), false);
625 
626             if (!CommandInterpreter::CommandAlias::ProcessAliasOptionsArgs (cmd_obj_sp, raw_command_string.c_str(), option_arg_vector_sp))
627             {
628                 result.AppendError ("Unable to create requested alias.\n");
629                 result.SetStatus (eReturnStatusFailed);
630                 return false;
631             }
632 
633             // Create the alias
634             if (m_interpreter.AliasExists (alias_command.c_str())
635                 || m_interpreter.UserCommandExists (alias_command.c_str()))
636             {
637                 result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
638                                                 alias_command.c_str());
639             }
640 
641             if (cmd_obj_sp)
642             {
643                 m_interpreter.AddAlias (alias_command.c_str(), cmd_obj_sp, option_arg_vector_sp);
644                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
645             }
646             else
647             {
648                 result.AppendError ("Unable to create requested alias.\n");
649                 result.SetStatus (eReturnStatusFailed);
650             }
651             return result.Succeeded ();
652     }
653 
654     bool
655     HandleAliasingNormalCommand (Args& args, CommandReturnObject &result)
656     {
657         size_t argc = args.GetArgumentCount();
658 
659         if (argc < 2)
660         {
661             result.AppendError ("'alias' requires at least two arguments");
662             result.SetStatus (eReturnStatusFailed);
663             return false;
664         }
665 
666         const std::string alias_command = args.GetArgumentAtIndex(0);
667         const std::string actual_command = args.GetArgumentAtIndex(1);
668 
669         args.Shift();  // Shift the alias command word off the argument vector.
670         args.Shift();  // Shift the old command word off the argument vector.
671 
672         // Verify that the command is alias'able, and get the appropriate command object.
673 
674         if (m_interpreter.CommandExists (alias_command.c_str()))
675         {
676             result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
677                                          alias_command.c_str());
678             result.SetStatus (eReturnStatusFailed);
679         }
680         else
681         {
682              CommandObjectSP command_obj_sp(m_interpreter.GetCommandSPExact (actual_command.c_str(), true));
683              CommandObjectSP subcommand_obj_sp;
684              bool use_subcommand = false;
685              if (command_obj_sp)
686              {
687                  CommandObject *cmd_obj = command_obj_sp.get();
688                  CommandObject *sub_cmd_obj = nullptr;
689                  OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
690 
691                  while (cmd_obj->IsMultiwordObject() && args.GetArgumentCount() > 0)
692                  {
693                      if (argc >= 3)
694                      {
695                          const std::string sub_command = args.GetArgumentAtIndex(0);
696                          assert (sub_command.length() != 0);
697                          subcommand_obj_sp = cmd_obj->GetSubcommandSP (sub_command.c_str());
698                          if (subcommand_obj_sp)
699                          {
700                              sub_cmd_obj = subcommand_obj_sp.get();
701                              use_subcommand = true;
702                              args.Shift();  // Shift the sub_command word off the argument vector.
703                              cmd_obj = sub_cmd_obj;
704                          }
705                          else
706                          {
707                              result.AppendErrorWithFormat("'%s' is not a valid sub-command of '%s'.  "
708                                                           "Unable to create alias.\n",
709                                                           sub_command.c_str(), actual_command.c_str());
710                              result.SetStatus (eReturnStatusFailed);
711                              return false;
712                          }
713                      }
714                  }
715 
716                  // Verify & handle any options/arguments passed to the alias command
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                     std::string args_string;
725                     args.GetCommandString (args_string);
726 
727                     if (!CommandInterpreter::CommandAlias::ProcessAliasOptionsArgs (tmp_sp, args_string.c_str(), option_arg_vector_sp))
728                     {
729                         result.AppendError ("Unable to create requested alias.\n");
730                         result.SetStatus (eReturnStatusFailed);
731                         return false;
732                     }
733                  }
734 
735                  // Create the alias.
736 
737                  if (m_interpreter.AliasExists (alias_command.c_str())
738                      || m_interpreter.UserCommandExists (alias_command.c_str()))
739                  {
740                      result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n",
741                                                      alias_command.c_str());
742                  }
743 
744                  if (use_subcommand)
745                      m_interpreter.AddAlias (alias_command.c_str(), subcommand_obj_sp, option_arg_vector_sp);
746                  else
747                      m_interpreter.AddAlias (alias_command.c_str(), command_obj_sp, option_arg_vector_sp);
748                  result.SetStatus (eReturnStatusSuccessFinishNoResult);
749              }
750              else
751              {
752                  result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
753                  result.SetStatus (eReturnStatusFailed);
754                  return false;
755              }
756         }
757 
758         return result.Succeeded();
759     }
760 };
761 
762 #pragma mark CommandObjectCommandsUnalias
763 //-------------------------------------------------------------------------
764 // CommandObjectCommandsUnalias
765 //-------------------------------------------------------------------------
766 
767 class CommandObjectCommandsUnalias : public CommandObjectParsed
768 {
769 public:
770     CommandObjectCommandsUnalias (CommandInterpreter &interpreter) :
771         CommandObjectParsed(interpreter,
772                             "command unalias",
773                             "Allow the user to remove/delete a user-defined command abbreviation.",
774                             nullptr)
775     {
776         CommandArgumentEntry arg;
777         CommandArgumentData alias_arg;
778 
779         // Define the first (and only) variant of this arg.
780         alias_arg.arg_type = eArgTypeAliasName;
781         alias_arg.arg_repetition = eArgRepeatPlain;
782 
783         // There is only one variant this argument could be; put it into the argument entry.
784         arg.push_back (alias_arg);
785 
786         // Push the data for the first argument into the m_arguments vector.
787         m_arguments.push_back (arg);
788     }
789 
790     ~CommandObjectCommandsUnalias() override = default;
791 
792 protected:
793     bool
794     DoExecute (Args& args, CommandReturnObject &result) override
795     {
796         CommandObject::CommandMap::iterator pos;
797         CommandObject *cmd_obj;
798 
799         if (args.GetArgumentCount() != 0)
800         {
801             const char *command_name = args.GetArgumentAtIndex(0);
802             cmd_obj = m_interpreter.GetCommandObject(command_name);
803             if (cmd_obj)
804             {
805                 if (m_interpreter.CommandExists (command_name))
806                 {
807                     if (cmd_obj->IsRemovable())
808                     {
809                         result.AppendErrorWithFormat ("'%s' is not an alias, it is a debugger command which can be removed using the 'command delete' command.\n",
810                                                       command_name);
811                     }
812                     else
813                     {
814                         result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
815                                                       command_name);
816                     }
817                     result.SetStatus (eReturnStatusFailed);
818                 }
819                 else
820                 {
821                     if (!m_interpreter.RemoveAlias(command_name))
822                     {
823                         if (m_interpreter.AliasExists (command_name))
824                             result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n",
825                                                           command_name);
826                         else
827                             result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
828                         result.SetStatus (eReturnStatusFailed);
829                     }
830                     else
831                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
832                 }
833             }
834             else
835             {
836                 result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a "
837                                               "current list of commands.\n",
838                                              command_name);
839                 result.SetStatus (eReturnStatusFailed);
840             }
841         }
842         else
843         {
844             result.AppendError ("must call 'unalias' with a valid alias");
845             result.SetStatus (eReturnStatusFailed);
846         }
847 
848         return result.Succeeded();
849     }
850 };
851 
852 #pragma mark CommandObjectCommandsDelete
853 //-------------------------------------------------------------------------
854 // CommandObjectCommandsDelete
855 //-------------------------------------------------------------------------
856 
857 class CommandObjectCommandsDelete : public CommandObjectParsed
858 {
859 public:
860     CommandObjectCommandsDelete (CommandInterpreter &interpreter) :
861         CommandObjectParsed(interpreter,
862                             "command delete",
863                             "Allow the user to delete user-defined regular expression, python or multi-word commands.",
864                             nullptr)
865     {
866         CommandArgumentEntry arg;
867         CommandArgumentData alias_arg;
868 
869         // Define the first (and only) variant of this arg.
870         alias_arg.arg_type = eArgTypeCommandName;
871         alias_arg.arg_repetition = eArgRepeatPlain;
872 
873         // There is only one variant this argument could be; put it into the argument entry.
874         arg.push_back (alias_arg);
875 
876         // Push the data for the first argument into the m_arguments vector.
877         m_arguments.push_back (arg);
878     }
879 
880     ~CommandObjectCommandsDelete() override = default;
881 
882 protected:
883     bool
884     DoExecute (Args& args, CommandReturnObject &result) override
885     {
886         CommandObject::CommandMap::iterator pos;
887 
888         if (args.GetArgumentCount() != 0)
889         {
890             const char *command_name = args.GetArgumentAtIndex(0);
891             if (m_interpreter.CommandExists (command_name))
892             {
893                 if (m_interpreter.RemoveCommand (command_name))
894                 {
895                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
896                 }
897                 else
898                 {
899                     result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
900                                                   command_name);
901                     result.SetStatus (eReturnStatusFailed);
902                 }
903             }
904             else
905             {
906                 StreamString error_msg_stream;
907                 const bool generate_apropos = true;
908                 const bool generate_type_lookup = false;
909                 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage(&error_msg_stream,
910                                                                         command_name,
911                                                                         nullptr,
912                                                                         nullptr,
913                                                                         generate_apropos,
914                                                                         generate_type_lookup);
915                 result.AppendErrorWithFormat ("%s", error_msg_stream.GetData());
916                 result.SetStatus (eReturnStatusFailed);
917             }
918         }
919         else
920         {
921             result.AppendErrorWithFormat ("must call '%s' with one or more valid user defined regular expression, python or multi-word command names", GetCommandName ());
922             result.SetStatus (eReturnStatusFailed);
923         }
924 
925         return result.Succeeded();
926     }
927 };
928 
929 //-------------------------------------------------------------------------
930 // CommandObjectCommandsAddRegex
931 //-------------------------------------------------------------------------
932 #pragma mark CommandObjectCommandsAddRegex
933 
934 class CommandObjectCommandsAddRegex :
935     public CommandObjectParsed,
936     public IOHandlerDelegateMultiline
937 {
938 public:
939     CommandObjectCommandsAddRegex (CommandInterpreter &interpreter) :
940         CommandObjectParsed (interpreter,
941                        "command regex",
942                        "Allow the user to create a regular expression command.",
943                        "command regex <cmd-name> [s/<regex>/<subst>/ ...]"),
944         IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
945         m_options (interpreter)
946     {
947         SetHelpLong(R"(
948 )" "This command allows the user to create powerful regular expression commands \
949 with substitutions. The regular expressions and substitutions are specified \
950 using the regular expression substitution format of:" R"(
951 
952     s/<regex>/<subst>/
953 
954 )" "<regex> is a regular expression that can use parenthesis to capture regular \
955 expression input and substitute the captured matches in the output using %1 \
956 for the first match, %2 for the second, and so on." R"(
957 
958 )" "The regular expressions can all be specified on the command line if more than \
959 one argument is provided. If just the command name is provided on the command \
960 line, then the regular expressions and substitutions can be entered on separate \
961 lines, followed by an empty line to terminate the command definition." R"(
962 
963 EXAMPLES
964 
965 )" "The following example will define a regular expression command named 'f' that \
966 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
967 a number follows 'f':" R"(
968 
969     (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
970         );
971     }
972 
973     ~CommandObjectCommandsAddRegex() override = default;
974 
975 protected:
976     void
977     IOHandlerActivated (IOHandler &io_handler) override
978     {
979         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
980         if (output_sp)
981         {
982             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");
983             output_sp->Flush();
984         }
985     }
986 
987     void
988     IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
989     {
990         io_handler.SetIsDone(true);
991         if (m_regex_cmd_ap)
992         {
993             StringList lines;
994             if (lines.SplitIntoLines (data))
995             {
996                 const size_t num_lines = lines.GetSize();
997                 bool check_only = false;
998                 for (size_t i=0; i<num_lines; ++i)
999                 {
1000                     llvm::StringRef bytes_strref (lines[i]);
1001                     Error error = AppendRegexSubstitution (bytes_strref, check_only);
1002                     if (error.Fail())
1003                     {
1004                         if (!m_interpreter.GetDebugger().GetCommandInterpreter().GetBatchCommandMode())
1005                         {
1006                             StreamSP out_stream = m_interpreter.GetDebugger().GetAsyncOutputStream();
1007                             out_stream->Printf("error: %s\n", error.AsCString());
1008                         }
1009                     }
1010                 }
1011             }
1012             if (m_regex_cmd_ap->HasRegexEntries())
1013             {
1014                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1015                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1016             }
1017         }
1018     }
1019 
1020     bool
1021     DoExecute (Args& command, CommandReturnObject &result) override
1022     {
1023         const size_t argc = command.GetArgumentCount();
1024         if (argc == 0)
1025         {
1026             result.AppendError ("usage: 'command regex <command-name> [s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n");
1027             result.SetStatus (eReturnStatusFailed);
1028         }
1029         else
1030         {
1031             Error error;
1032             const char *name = command.GetArgumentAtIndex(0);
1033             m_regex_cmd_ap.reset (new CommandObjectRegexCommand (m_interpreter,
1034                                                                  name,
1035                                                                  m_options.GetHelp (),
1036                                                                  m_options.GetSyntax (),
1037                                                                  10,
1038                                                                  0,
1039                                                                  true));
1040 
1041             if (argc == 1)
1042             {
1043                 Debugger &debugger = m_interpreter.GetDebugger();
1044                 bool color_prompt = debugger.GetUseColor();
1045                 const bool multiple_lines = true; // Get multiple lines
1046                 IOHandlerSP io_handler_sp(new IOHandlerEditline(debugger,
1047                                                                 IOHandler::Type::Other,
1048                                                                 "lldb-regex", // Name of input reader for history
1049                                                                 "> ",         // Prompt
1050                                                                 nullptr,      // Continuation prompt
1051                                                                 multiple_lines,
1052                                                                 color_prompt,
1053                                                                 0,            // Don't show line numbers
1054                                                                 *this));
1055 
1056                 if (io_handler_sp)
1057                 {
1058                     debugger.PushIOHandler(io_handler_sp);
1059                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1060                 }
1061             }
1062             else
1063             {
1064                 for (size_t arg_idx = 1; arg_idx < argc; ++arg_idx)
1065                 {
1066                     llvm::StringRef arg_strref (command.GetArgumentAtIndex(arg_idx));
1067                     bool check_only = false;
1068                     error = AppendRegexSubstitution (arg_strref, check_only);
1069                     if (error.Fail())
1070                         break;
1071                 }
1072 
1073                 if (error.Success())
1074                 {
1075                     AddRegexCommandToInterpreter();
1076                 }
1077             }
1078             if (error.Fail())
1079             {
1080                 result.AppendError (error.AsCString());
1081                 result.SetStatus (eReturnStatusFailed);
1082             }
1083         }
1084 
1085         return result.Succeeded();
1086     }
1087 
1088     Error
1089     AppendRegexSubstitution (const llvm::StringRef &regex_sed, bool check_only)
1090     {
1091         Error error;
1092 
1093         if (!m_regex_cmd_ap)
1094         {
1095             error.SetErrorStringWithFormat("invalid regular expression command object for: '%.*s'",
1096                                            (int)regex_sed.size(),
1097                                            regex_sed.data());
1098             return error;
1099         }
1100 
1101         size_t regex_sed_size = regex_sed.size();
1102 
1103         if (regex_sed_size <= 1)
1104         {
1105             error.SetErrorStringWithFormat("regular expression substitution string is too short: '%.*s'",
1106                                            (int)regex_sed.size(),
1107                                            regex_sed.data());
1108             return error;
1109         }
1110 
1111         if (regex_sed[0] != 's')
1112         {
1113             error.SetErrorStringWithFormat("regular expression substitution string doesn't start with 's': '%.*s'",
1114                                            (int)regex_sed.size(),
1115                                            regex_sed.data());
1116             return error;
1117         }
1118         const size_t first_separator_char_pos = 1;
1119         // use the char that follows 's' as the regex separator character
1120         // so we can have "s/<regex>/<subst>/" or "s|<regex>|<subst>|"
1121         const char separator_char = regex_sed[first_separator_char_pos];
1122         const size_t second_separator_char_pos = regex_sed.find (separator_char, first_separator_char_pos + 1);
1123 
1124         if (second_separator_char_pos == std::string::npos)
1125         {
1126             error.SetErrorStringWithFormat("missing second '%c' separator char after '%.*s' in '%.*s'",
1127                                            separator_char,
1128                                            (int)(regex_sed.size() - first_separator_char_pos - 1),
1129                                            regex_sed.data() + (first_separator_char_pos + 1),
1130                                            (int)regex_sed.size(),
1131                                            regex_sed.data());
1132             return error;
1133         }
1134 
1135         const size_t third_separator_char_pos = regex_sed.find (separator_char, second_separator_char_pos + 1);
1136 
1137         if (third_separator_char_pos == std::string::npos)
1138         {
1139             error.SetErrorStringWithFormat("missing third '%c' separator char after '%.*s' in '%.*s'",
1140                                            separator_char,
1141                                            (int)(regex_sed.size() - second_separator_char_pos - 1),
1142                                            regex_sed.data() + (second_separator_char_pos + 1),
1143                                            (int)regex_sed.size(),
1144                                            regex_sed.data());
1145             return error;
1146         }
1147 
1148         if (third_separator_char_pos != regex_sed_size - 1)
1149         {
1150             // Make sure that everything that follows the last regex
1151             // separator char
1152             if (regex_sed.find_first_not_of("\t\n\v\f\r ", third_separator_char_pos + 1) != std::string::npos)
1153             {
1154                 error.SetErrorStringWithFormat("extra data found after the '%.*s' regular expression substitution string: '%.*s'",
1155                                                (int)third_separator_char_pos + 1,
1156                                                regex_sed.data(),
1157                                                (int)(regex_sed.size() - third_separator_char_pos - 1),
1158                                                regex_sed.data() + (third_separator_char_pos + 1));
1159                 return error;
1160             }
1161         }
1162         else if (first_separator_char_pos + 1 == second_separator_char_pos)
1163         {
1164             error.SetErrorStringWithFormat("<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1165                                            separator_char,
1166                                            separator_char,
1167                                            separator_char,
1168                                            (int)regex_sed.size(),
1169                                            regex_sed.data());
1170             return error;
1171         }
1172         else if (second_separator_char_pos + 1 == third_separator_char_pos)
1173         {
1174             error.SetErrorStringWithFormat("<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'",
1175                                            separator_char,
1176                                            separator_char,
1177                                            separator_char,
1178                                            (int)regex_sed.size(),
1179                                            regex_sed.data());
1180             return error;
1181         }
1182 
1183         if (!check_only)
1184         {
1185             std::string regex(regex_sed.substr(first_separator_char_pos + 1, second_separator_char_pos - first_separator_char_pos - 1));
1186             std::string subst(regex_sed.substr(second_separator_char_pos + 1, third_separator_char_pos - second_separator_char_pos - 1));
1187             m_regex_cmd_ap->AddRegexCommand (regex.c_str(),
1188                                              subst.c_str());
1189         }
1190         return error;
1191     }
1192 
1193     void
1194     AddRegexCommandToInterpreter()
1195     {
1196         if (m_regex_cmd_ap)
1197         {
1198             if (m_regex_cmd_ap->HasRegexEntries())
1199             {
1200                 CommandObjectSP cmd_sp (m_regex_cmd_ap.release());
1201                 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true);
1202             }
1203         }
1204     }
1205 
1206 private:
1207     std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_ap;
1208 
1209      class CommandOptions : public Options
1210      {
1211      public:
1212          CommandOptions (CommandInterpreter &interpreter) :
1213             Options (interpreter)
1214          {
1215          }
1216 
1217          ~CommandOptions() override = default;
1218 
1219          Error
1220          SetOptionValue (uint32_t option_idx, const char *option_arg) override
1221          {
1222              Error error;
1223              const int short_option = m_getopt_table[option_idx].val;
1224 
1225              switch (short_option)
1226              {
1227                  case 'h':
1228                      m_help.assign (option_arg);
1229                      break;
1230                  case 's':
1231                      m_syntax.assign (option_arg);
1232                      break;
1233                  default:
1234                      error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1235                      break;
1236              }
1237 
1238              return error;
1239          }
1240 
1241          void
1242          OptionParsingStarting () override
1243          {
1244              m_help.clear();
1245              m_syntax.clear();
1246          }
1247 
1248          const OptionDefinition*
1249          GetDefinitions () override
1250          {
1251              return g_option_table;
1252          }
1253 
1254          // Options table: Required for subclasses of Options.
1255 
1256          static OptionDefinition g_option_table[];
1257 
1258          const char *
1259          GetHelp()
1260          {
1261              return (m_help.empty() ? nullptr : m_help.c_str());
1262          }
1263 
1264          const char *
1265          GetSyntax ()
1266          {
1267              return (m_syntax.empty() ? nullptr : m_syntax.c_str());
1268          }
1269 
1270      protected:
1271          // Instance variables to hold the values for command options.
1272 
1273          std::string m_help;
1274          std::string m_syntax;
1275      };
1276 
1277      Options *
1278      GetOptions () override
1279      {
1280          return &m_options;
1281      }
1282 
1283      CommandOptions m_options;
1284 };
1285 
1286 OptionDefinition
1287 CommandObjectCommandsAddRegex::CommandOptions::g_option_table[] =
1288 {
1289 { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command."},
1290 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax."},
1291 { 0             , false,  nullptr   , 0  , 0                , nullptr, nullptr, 0, eArgTypeNone, nullptr }
1292 };
1293 
1294 class CommandObjectPythonFunction : public CommandObjectRaw
1295 {
1296 public:
1297     CommandObjectPythonFunction (CommandInterpreter &interpreter,
1298                                  std::string name,
1299                                  std::string funct,
1300                                  std::string help,
1301                                  ScriptedCommandSynchronicity synch) :
1302         CommandObjectRaw(interpreter,
1303                          name.c_str(),
1304                          nullptr,
1305                          nullptr),
1306         m_function_name(funct),
1307         m_synchro(synch),
1308         m_fetched_help_long(false)
1309     {
1310         if (!help.empty())
1311             SetHelp(help.c_str());
1312         else
1313         {
1314             StreamString stream;
1315             stream.Printf("For more information run 'help %s'",name.c_str());
1316             SetHelp(stream.GetData());
1317         }
1318     }
1319 
1320     ~CommandObjectPythonFunction() override = default;
1321 
1322     bool
1323     IsRemovable () const override
1324     {
1325         return true;
1326     }
1327 
1328     const std::string&
1329     GetFunctionName ()
1330     {
1331         return m_function_name;
1332     }
1333 
1334     ScriptedCommandSynchronicity
1335     GetSynchronicity ()
1336     {
1337         return m_synchro;
1338     }
1339 
1340     const char *
1341     GetHelpLong () override
1342     {
1343         if (!m_fetched_help_long)
1344         {
1345             ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1346             if (scripter)
1347             {
1348                 std::string docstring;
1349                 m_fetched_help_long = scripter->GetDocumentationForItem(m_function_name.c_str(),docstring);
1350                 if (!docstring.empty())
1351                     SetHelpLong(docstring);
1352             }
1353         }
1354         return CommandObjectRaw::GetHelpLong();
1355     }
1356 
1357 protected:
1358     bool
1359     DoExecute (const char *raw_command_line, CommandReturnObject &result) override
1360     {
1361         ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1362 
1363         Error error;
1364 
1365         result.SetStatus(eReturnStatusInvalid);
1366 
1367         if (!scripter || !scripter->RunScriptBasedCommand(m_function_name.c_str(),
1368                                                           raw_command_line,
1369                                                           m_synchro,
1370                                                           result,
1371                                                           error,
1372                                                           m_exe_ctx))
1373         {
1374             result.AppendError(error.AsCString());
1375             result.SetStatus(eReturnStatusFailed);
1376         }
1377         else
1378         {
1379             // Don't change the status if the command already set it...
1380             if (result.GetStatus() == eReturnStatusInvalid)
1381             {
1382                 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0')
1383                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1384                 else
1385                     result.SetStatus(eReturnStatusSuccessFinishResult);
1386             }
1387         }
1388 
1389         return result.Succeeded();
1390     }
1391 
1392 private:
1393     std::string m_function_name;
1394     ScriptedCommandSynchronicity m_synchro;
1395     bool m_fetched_help_long;
1396 };
1397 
1398 class CommandObjectScriptingObject : public CommandObjectRaw
1399 {
1400 public:
1401     CommandObjectScriptingObject (CommandInterpreter &interpreter,
1402                                   std::string name,
1403                                   StructuredData::GenericSP cmd_obj_sp,
1404                                   ScriptedCommandSynchronicity synch) :
1405         CommandObjectRaw(interpreter,
1406                          name.c_str(),
1407                          nullptr,
1408                          nullptr),
1409         m_cmd_obj_sp(cmd_obj_sp),
1410         m_synchro(synch),
1411         m_fetched_help_short(false),
1412         m_fetched_help_long(false)
1413     {
1414         StreamString stream;
1415         stream.Printf("For more information run 'help %s'",name.c_str());
1416         SetHelp(stream.GetData());
1417         if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter())
1418             GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
1419     }
1420 
1421     ~CommandObjectScriptingObject() override = default;
1422 
1423     bool
1424     IsRemovable () const override
1425     {
1426         return true;
1427     }
1428 
1429     StructuredData::GenericSP
1430     GetImplementingObject ()
1431     {
1432         return m_cmd_obj_sp;
1433     }
1434 
1435     ScriptedCommandSynchronicity
1436     GetSynchronicity ()
1437     {
1438         return m_synchro;
1439     }
1440 
1441     const char *
1442     GetHelp () override
1443     {
1444         if (!m_fetched_help_short)
1445         {
1446             ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1447             if (scripter)
1448             {
1449                 std::string docstring;
1450                 m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring);
1451                 if (!docstring.empty())
1452                     SetHelp(docstring);
1453             }
1454         }
1455         return CommandObjectRaw::GetHelp();
1456     }
1457 
1458     const char *
1459     GetHelpLong () override
1460     {
1461         if (!m_fetched_help_long)
1462         {
1463             ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1464             if (scripter)
1465             {
1466                 std::string docstring;
1467                 m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring);
1468                 if (!docstring.empty())
1469                     SetHelpLong(docstring);
1470             }
1471         }
1472         return CommandObjectRaw::GetHelpLong();
1473     }
1474 
1475 protected:
1476     bool
1477     DoExecute (const char *raw_command_line, CommandReturnObject &result) override
1478     {
1479         ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
1480 
1481         Error error;
1482 
1483         result.SetStatus(eReturnStatusInvalid);
1484 
1485         if (!scripter || !scripter->RunScriptBasedCommand(m_cmd_obj_sp,
1486                                                           raw_command_line,
1487                                                           m_synchro,
1488                                                           result,
1489                                                           error,
1490                                                           m_exe_ctx))
1491         {
1492             result.AppendError(error.AsCString());
1493             result.SetStatus(eReturnStatusFailed);
1494         }
1495         else
1496         {
1497             // Don't change the status if the command already set it...
1498             if (result.GetStatus() == eReturnStatusInvalid)
1499             {
1500                 if (result.GetOutputData() == nullptr || result.GetOutputData()[0] == '\0')
1501                     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1502                 else
1503                     result.SetStatus(eReturnStatusSuccessFinishResult);
1504             }
1505         }
1506 
1507         return result.Succeeded();
1508     }
1509 
1510 private:
1511     StructuredData::GenericSP m_cmd_obj_sp;
1512     ScriptedCommandSynchronicity m_synchro;
1513     bool m_fetched_help_short: 1;
1514     bool m_fetched_help_long: 1;
1515 };
1516 
1517 //-------------------------------------------------------------------------
1518 // CommandObjectCommandsScriptImport
1519 //-------------------------------------------------------------------------
1520 
1521 class CommandObjectCommandsScriptImport : public CommandObjectParsed
1522 {
1523 public:
1524     CommandObjectCommandsScriptImport (CommandInterpreter &interpreter) :
1525         CommandObjectParsed(interpreter,
1526                             "command script import",
1527                             "Import a scripting module in LLDB.",
1528                             nullptr),
1529         m_options(interpreter)
1530     {
1531         CommandArgumentEntry arg1;
1532         CommandArgumentData cmd_arg;
1533 
1534         // Define the first (and only) variant of this arg.
1535         cmd_arg.arg_type = eArgTypeFilename;
1536         cmd_arg.arg_repetition = eArgRepeatPlus;
1537 
1538         // There is only one variant this argument could be; put it into the argument entry.
1539         arg1.push_back (cmd_arg);
1540 
1541         // Push the data for the first argument into the m_arguments vector.
1542         m_arguments.push_back (arg1);
1543     }
1544 
1545     ~CommandObjectCommandsScriptImport() override = default;
1546 
1547     int
1548     HandleArgumentCompletion (Args &input,
1549                               int &cursor_index,
1550                               int &cursor_char_position,
1551                               OptionElementVector &opt_element_vector,
1552                               int match_start_point,
1553                               int max_return_elements,
1554                               bool &word_complete,
1555                               StringList &matches) override
1556     {
1557         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
1558         completion_str.erase (cursor_char_position);
1559 
1560         CommandCompletions::InvokeCommonCompletionCallbacks(m_interpreter,
1561                                                             CommandCompletions::eDiskFileCompletion,
1562                                                             completion_str.c_str(),
1563                                                             match_start_point,
1564                                                             max_return_elements,
1565                                                             nullptr,
1566                                                             word_complete,
1567                                                             matches);
1568         return matches.GetSize();
1569     }
1570 
1571     Options *
1572     GetOptions () override
1573     {
1574         return &m_options;
1575     }
1576 
1577 protected:
1578     class CommandOptions : public Options
1579     {
1580     public:
1581         CommandOptions (CommandInterpreter &interpreter) :
1582             Options (interpreter)
1583         {
1584         }
1585 
1586         ~CommandOptions() override = default;
1587 
1588         Error
1589         SetOptionValue (uint32_t option_idx, const char *option_arg) override
1590         {
1591             Error error;
1592             const int short_option = m_getopt_table[option_idx].val;
1593 
1594             switch (short_option)
1595             {
1596                 case 'r':
1597                     m_allow_reload = true;
1598                     break;
1599                 default:
1600                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1601                     break;
1602             }
1603 
1604             return error;
1605         }
1606 
1607         void
1608         OptionParsingStarting () override
1609         {
1610             m_allow_reload = true;
1611         }
1612 
1613         const OptionDefinition*
1614         GetDefinitions () override
1615         {
1616             return g_option_table;
1617         }
1618 
1619         // Options table: Required for subclasses of Options.
1620 
1621         static OptionDefinition g_option_table[];
1622 
1623         // Instance variables to hold the values for command options.
1624 
1625         bool m_allow_reload;
1626     };
1627 
1628     bool
1629     DoExecute (Args& command, CommandReturnObject &result) override
1630     {
1631         if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1632         {
1633             result.AppendError ("only scripting language supported for module importing is currently Python");
1634             result.SetStatus (eReturnStatusFailed);
1635             return false;
1636         }
1637 
1638         size_t argc = command.GetArgumentCount();
1639         if (0 == argc)
1640         {
1641             result.AppendError("command script import needs one or more arguments");
1642             result.SetStatus (eReturnStatusFailed);
1643             return false;
1644         }
1645 
1646         for (size_t i = 0;
1647              i < argc;
1648              i++)
1649         {
1650             std::string path = command.GetArgumentAtIndex(i);
1651             Error error;
1652 
1653             const bool init_session = true;
1654             // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
1655             // commands won't ever be recursively invoked, but it's actually possible to craft
1656             // a Python script that does other "command script imports" in __lldb_init_module
1657             // the real fix is to have recursive commands possible with a CommandInvocation object
1658             // separate from the CommandObject itself, so that recursive command invocations
1659             // won't stomp on each other (wrt to execution contents, options, and more)
1660             m_exe_ctx.Clear();
1661             if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
1662                                                                           m_options.m_allow_reload,
1663                                                                           init_session,
1664                                                                           error))
1665             {
1666                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1667             }
1668             else
1669             {
1670                 result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
1671                 result.SetStatus (eReturnStatusFailed);
1672             }
1673         }
1674 
1675         return result.Succeeded();
1676     }
1677 
1678     CommandOptions m_options;
1679 };
1680 
1681 OptionDefinition
1682 CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
1683 {
1684     { 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."},
1685     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
1686 };
1687 
1688 //-------------------------------------------------------------------------
1689 // CommandObjectCommandsScriptAdd
1690 //-------------------------------------------------------------------------
1691 
1692 class CommandObjectCommandsScriptAdd :
1693     public CommandObjectParsed,
1694     public IOHandlerDelegateMultiline
1695 {
1696 public:
1697     CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) :
1698         CommandObjectParsed(interpreter,
1699                             "command script add",
1700                             "Add a scripted function as an LLDB command.",
1701                             nullptr),
1702         IOHandlerDelegateMultiline ("DONE"),
1703         m_options (interpreter)
1704     {
1705         CommandArgumentEntry arg1;
1706         CommandArgumentData cmd_arg;
1707 
1708         // Define the first (and only) variant of this arg.
1709         cmd_arg.arg_type = eArgTypeCommandName;
1710         cmd_arg.arg_repetition = eArgRepeatPlain;
1711 
1712         // There is only one variant this argument could be; put it into the argument entry.
1713         arg1.push_back (cmd_arg);
1714 
1715         // Push the data for the first argument into the m_arguments vector.
1716         m_arguments.push_back (arg1);
1717     }
1718 
1719     ~CommandObjectCommandsScriptAdd() override = default;
1720 
1721     Options *
1722     GetOptions () override
1723     {
1724         return &m_options;
1725     }
1726 
1727 protected:
1728     class CommandOptions : public Options
1729     {
1730     public:
1731         CommandOptions (CommandInterpreter &interpreter) :
1732             Options (interpreter),
1733             m_class_name(),
1734             m_funct_name(),
1735             m_short_help(),
1736             m_synchronicity(eScriptedCommandSynchronicitySynchronous)
1737         {
1738         }
1739 
1740         ~CommandOptions() override = default;
1741 
1742         Error
1743         SetOptionValue (uint32_t option_idx, const char *option_arg) override
1744         {
1745             Error error;
1746             const int short_option = m_getopt_table[option_idx].val;
1747 
1748             switch (short_option)
1749             {
1750                 case 'f':
1751                     if (option_arg)
1752                         m_funct_name.assign(option_arg);
1753                     break;
1754                 case 'c':
1755                     if (option_arg)
1756                         m_class_name.assign(option_arg);
1757                     break;
1758                 case 'h':
1759                     if (option_arg)
1760                         m_short_help.assign(option_arg);
1761                     break;
1762                 case 's':
1763                     m_synchronicity = (ScriptedCommandSynchronicity) Args::StringToOptionEnum(option_arg, g_option_table[option_idx].enum_values, 0, error);
1764                     if (!error.Success())
1765                         error.SetErrorStringWithFormat ("unrecognized value for synchronicity '%s'", option_arg);
1766                     break;
1767                 default:
1768                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1769                     break;
1770             }
1771 
1772             return error;
1773         }
1774 
1775         void
1776         OptionParsingStarting () override
1777         {
1778             m_class_name.clear();
1779             m_funct_name.clear();
1780             m_short_help.clear();
1781             m_synchronicity = eScriptedCommandSynchronicitySynchronous;
1782         }
1783 
1784         const OptionDefinition*
1785         GetDefinitions () override
1786         {
1787             return g_option_table;
1788         }
1789 
1790         // Options table: Required for subclasses of Options.
1791 
1792         static OptionDefinition g_option_table[];
1793 
1794         // Instance variables to hold the values for command options.
1795 
1796         std::string m_class_name;
1797         std::string m_funct_name;
1798         std::string m_short_help;
1799         ScriptedCommandSynchronicity m_synchronicity;
1800     };
1801 
1802     void
1803     IOHandlerActivated (IOHandler &io_handler) override
1804     {
1805         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
1806         if (output_sp)
1807         {
1808             output_sp->PutCString(g_python_command_instructions);
1809             output_sp->Flush();
1810         }
1811     }
1812 
1813 
1814     void
1815     IOHandlerInputComplete (IOHandler &io_handler, std::string &data) override
1816     {
1817         StreamFileSP error_sp = io_handler.GetErrorStreamFile();
1818 
1819         ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
1820         if (interpreter)
1821         {
1822 
1823             StringList lines;
1824             lines.SplitIntoLines(data);
1825             if (lines.GetSize() > 0)
1826             {
1827                 std::string funct_name_str;
1828                 if (interpreter->GenerateScriptAliasFunction (lines, funct_name_str))
1829                 {
1830                     if (funct_name_str.empty())
1831                     {
1832                         error_sp->Printf ("error: unable to obtain a function name, didn't add python command.\n");
1833                         error_sp->Flush();
1834                     }
1835                     else
1836                     {
1837                         // everything should be fine now, let's add this alias
1838 
1839                         CommandObjectSP command_obj_sp(new CommandObjectPythonFunction (m_interpreter,
1840                                                                                         m_cmd_name,
1841                                                                                         funct_name_str.c_str(),
1842                                                                                         m_short_help,
1843                                                                                         m_synchronicity));
1844 
1845                         if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, true))
1846                         {
1847                             error_sp->Printf ("error: unable to add selected command, didn't add python command.\n");
1848                             error_sp->Flush();
1849                         }
1850                     }
1851                 }
1852                 else
1853                 {
1854                     error_sp->Printf ("error: unable to create function, didn't add python command.\n");
1855                     error_sp->Flush();
1856                 }
1857             }
1858             else
1859             {
1860                 error_sp->Printf ("error: empty function, didn't add python command.\n");
1861                 error_sp->Flush();
1862             }
1863         }
1864         else
1865         {
1866             error_sp->Printf ("error: script interpreter missing, didn't add python command.\n");
1867             error_sp->Flush();
1868         }
1869 
1870         io_handler.SetIsDone(true);
1871     }
1872 
1873 protected:
1874     bool
1875     DoExecute (Args& command, CommandReturnObject &result) override
1876     {
1877         if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
1878         {
1879             result.AppendError ("only scripting language supported for scripted commands is currently Python");
1880             result.SetStatus (eReturnStatusFailed);
1881             return false;
1882         }
1883 
1884         size_t argc = command.GetArgumentCount();
1885 
1886         if (argc != 1)
1887         {
1888             result.AppendError ("'command script add' requires one argument");
1889             result.SetStatus (eReturnStatusFailed);
1890             return false;
1891         }
1892 
1893         // Store the options in case we get multi-line input
1894         m_cmd_name = command.GetArgumentAtIndex(0);
1895         m_short_help.assign(m_options.m_short_help);
1896         m_synchronicity = m_options.m_synchronicity;
1897 
1898         if (m_options.m_class_name.empty())
1899         {
1900             if (m_options.m_funct_name.empty())
1901             {
1902                 m_interpreter.GetPythonCommandsFromIOHandler("     ",  // Prompt
1903                                                              *this,    // IOHandlerDelegate
1904                                                              true,     // Run IOHandler in async mode
1905                                                              nullptr); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
1906             }
1907             else
1908             {
1909                 CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
1910                                                                         m_cmd_name,
1911                                                                         m_options.m_funct_name,
1912                                                                         m_options.m_short_help,
1913                                                                         m_synchronicity));
1914                 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
1915                 {
1916                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1917                 }
1918                 else
1919                 {
1920                     result.AppendError("cannot add command");
1921                     result.SetStatus (eReturnStatusFailed);
1922                 }
1923             }
1924         }
1925         else
1926         {
1927             ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter();
1928             if (!interpreter)
1929             {
1930                 result.AppendError("cannot find ScriptInterpreter");
1931                 result.SetStatus(eReturnStatusFailed);
1932                 return false;
1933             }
1934 
1935             auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str());
1936             if (!cmd_obj_sp)
1937             {
1938                 result.AppendError("cannot create helper object");
1939                 result.SetStatus(eReturnStatusFailed);
1940                 return false;
1941             }
1942 
1943             CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter,
1944                                                                      m_cmd_name,
1945                                                                      cmd_obj_sp,
1946                                                                      m_synchronicity));
1947             if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
1948             {
1949                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1950             }
1951             else
1952             {
1953                 result.AppendError("cannot add command");
1954                 result.SetStatus (eReturnStatusFailed);
1955             }
1956         }
1957 
1958         return result.Succeeded();
1959     }
1960 
1961     CommandOptions m_options;
1962     std::string m_cmd_name;
1963     std::string m_short_help;
1964     ScriptedCommandSynchronicity m_synchronicity;
1965 };
1966 
1967 static OptionEnumValueElement g_script_synchro_type[] =
1968 {
1969     { eScriptedCommandSynchronicitySynchronous,      "synchronous",       "Run synchronous"},
1970     { eScriptedCommandSynchronicityAsynchronous,     "asynchronous",      "Run asynchronous"},
1971     { eScriptedCommandSynchronicityCurrentValue,     "current",           "Do not alter current setting"},
1972     { 0, nullptr, nullptr }
1973 };
1974 
1975 OptionDefinition
1976 CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
1977 {
1978     { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction,        "Name of the Python function to bind to this command name."},
1979     { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass,        "Name of the Python class to bind to this command name."},
1980     { LLDB_OPT_SET_1, false, "help"  , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command."},
1981     { 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."},
1982     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
1983 };
1984 
1985 //-------------------------------------------------------------------------
1986 // CommandObjectCommandsScriptList
1987 //-------------------------------------------------------------------------
1988 
1989 class CommandObjectCommandsScriptList : public CommandObjectParsed
1990 {
1991 public:
1992     CommandObjectCommandsScriptList(CommandInterpreter &interpreter) :
1993         CommandObjectParsed(interpreter,
1994                             "command script list",
1995                             "List defined scripted commands.",
1996                             nullptr)
1997     {
1998     }
1999 
2000     ~CommandObjectCommandsScriptList() override = default;
2001 
2002     bool
2003     DoExecute (Args& command, CommandReturnObject &result) override
2004     {
2005         m_interpreter.GetHelp(result,
2006                               CommandInterpreter::eCommandTypesUserDef);
2007 
2008         result.SetStatus (eReturnStatusSuccessFinishResult);
2009 
2010         return true;
2011     }
2012 };
2013 
2014 //-------------------------------------------------------------------------
2015 // CommandObjectCommandsScriptClear
2016 //-------------------------------------------------------------------------
2017 
2018 class CommandObjectCommandsScriptClear : public CommandObjectParsed
2019 {
2020 public:
2021     CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) :
2022         CommandObjectParsed(interpreter,
2023                             "command script clear",
2024                             "Delete all scripted commands.",
2025                             nullptr)
2026     {
2027     }
2028 
2029     ~CommandObjectCommandsScriptClear() override = default;
2030 
2031 protected:
2032     bool
2033     DoExecute (Args& command, CommandReturnObject &result) override
2034     {
2035         m_interpreter.RemoveAllUser();
2036 
2037         result.SetStatus (eReturnStatusSuccessFinishResult);
2038 
2039         return true;
2040     }
2041 };
2042 
2043 //-------------------------------------------------------------------------
2044 // CommandObjectCommandsScriptDelete
2045 //-------------------------------------------------------------------------
2046 
2047 class CommandObjectCommandsScriptDelete : public CommandObjectParsed
2048 {
2049 public:
2050     CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) :
2051         CommandObjectParsed(interpreter,
2052                             "command script delete",
2053                             "Delete a scripted command.",
2054                             nullptr)
2055     {
2056         CommandArgumentEntry arg1;
2057         CommandArgumentData cmd_arg;
2058 
2059         // Define the first (and only) variant of this arg.
2060         cmd_arg.arg_type = eArgTypeCommandName;
2061         cmd_arg.arg_repetition = eArgRepeatPlain;
2062 
2063         // There is only one variant this argument could be; put it into the argument entry.
2064         arg1.push_back (cmd_arg);
2065 
2066         // Push the data for the first argument into the m_arguments vector.
2067         m_arguments.push_back (arg1);
2068     }
2069 
2070     ~CommandObjectCommandsScriptDelete() override = default;
2071 
2072 protected:
2073     bool
2074     DoExecute (Args& command, CommandReturnObject &result) override
2075     {
2076 
2077         size_t argc = command.GetArgumentCount();
2078 
2079         if (argc != 1)
2080         {
2081             result.AppendError ("'command script delete' requires one argument");
2082             result.SetStatus (eReturnStatusFailed);
2083             return false;
2084         }
2085 
2086         const char* cmd_name = command.GetArgumentAtIndex(0);
2087 
2088         if (cmd_name && *cmd_name && m_interpreter.HasUserCommands() && m_interpreter.UserCommandExists(cmd_name))
2089         {
2090             m_interpreter.RemoveUser(cmd_name);
2091             result.SetStatus (eReturnStatusSuccessFinishResult);
2092         }
2093         else
2094         {
2095             result.AppendErrorWithFormat ("command %s not found", cmd_name);
2096             result.SetStatus (eReturnStatusFailed);
2097         }
2098 
2099         return result.Succeeded();
2100     }
2101 };
2102 
2103 #pragma mark CommandObjectMultiwordCommandsScript
2104 
2105 //-------------------------------------------------------------------------
2106 // CommandObjectMultiwordCommandsScript
2107 //-------------------------------------------------------------------------
2108 
2109 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword
2110 {
2111 public:
2112     CommandObjectMultiwordCommandsScript (CommandInterpreter &interpreter) :
2113     CommandObjectMultiword (interpreter,
2114                             "command script",
2115                             "A set of commands for managing or customizing script commands.",
2116                             "command script <subcommand> [<subcommand-options>]")
2117     {
2118         LoadSubCommand ("add",    CommandObjectSP (new CommandObjectCommandsScriptAdd (interpreter)));
2119         LoadSubCommand ("delete", CommandObjectSP (new CommandObjectCommandsScriptDelete (interpreter)));
2120         LoadSubCommand ("clear",  CommandObjectSP (new CommandObjectCommandsScriptClear (interpreter)));
2121         LoadSubCommand ("list",   CommandObjectSP (new CommandObjectCommandsScriptList (interpreter)));
2122         LoadSubCommand ("import", CommandObjectSP (new CommandObjectCommandsScriptImport (interpreter)));
2123     }
2124 
2125     ~CommandObjectMultiwordCommandsScript() override = default;
2126 };
2127 
2128 #pragma mark CommandObjectMultiwordCommands
2129 
2130 //-------------------------------------------------------------------------
2131 // CommandObjectMultiwordCommands
2132 //-------------------------------------------------------------------------
2133 
2134 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands (CommandInterpreter &interpreter) :
2135     CommandObjectMultiword (interpreter,
2136                             "command",
2137                             "A set of commands for managing or customizing the debugger commands.",
2138                             "command <subcommand> [<subcommand-options>]")
2139 {
2140     LoadSubCommand ("source",  CommandObjectSP (new CommandObjectCommandsSource (interpreter)));
2141     LoadSubCommand ("alias",   CommandObjectSP (new CommandObjectCommandsAlias (interpreter)));
2142     LoadSubCommand ("unalias", CommandObjectSP (new CommandObjectCommandsUnalias (interpreter)));
2143     LoadSubCommand ("delete",  CommandObjectSP (new CommandObjectCommandsDelete (interpreter)));
2144     LoadSubCommand ("regex",   CommandObjectSP (new CommandObjectCommandsAddRegex (interpreter)));
2145     LoadSubCommand ("history", CommandObjectSP (new CommandObjectCommandsHistory (interpreter)));
2146     LoadSubCommand ("script",  CommandObjectSP (new CommandObjectMultiwordCommandsScript (interpreter)));
2147 }
2148 
2149 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default;
2150