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