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