1 | //===-- Options.h -----------------------------------------------*- 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 | |
9 | #ifndef LLDB_INTERPRETER_OPTIONS_H |
10 | #define LLDB_INTERPRETER_OPTIONS_H |
11 | |
12 | #include <set> |
13 | #include <vector> |
14 | |
15 | #include "lldb/Utility/Args.h" |
16 | #include "lldb/Utility/CompletionRequest.h" |
17 | #include "lldb/Utility/OptionDefinition.h" |
18 | #include "lldb/Utility/Status.h" |
19 | #include "lldb/lldb-defines.h" |
20 | #include "lldb/lldb-private.h" |
21 | |
22 | #include "llvm/ADT/ArrayRef.h" |
23 | #include "llvm/ADT/StringRef.h" |
24 | |
25 | namespace lldb_private { |
26 | |
27 | struct Option; |
28 | |
29 | typedef std::vector<std::tuple<std::string, int, std::string>> OptionArgVector; |
30 | typedef std::shared_ptr<OptionArgVector> OptionArgVectorSP; |
31 | |
32 | struct OptionArgElement { |
33 | enum { eUnrecognizedArg = -1, eBareDash = -2, eBareDoubleDash = -3 }; |
34 | |
35 | OptionArgElement(int defs_index, int pos, int arg_pos) |
36 | : opt_defs_index(defs_index), opt_pos(pos), opt_arg_pos(arg_pos) {} |
37 | |
38 | int opt_defs_index; |
39 | int opt_pos; |
40 | int opt_arg_pos; |
41 | }; |
42 | |
43 | typedef std::vector<OptionArgElement> OptionElementVector; |
44 | |
45 | /// \class Options Options.h "lldb/Interpreter/Options.h" |
46 | /// A command line option parsing protocol class. |
47 | /// |
48 | /// Options is designed to be subclassed to contain all needed options for a |
49 | /// given command. The options can be parsed by calling the Parse function. |
50 | /// |
51 | /// The options are specified using the format defined for the libc options |
52 | /// parsing function getopt_long_only: \code |
53 | /// #include <getopt.h> |
54 | /// int getopt_long_only(int argc, char * const *argv, const char |
55 | /// *optstring, const struct option *longopts, int *longindex); |
56 | /// \endcode |
57 | /// |
58 | class Options { |
59 | public: |
60 | Options(); |
61 | |
62 | virtual ~Options(); |
63 | |
64 | void BuildGetoptTable(); |
65 | |
66 | void BuildValidOptionSets(); |
67 | |
68 | uint32_t NumCommandOptions(); |
69 | |
70 | /// Get the option definitions to use when parsing Args options. |
71 | /// |
72 | /// \see Args::ParseOptions (Options&) |
73 | /// \see man getopt_long_only |
74 | Option *GetLongOptions(); |
75 | |
76 | // This gets passed the short option as an integer... |
77 | void OptionSeen(int short_option); |
78 | |
79 | bool VerifyOptions(CommandReturnObject &result); |
80 | |
81 | // Verify that the options given are in the options table and can be used |
82 | // together, but there may be some required options that are missing (used to |
83 | // verify options that get folded into command aliases). |
84 | bool VerifyPartialOptions(CommandReturnObject &result); |
85 | |
86 | void OutputFormattedUsageText(Stream &strm, |
87 | const OptionDefinition &option_def, |
88 | uint32_t output_max_columns); |
89 | |
90 | void GenerateOptionUsage(Stream &strm, CommandObject &cmd, |
91 | uint32_t screen_width); |
92 | |
93 | bool SupportsLongOption(const char *long_option); |
94 | |
95 | // The following two pure virtual functions must be defined by every class |
96 | // that inherits from this class. |
97 | |
98 | virtual llvm::ArrayRef<OptionDefinition> GetDefinitions() { |
99 | return llvm::ArrayRef<OptionDefinition>(); |
100 | } |
101 | |
102 | // Call this prior to parsing any options. This call will call the subclass |
103 | // OptionParsingStarting() and will avoid the need for all |
104 | // OptionParsingStarting() function instances from having to call the |
105 | // Option::OptionParsingStarting() like they did before. This was error prone |
106 | // and subclasses shouldn't have to do it. |
107 | void NotifyOptionParsingStarting(ExecutionContext *execution_context); |
108 | |
109 | /// Parse the provided arguments. |
110 | /// |
111 | /// The parsed options are set via calls to SetOptionValue. In case of a |
112 | /// successful parse, the function returns a copy of the input arguments |
113 | /// with the parsed options removed. Otherwise, it returns an error. |
114 | /// |
115 | /// param[in] platform_sp |
116 | /// The platform used for option validation. This is necessary |
117 | /// because an empty execution_context is not enough to get us |
118 | /// to a reasonable platform. If the platform isn't given, |
119 | /// we'll try to get it from the execution context. If we can't |
120 | /// get it from the execution context, we'll skip validation. |
121 | /// |
122 | /// param[in] require_validation |
123 | /// When true, it will fail option parsing if validation could |
124 | /// not occur due to not having a platform. |
125 | llvm::Expected<Args> Parse(const Args &args, |
126 | ExecutionContext *execution_context, |
127 | lldb::PlatformSP platform_sp, |
128 | bool require_validation); |
129 | |
130 | llvm::Expected<Args> ParseAlias(const Args &args, |
131 | OptionArgVector *option_arg_vector, |
132 | std::string &input_line); |
133 | |
134 | OptionElementVector ParseForCompletion(const Args &args, |
135 | uint32_t cursor_index); |
136 | |
137 | Status NotifyOptionParsingFinished(ExecutionContext *execution_context); |
138 | |
139 | /// Set the value of an option. |
140 | /// |
141 | /// \param[in] option_idx |
142 | /// The index into the "struct option" array that was returned |
143 | /// by Options::GetLongOptions(). |
144 | /// |
145 | /// \param[in] option_arg |
146 | /// The argument value for the option that the user entered, or |
147 | /// nullptr if there is no argument for the current option. |
148 | /// |
149 | /// \param[in] execution_context |
150 | /// The execution context to use for evaluating the option. |
151 | /// May be nullptr if the option is to be evaluated outside any |
152 | /// particular context. |
153 | /// |
154 | /// \see Args::ParseOptions (Options&) |
155 | /// \see man getopt_long_only |
156 | virtual Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, |
157 | ExecutionContext *execution_context) = 0; |
158 | |
159 | /// Handles the generic bits of figuring out whether we are in an option, |
160 | /// and if so completing it. |
161 | /// |
162 | /// \param[in,out] request |
163 | /// The completion request that we need to act upon. |
164 | /// |
165 | /// \param[in] interpreter |
166 | /// The interpreter that's doing the completing. |
167 | /// |
168 | /// FIXME: This is the wrong return value, since we also need to |
169 | /// make a distinction between total number of matches, and the window the |
170 | /// user wants returned. |
171 | /// |
172 | /// \return |
173 | /// \b true if we were in an option, \b false otherwise. |
174 | bool HandleOptionCompletion(lldb_private::CompletionRequest &request, |
175 | OptionElementVector &option_map, |
176 | CommandInterpreter &interpreter); |
177 | |
178 | /// Handles the generic bits of figuring out whether we are in an option, |
179 | /// and if so completing it. |
180 | /// |
181 | /// \param[in,out] request |
182 | /// The completion request that we need to act upon. |
183 | /// |
184 | /// \param[in] interpreter |
185 | /// The command interpreter doing the completion. |
186 | virtual void |
187 | HandleOptionArgumentCompletion(lldb_private::CompletionRequest &request, |
188 | OptionElementVector &opt_element_vector, |
189 | int opt_element_index, |
190 | CommandInterpreter &interpreter); |
191 | |
192 | protected: |
193 | // This is a set of options expressed as indexes into the options table for |
194 | // this Option. |
195 | typedef std::set<int> OptionSet; |
196 | typedef std::vector<OptionSet> OptionSetVector; |
197 | |
198 | std::vector<Option> m_getopt_table; |
199 | OptionSet m_seen_options; |
200 | OptionSetVector m_required_options; |
201 | OptionSetVector m_optional_options; |
202 | |
203 | OptionSetVector &GetRequiredOptions() { |
204 | BuildValidOptionSets(); |
205 | return m_required_options; |
206 | } |
207 | |
208 | OptionSetVector &GetOptionalOptions() { |
209 | BuildValidOptionSets(); |
210 | return m_optional_options; |
211 | } |
212 | |
213 | bool IsASubset(const OptionSet &set_a, const OptionSet &set_b); |
214 | |
215 | size_t OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b, |
216 | OptionSet &diffs); |
217 | |
218 | void OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b, |
219 | OptionSet &union_set); |
220 | |
221 | // Subclasses must reset their option values prior to starting a new option |
222 | // parse. Each subclass must override this function and revert all option |
223 | // settings to default values. |
224 | virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0; |
225 | |
226 | virtual Status OptionParsingFinished(ExecutionContext *execution_context) { |
227 | // If subclasses need to know when the options are done being parsed they |
228 | // can implement this function to do extra checking |
229 | Status error; |
230 | return error; |
231 | } |
232 | }; |
233 | |
234 | class OptionGroup { |
235 | public: |
236 | OptionGroup() = default; |
237 | |
238 | virtual ~OptionGroup() = default; |
239 | |
240 | virtual llvm::ArrayRef<OptionDefinition> GetDefinitions() = 0; |
241 | |
242 | virtual Status SetOptionValue(uint32_t option_idx, |
243 | llvm::StringRef option_value, |
244 | ExecutionContext *execution_context) = 0; |
245 | |
246 | virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0; |
247 | |
248 | virtual Status OptionParsingFinished(ExecutionContext *execution_context) { |
249 | // If subclasses need to know when the options are done being parsed they |
250 | // can implement this function to do extra checking |
251 | Status error; |
252 | return error; |
253 | } |
254 | }; |
255 | |
256 | class OptionGroupOptions : public Options { |
257 | public: |
258 | OptionGroupOptions() = default; |
259 | |
260 | ~OptionGroupOptions() override = default; |
261 | |
262 | /// Append options from a OptionGroup class. |
263 | /// |
264 | /// Append all options from \a group using the exact same option groups that |
265 | /// each option is defined with. |
266 | /// |
267 | /// \param[in] group |
268 | /// A group of options to take option values from and copy their |
269 | /// definitions into this class. |
270 | void Append(OptionGroup *group); |
271 | |
272 | /// Append options from a OptionGroup class. |
273 | /// |
274 | /// Append options from \a group that have a usage mask that has any bits in |
275 | /// "src_mask" set. After the option definition is copied into the options |
276 | /// definitions in this class, set the usage_mask to "dst_mask". |
277 | /// |
278 | /// \param[in] group |
279 | /// A group of options to take option values from and copy their |
280 | /// definitions into this class. |
281 | /// |
282 | /// \param[in] src_mask |
283 | /// When copying options from \a group, you might only want some of |
284 | /// the options to be appended to this group. This mask allows you |
285 | /// to control which options from \a group get added. It also allows |
286 | /// you to specify the same options from \a group multiple times |
287 | /// for different option sets. |
288 | /// |
289 | /// \param[in] dst_mask |
290 | /// Set the usage mask for any copied options to \a dst_mask after |
291 | /// copying the option definition. |
292 | void Append(OptionGroup *group, uint32_t src_mask, uint32_t dst_mask); |
293 | |
294 | /// Append selected options from a OptionGroup class. |
295 | /// |
296 | /// Append the subset of options from \a group, where the "long_option" value |
297 | /// is _not_ in \a exclude_long_options. |
298 | /// |
299 | /// \param[in] group |
300 | /// A group of options to take option values from and copy their |
301 | /// definitions into this class. |
302 | /// |
303 | /// \param[in] exclude_long_options |
304 | /// A set of long option strings which indicate which option values values |
305 | /// to limit from \a group. |
306 | void Append(OptionGroup *group, |
307 | llvm::ArrayRef<llvm::StringRef> exclude_long_options); |
308 | |
309 | void Finalize(); |
310 | |
311 | bool DidFinalize() { return m_did_finalize; } |
312 | |
313 | Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, |
314 | ExecutionContext *execution_context) override; |
315 | |
316 | void OptionParsingStarting(ExecutionContext *execution_context) override; |
317 | |
318 | Status OptionParsingFinished(ExecutionContext *execution_context) override; |
319 | |
320 | llvm::ArrayRef<OptionDefinition> GetDefinitions() override { |
321 | assert(m_did_finalize); |
322 | return m_option_defs; |
323 | } |
324 | |
325 | const OptionGroup *GetGroupWithOption(char short_opt); |
326 | |
327 | struct OptionInfo { |
328 | OptionInfo(OptionGroup *g, uint32_t i) : option_group(g), option_index(i) {} |
329 | OptionGroup *option_group; // The group that this option came from |
330 | uint32_t option_index; // The original option index from the OptionGroup |
331 | }; |
332 | typedef std::vector<OptionInfo> OptionInfos; |
333 | |
334 | std::vector<OptionDefinition> m_option_defs; |
335 | OptionInfos m_option_infos; |
336 | bool m_did_finalize = false; |
337 | }; |
338 | |
339 | } // namespace lldb_private |
340 | |
341 | #endif // LLDB_INTERPRETER_OPTIONS_H |
342 | |