LLDB  mainline
CommandAlias.cpp
Go to the documentation of this file.
1 //===-- CommandAlias.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 
10 
11 #include "llvm/Support/ErrorHandling.h"
12 
18 
19 using namespace lldb;
20 using namespace lldb_private;
21 
22 static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
23  llvm::StringRef options_args,
24  OptionArgVectorSP &option_arg_vector_sp) {
25  bool success = true;
26  OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
27 
28  if (options_args.size() < 1)
29  return true;
30 
31  Args args(options_args);
32  std::string options_string(options_args);
33  CommandReturnObject result;
34  // Check to see if the command being aliased can take any command options.
35  Options *options = cmd_obj_sp->GetOptions();
36  if (options) {
37  // See if any options were specified as part of the alias; if so, handle
38  // them appropriately.
39  ExecutionContext exe_ctx =
40  cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();
41  options->NotifyOptionParsingStarting(&exe_ctx);
42 
43  llvm::Expected<Args> args_or =
44  options->ParseAlias(args, option_arg_vector, options_string);
45  if (!args_or) {
46  result.AppendError(toString(args_or.takeError()));
47  result.AppendError("Unable to create requested alias.\n");
49  return false;
50  }
51  args = std::move(*args_or);
52  options->VerifyPartialOptions(result);
53  if (!result.Succeeded() &&
55  result.AppendError("Unable to create requested alias.\n");
56  return false;
57  }
58  }
59 
60  if (!options_string.empty()) {
61  if (cmd_obj_sp->WantsRawCommandString())
62  option_arg_vector->emplace_back("<argument>", -1, options_string);
63  else {
64  for (auto &entry : args.entries()) {
65  if (!entry.ref.empty())
66  option_arg_vector->emplace_back("<argument>", -1, entry.ref);
67  }
68  }
69  }
70 
71  return success;
72 }
73 
74 CommandAlias::CommandAlias(CommandInterpreter &interpreter,
75  lldb::CommandObjectSP cmd_sp,
76  llvm::StringRef options_args, llvm::StringRef name,
77  llvm::StringRef help, llvm::StringRef syntax,
78  uint32_t flags)
79  : CommandObject(interpreter, name, help, syntax, flags),
80  m_underlying_command_sp(), m_option_string(options_args),
81  m_option_args_sp(new OptionArgVector),
82  m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),
83  m_did_set_help_long(false) {
84  if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
85  m_underlying_command_sp = cmd_sp;
86  for (int i = 0;
87  auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
88  i++) {
89  m_arguments.push_back(*cmd_entry);
90  }
91  if (!help.empty()) {
92  StreamString sstr;
93  StreamString translation_and_help;
94  GetAliasExpansion(sstr);
95 
96  translation_and_help.Printf(
97  "(%s) %s", sstr.GetData(),
98  GetUnderlyingCommand()->GetHelp().str().c_str());
99  SetHelp(translation_and_help.GetString());
100  }
101  }
102 }
103 
105  if (IsValid())
106  return m_underlying_command_sp->WantsRawCommandString();
107  return false;
108 }
109 
111  if (IsValid())
112  return m_underlying_command_sp->WantsCompletion();
113  return false;
114 }
115 
117  if (IsValid())
118  return m_underlying_command_sp->HandleCompletion(request);
119  return -1;
120 }
121 
123  CompletionRequest &request, OptionElementVector &opt_element_vector) {
124  if (IsValid())
125  return m_underlying_command_sp->HandleArgumentCompletion(
126  request, opt_element_vector);
127  return -1;
128 }
129 
131  if (IsValid())
132  return m_underlying_command_sp->GetOptions();
133  return nullptr;
134 }
135 
136 bool CommandAlias::Execute(const char *args_string,
137  CommandReturnObject &result) {
138  llvm_unreachable("CommandAlias::Execute is not to be called");
139 }
140 
142  llvm::StringRef command_name = m_underlying_command_sp->GetCommandName();
143  help_string.Printf("'%*s", (int)command_name.size(), command_name.data());
144 
145  if (!m_option_args_sp) {
146  help_string.Printf("'");
147  return;
148  }
149 
150  OptionArgVector *options = m_option_args_sp.get();
151  std::string opt;
152  std::string value;
153 
154  for (const auto &opt_entry : *options) {
155  std::tie(opt, std::ignore, value) = opt_entry;
156  if (opt == "<argument>") {
157  help_string.Printf(" %s", value.c_str());
158  } else {
159  help_string.Printf(" %s", opt.c_str());
160  if ((value != "<no-argument>") && (value != "<need-argument")) {
161  help_string.Printf(" %s", value.c_str());
162  }
163  }
164  }
165 
166  help_string.Printf("'");
167 }
168 
170  if (m_is_dashdash_alias != eLazyBoolCalculate)
171  return (m_is_dashdash_alias == eLazyBoolYes);
172  m_is_dashdash_alias = eLazyBoolNo;
173  if (!IsValid())
174  return false;
175 
176  std::string opt;
177  std::string value;
178 
179  for (const auto &opt_entry : *GetOptionArguments()) {
180  std::tie(opt, std::ignore, value) = opt_entry;
181  if (opt == "<argument>" && !value.empty() &&
182  llvm::StringRef(value).endswith("--")) {
183  m_is_dashdash_alias = eLazyBoolYes;
184  break;
185  }
186  }
187 
188  // if this is a nested alias, it may be adding arguments on top of an already
189  // dash-dash alias
190  if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
191  m_is_dashdash_alias =
192  (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes
193  : eLazyBoolNo);
194  return (m_is_dashdash_alias == eLazyBoolYes);
195 }
196 
198  if (GetUnderlyingCommand())
199  return GetUnderlyingCommand()->IsAlias();
200  return false;
201 }
202 
203 std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() {
204  auto underlying = GetUnderlyingCommand();
205  if (!underlying)
206  return {nullptr, nullptr};
207 
208  if (underlying->IsAlias()) {
209  auto desugared = ((CommandAlias *)underlying.get())->Desugar();
210  auto options = GetOptionArguments();
211  options->insert(options->begin(), desugared.second->begin(),
212  desugared.second->end());
213  return {desugared.first, options};
214  }
215 
216  return {underlying, GetOptionArguments()};
217 }
218 
219 // allow CommandAlias objects to provide their own help, but fallback to the
220 // info for the underlying command if no customization has been provided
221 void CommandAlias::SetHelp(llvm::StringRef str) {
222  this->CommandObject::SetHelp(str);
223  m_did_set_help = true;
224 }
225 
226 void CommandAlias::SetHelpLong(llvm::StringRef str) {
227  this->CommandObject::SetHelpLong(str);
228  m_did_set_help_long = true;
229 }
230 
231 llvm::StringRef CommandAlias::GetHelp() {
232  if (!m_cmd_help_short.empty() || m_did_set_help)
233  return m_cmd_help_short;
234  if (IsValid())
235  return m_underlying_command_sp->GetHelp();
236  return llvm::StringRef();
237 }
238 
239 llvm::StringRef CommandAlias::GetHelpLong() {
240  if (!m_cmd_help_long.empty() || m_did_set_help_long)
241  return m_cmd_help_long;
242  if (IsValid())
243  return m_underlying_command_sp->GetHelpLong();
244  return llvm::StringRef();
245 }
A command line argument class.
Definition: Args.h:32
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:123
llvm::StringRef GetHelpLong() override
std::pair< lldb::CommandObjectSP, OptionArgVectorSP > Desugar()
int HandleCompletion(CompletionRequest &request) override
This default version handles calling option argument completions and then calls HandleArgumentComplet...
llvm::Expected< Args > ParseAlias(const Args &args, OptionArgVector *option_arg_vector, std::string &input_line)
Definition: Options.cpp:975
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
bool IsDashDashCommand() override
const char * GetData() const
Definition: StreamString.h:43
bool WantsRawCommandString() override
"lldb/Utility/ArgCompletionRequest.h"
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:41
virtual void SetHelpLong(llvm::StringRef str)
llvm::StringRef toString(Record::Kind K)
std::vector< std::tuple< std::string, int, std::string > > OptionArgVector
Definition: Options.h:25
Options * GetOptions() override
static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp, llvm::StringRef options_args, OptionArgVectorSP &option_arg_vector_sp)
llvm::StringRef GetString() const
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
OptionArgVectorSP GetOptionArguments() const
Definition: CommandAlias.h:64
int HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
A command line option parsing protocol class.
Definition: Options.h:62
void void AppendError(llvm::StringRef in_string)
bool VerifyPartialOptions(CommandReturnObject &result)
Definition: Options.cpp:625
lldb::CommandObjectSP GetUnderlyingCommand()
Definition: CommandAlias.h:61
Definition: SBAddress.h:15
void GetAliasExpansion(StreamString &help_string) const
std::shared_ptr< OptionArgVector > OptionArgVectorSP
Definition: Options.h:28
bool WantsCompletion() override
virtual void SetHelp(llvm::StringRef str)
llvm::StringRef GetHelp() override
void SetHelp(llvm::StringRef str) override
void SetStatus(lldb::ReturnStatus status)
void SetHelpLong(llvm::StringRef str) override
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition: Options.cpp:32
bool Execute(const char *args_string, CommandReturnObject &result) override
std::vector< CommandArgumentEntry > m_arguments