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