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