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