]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Interpreter/CommandAlias.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Interpreter / CommandAlias.cpp
1 //===-- CommandAlias.cpp -----------------------------------------*- C++-*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Interpreter/CommandAlias.h"
11
12 #include "llvm/Support/ErrorHandling.h"
13
14 #include "lldb/Core/StreamString.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandObject.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/Options.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   CommandReturnObject result;
35   // Check to see if the command being aliased can take any command options.
36   Options *options = cmd_obj_sp->GetOptions();
37   if (options) {
38     // See if any options were specified as part of the alias;  if so, handle
39     // them appropriately.
40     ExecutionContext exe_ctx =
41         cmd_obj_sp->GetCommandInterpreter().GetExecutionContext();
42     options->NotifyOptionParsingStarting(&exe_ctx);
43     args.Unshift(llvm::StringRef("dummy_arg"));
44     options_string = args.ParseAliasOptions(*options, result, option_arg_vector,
45                                             options_args);
46     args.Shift();
47     if (result.Succeeded())
48       options->VerifyPartialOptions(result);
49     if (!result.Succeeded() &&
50         result.GetStatus() != lldb::eReturnStatusStarted) {
51       result.AppendError("Unable to create requested alias.\n");
52       return false;
53     }
54   }
55
56   if (!options_string.empty()) {
57     if (cmd_obj_sp->WantsRawCommandString())
58       option_arg_vector->emplace_back("<argument>", -1, options_string);
59     else {
60       for (auto &entry : args.entries()) {
61         if (!entry.ref.empty())
62           option_arg_vector->emplace_back("<argument>", -1, entry.ref);
63       }
64     }
65   }
66
67   return success;
68 }
69
70 CommandAlias::CommandAlias(CommandInterpreter &interpreter,
71                            lldb::CommandObjectSP cmd_sp,
72                            llvm::StringRef options_args, llvm::StringRef name,
73                            llvm::StringRef help, llvm::StringRef syntax,
74                            uint32_t flags)
75     : CommandObject(interpreter, name, help, syntax, flags),
76       m_underlying_command_sp(), m_option_string(options_args),
77       m_option_args_sp(new OptionArgVector),
78       m_is_dashdash_alias(eLazyBoolCalculate), m_did_set_help(false),
79       m_did_set_help_long(false) {
80   if (ProcessAliasOptionsArgs(cmd_sp, options_args, m_option_args_sp)) {
81     m_underlying_command_sp = cmd_sp;
82     for (int i = 0;
83          auto cmd_entry = m_underlying_command_sp->GetArgumentEntryAtIndex(i);
84          i++) {
85       m_arguments.push_back(*cmd_entry);
86     }
87     if (!help.empty()) {
88       StreamString sstr;
89       StreamString translation_and_help;
90       GetAliasExpansion(sstr);
91
92       translation_and_help.Printf(
93           "(%s)  %s", sstr.GetData(),
94           GetUnderlyingCommand()->GetHelp().str().c_str());
95       SetHelp(translation_and_help.GetString());
96     }
97   }
98 }
99
100 bool CommandAlias::WantsRawCommandString() {
101   if (IsValid())
102     return m_underlying_command_sp->WantsRawCommandString();
103   return false;
104 }
105
106 bool CommandAlias::WantsCompletion() {
107   if (IsValid())
108     return m_underlying_command_sp->WantsCompletion();
109   return false;
110 }
111
112 int CommandAlias::HandleCompletion(Args &input, int &cursor_index,
113                                    int &cursor_char_position,
114                                    int match_start_point,
115                                    int max_return_elements, bool &word_complete,
116                                    StringList &matches) {
117   if (IsValid())
118     return m_underlying_command_sp->HandleCompletion(
119         input, cursor_index, cursor_char_position, match_start_point,
120         max_return_elements, word_complete, matches);
121   return -1;
122 }
123
124 int CommandAlias::HandleArgumentCompletion(
125     Args &input, int &cursor_index, int &cursor_char_position,
126     OptionElementVector &opt_element_vector, int match_start_point,
127     int max_return_elements, bool &word_complete, StringList &matches) {
128   if (IsValid())
129     return m_underlying_command_sp->HandleArgumentCompletion(
130         input, cursor_index, cursor_char_position, opt_element_vector,
131         match_start_point, max_return_elements, word_complete, matches);
132   return -1;
133 }
134
135 Options *CommandAlias::GetOptions() {
136   if (IsValid())
137     return m_underlying_command_sp->GetOptions();
138   return nullptr;
139 }
140
141 bool CommandAlias::Execute(const char *args_string,
142                            CommandReturnObject &result) {
143   llvm_unreachable("CommandAlias::Execute is not to be called");
144 }
145
146 void CommandAlias::GetAliasExpansion(StreamString &help_string) const {
147   llvm::StringRef command_name = m_underlying_command_sp->GetCommandName();
148   help_string.Printf("'%*s", (int)command_name.size(), command_name.data());
149
150   if (!m_option_args_sp) {
151     help_string.Printf("'");
152     return;
153   }
154
155   OptionArgVector *options = m_option_args_sp.get();
156   std::string opt;
157   std::string value;
158
159   for (const auto &opt_entry : *options) {
160     std::tie(opt, std::ignore, value) = opt_entry;
161     if (opt == "<argument>") {
162       help_string.Printf(" %s", value.c_str());
163     } else {
164       help_string.Printf(" %s", opt.c_str());
165       if ((value.compare("<no-argument>") != 0) &&
166           (value.compare("<need-argument") != 0)) {
167         help_string.Printf(" %s", value.c_str());
168       }
169     }
170   }
171
172   help_string.Printf("'");
173 }
174
175 bool CommandAlias::IsDashDashCommand() {
176   if (m_is_dashdash_alias != eLazyBoolCalculate)
177     return (m_is_dashdash_alias == eLazyBoolYes);
178   m_is_dashdash_alias = eLazyBoolNo;
179   if (!IsValid())
180     return false;
181
182   std::string opt;
183   std::string value;
184
185   for (const auto &opt_entry : *GetOptionArguments()) {
186     std::tie(opt, std::ignore, value) = opt_entry;
187     if (opt == "<argument>" && !value.empty() &&
188         llvm::StringRef(value).endswith("--")) {
189       m_is_dashdash_alias = eLazyBoolYes;
190       break;
191     }
192   }
193
194   // if this is a nested alias, it may be adding arguments on top of an
195   // already dash-dash alias
196   if ((m_is_dashdash_alias == eLazyBoolNo) && IsNestedAlias())
197     m_is_dashdash_alias =
198         (GetUnderlyingCommand()->IsDashDashCommand() ? eLazyBoolYes
199                                                      : eLazyBoolNo);
200   return (m_is_dashdash_alias == eLazyBoolYes);
201 }
202
203 bool CommandAlias::IsNestedAlias() {
204   if (GetUnderlyingCommand())
205     return GetUnderlyingCommand()->IsAlias();
206   return false;
207 }
208
209 std::pair<lldb::CommandObjectSP, OptionArgVectorSP> CommandAlias::Desugar() {
210   auto underlying = GetUnderlyingCommand();
211   if (!underlying)
212     return {nullptr, nullptr};
213
214   if (underlying->IsAlias()) {
215     auto desugared = ((CommandAlias *)underlying.get())->Desugar();
216     auto options = GetOptionArguments();
217     options->insert(options->begin(), desugared.second->begin(),
218                     desugared.second->end());
219     return {desugared.first, options};
220   }
221
222   return {underlying, GetOptionArguments()};
223 }
224
225 // allow CommandAlias objects to provide their own help, but fallback to the
226 // info
227 // for the underlying command if no customization has been provided
228 void CommandAlias::SetHelp(llvm::StringRef str) {
229   this->CommandObject::SetHelp(str);
230   m_did_set_help = true;
231 }
232
233 void CommandAlias::SetHelpLong(llvm::StringRef str) {
234   this->CommandObject::SetHelpLong(str);
235   m_did_set_help_long = true;
236 }
237
238 llvm::StringRef CommandAlias::GetHelp() {
239   if (!m_cmd_help_short.empty() || m_did_set_help)
240     return m_cmd_help_short;
241   if (IsValid())
242     return m_underlying_command_sp->GetHelp();
243   return llvm::StringRef();
244 }
245
246 llvm::StringRef CommandAlias::GetHelpLong() {
247   if (!m_cmd_help_long.empty() || m_did_set_help_long)
248     return m_cmd_help_long;
249   if (IsValid())
250     return m_underlying_command_sp->GetHelpLong();
251   return llvm::StringRef();
252 }