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