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 /// 191 /// FIXME: This is the wrong return value, since we also need to 192 /// make a distinction between total number of matches, and the window the 193 /// user wants returned. 194 /// 195 /// \return 196 /// \btrue if we were in an option, \bfalse otherwise. 197 virtual bool 198 HandleOptionArgumentCompletion(lldb_private::CompletionRequest &request, 199 OptionElementVector &opt_element_vector, 200 int opt_element_index, 201 CommandInterpreter &interpreter); 202 203 protected: 204 // This is a set of options expressed as indexes into the options table for 205 // this Option. 206 typedef std::set<int> OptionSet; 207 typedef std::vector<OptionSet> OptionSetVector; 208 209 std::vector<Option> m_getopt_table; 210 OptionSet m_seen_options; 211 OptionSetVector m_required_options; 212 OptionSetVector m_optional_options; 213 214 OptionSetVector &GetRequiredOptions() { 215 BuildValidOptionSets(); 216 return m_required_options; 217 } 218 219 OptionSetVector &GetOptionalOptions() { 220 BuildValidOptionSets(); 221 return m_optional_options; 222 } 223 224 bool IsASubset(const OptionSet &set_a, const OptionSet &set_b); 225 226 size_t OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b, 227 OptionSet &diffs); 228 229 void OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b, 230 OptionSet &union_set); 231 232 // Subclasses must reset their option values prior to starting a new option 233 // parse. Each subclass must override this function and revert all option 234 // settings to default values. 235 virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0; 236 237 virtual Status OptionParsingFinished(ExecutionContext *execution_context) { 238 // If subclasses need to know when the options are done being parsed they 239 // can implement this function to do extra checking 240 Status error; 241 return error; 242 } 243 }; 244 245 class OptionGroup { 246 public: 247 OptionGroup() = default; 248 249 virtual ~OptionGroup() = default; 250 251 virtual llvm::ArrayRef<OptionDefinition> GetDefinitions() = 0; 252 253 virtual Status SetOptionValue(uint32_t option_idx, 254 llvm::StringRef option_value, 255 ExecutionContext *execution_context) = 0; 256 257 virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0; 258 259 virtual Status OptionParsingFinished(ExecutionContext *execution_context) { 260 // If subclasses need to know when the options are done being parsed they 261 // can implement this function to do extra checking 262 Status error; 263 return error; 264 } 265 }; 266 267 class OptionGroupOptions : public Options { 268 public: 269 OptionGroupOptions() 270 : Options(), m_option_defs(), m_option_infos(), m_did_finalize(false) {} 271 272 ~OptionGroupOptions() override = default; 273 274 /// Append options from a OptionGroup class. 275 /// 276 /// Append all options from \a group using the exact same option groups that 277 /// each option is defined with. 278 /// 279 /// \param[in] group 280 /// A group of options to take option values from and copy their 281 /// definitions into this class. 282 void Append(OptionGroup *group); 283 284 /// Append options from a OptionGroup class. 285 /// 286 /// Append options from \a group that have a usage mask that has any bits in 287 /// "src_mask" set. After the option definition is copied into the options 288 /// definitions in this class, set the usage_mask to "dst_mask". 289 /// 290 /// \param[in] group 291 /// A group of options to take option values from and copy their 292 /// definitions into this class. 293 /// 294 /// \param[in] src_mask 295 /// When copying options from \a group, you might only want some of 296 /// the options to be appended to this group. This mask allows you 297 /// to control which options from \a group get added. It also allows 298 /// you to specify the same options from \a group multiple times 299 /// for different option sets. 300 /// 301 /// \param[in] dst_mask 302 /// Set the usage mask for any copied options to \a dst_mask after 303 /// copying the option definition. 304 void Append(OptionGroup *group, uint32_t src_mask, uint32_t dst_mask); 305 306 void Finalize(); 307 308 bool DidFinalize() { return m_did_finalize; } 309 310 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 311 ExecutionContext *execution_context) override; 312 313 void OptionParsingStarting(ExecutionContext *execution_context) override; 314 315 Status OptionParsingFinished(ExecutionContext *execution_context) override; 316 317 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 318 assert(m_did_finalize); 319 return m_option_defs; 320 } 321 322 const OptionGroup *GetGroupWithOption(char short_opt); 323 324 struct OptionInfo { 325 OptionInfo(OptionGroup *g, uint32_t i) : option_group(g), option_index(i) {} 326 OptionGroup *option_group; // The group that this option came from 327 uint32_t option_index; // The original option index from the OptionGroup 328 }; 329 typedef std::vector<OptionInfo> OptionInfos; 330 331 std::vector<OptionDefinition> m_option_defs; 332 OptionInfos m_option_infos; 333 bool m_did_finalize; 334 }; 335 336 } // namespace lldb_private 337 338 #endif // liblldb_Options_h_ 339