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