Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Interpreter/CommandAlias.cpp
39587 views
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
9
#include "lldb/Interpreter/CommandAlias.h"
10
11
#include "llvm/ADT/STLExtras.h"
12
#include "llvm/Support/ErrorHandling.h"
13
14
#include "lldb/Interpreter/CommandInterpreter.h"
15
#include "lldb/Interpreter/CommandObject.h"
16
#include "lldb/Interpreter/CommandReturnObject.h"
17
#include "lldb/Interpreter/Options.h"
18
#include "lldb/Utility/StreamString.h"
19
20
using namespace lldb;
21
using namespace lldb_private;
22
23
static 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() &&
56
result.GetStatus() != lldb::eReturnStatusStarted) {
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
78
CommandAlias::CommandAlias(CommandInterpreter &interpreter,
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)) {
89
m_underlying_command_sp = cmd_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;
98
GetAliasExpansion(sstr);
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
108
bool CommandAlias::WantsRawCommandString() {
109
if (IsValid())
110
return m_underlying_command_sp->WantsRawCommandString();
111
return false;
112
}
113
114
bool CommandAlias::WantsCompletion() {
115
if (IsValid())
116
return m_underlying_command_sp->WantsCompletion();
117
return false;
118
}
119
120
void CommandAlias::HandleCompletion(CompletionRequest &request) {
121
if (IsValid())
122
m_underlying_command_sp->HandleCompletion(request);
123
}
124
125
void CommandAlias::HandleArgumentCompletion(
126
CompletionRequest &request, OptionElementVector &opt_element_vector) {
127
if (IsValid())
128
m_underlying_command_sp->HandleArgumentCompletion(request,
129
opt_element_vector);
130
}
131
132
Options *CommandAlias::GetOptions() {
133
if (IsValid())
134
return m_underlying_command_sp->GetOptions();
135
return nullptr;
136
}
137
138
void CommandAlias::Execute(const char *args_string,
139
CommandReturnObject &result) {
140
llvm_unreachable("CommandAlias::Execute is not to be called");
141
}
142
143
void CommandAlias::GetAliasExpansion(StreamString &help_string) const {
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;
158
if (opt == CommandInterpreter::g_argument) {
159
help_string.Printf(" %s", value.c_str());
160
} else {
161
help_string.Printf(" %s", opt.c_str());
162
if ((value != CommandInterpreter::g_no_argument)
163
&& (value != CommandInterpreter::g_need_argument)) {
164
help_string.Printf(" %s", value.c_str());
165
}
166
}
167
}
168
169
help_string.Printf("'");
170
}
171
172
bool CommandAlias::IsDashDashCommand() {
173
if (m_is_dashdash_alias != eLazyBoolCalculate)
174
return (m_is_dashdash_alias == eLazyBoolYes);
175
m_is_dashdash_alias = eLazyBoolNo;
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).ends_with("--")) {
186
m_is_dashdash_alias = eLazyBoolYes;
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
193
if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
194
m_is_dashdash_alias =
195
(GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes
196
: eLazyBoolNo);
197
return (m_is_dashdash_alias == eLazyBoolYes);
198
}
199
200
bool CommandAlias::IsNestedAlias() {
201
if (GetUnderlyingCommand())
202
return GetUnderlyingCommand()->IsAlias();
203
return false;
204
}
205
206
std::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
226
void CommandAlias::SetHelp(llvm::StringRef str) {
227
this->CommandObject::SetHelp(str);
228
m_did_set_help = true;
229
}
230
231
void CommandAlias::SetHelpLong(llvm::StringRef str) {
232
this->CommandObject::SetHelpLong(str);
233
m_did_set_help_long = true;
234
}
235
236
llvm::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
244
llvm::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
}
251
252