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