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