| //===-- Options.h -----------------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_Options_h_ |
| #define liblldb_Options_h_ |
| |
| #include <set> |
| #include <vector> |
| |
| #include "lldb/Utility/Args.h" |
| #include "lldb/Utility/CompletionRequest.h" |
| #include "lldb/Utility/Status.h" |
| #include "lldb/lldb-defines.h" |
| #include "lldb/lldb-private.h" |
| |
| #include "llvm/ADT/ArrayRef.h" |
| |
| namespace lldb_private { |
| |
| struct Option; |
| |
| typedef std::vector<std::tuple<std::string, int, std::string>> OptionArgVector; |
| typedef std::shared_ptr<OptionArgVector> OptionArgVectorSP; |
| |
| struct OptionArgElement { |
| enum { eUnrecognizedArg = -1, eBareDash = -2, eBareDoubleDash = -3 }; |
| |
| OptionArgElement(int defs_index, int pos, int arg_pos) |
| : opt_defs_index(defs_index), opt_pos(pos), opt_arg_pos(arg_pos) {} |
| |
| int opt_defs_index; |
| int opt_pos; |
| int opt_arg_pos; |
| }; |
| |
| typedef std::vector<OptionArgElement> OptionElementVector; |
| |
| static inline bool isprint8(int ch) { |
| if (ch & 0xffffff00u) |
| return false; |
| return isprint(ch); |
| } |
| |
| /// \class Options Options.h "lldb/Interpreter/Options.h" |
| /// A command line option parsing protocol class. |
| /// |
| /// Options is designed to be subclassed to contain all needed options for a |
| /// given command. The options can be parsed by calling the Parse function. |
| /// |
| /// The options are specified using the format defined for the libc options |
| /// parsing function getopt_long_only: \code |
| /// #include <getopt.h> |
| /// int getopt_long_only(int argc, char * const *argv, const char |
| /// *optstring, const struct option *longopts, int *longindex); |
| /// \endcode |
| /// |
| class Options { |
| public: |
| Options(); |
| |
| virtual ~Options(); |
| |
| void BuildGetoptTable(); |
| |
| void BuildValidOptionSets(); |
| |
| uint32_t NumCommandOptions(); |
| |
| /// Get the option definitions to use when parsing Args options. |
| /// |
| /// \see Args::ParseOptions (Options&) |
| /// \see man getopt_long_only |
| Option *GetLongOptions(); |
| |
| // This gets passed the short option as an integer... |
| void OptionSeen(int short_option); |
| |
| bool VerifyOptions(CommandReturnObject &result); |
| |
| // Verify that the options given are in the options table and can be used |
| // together, but there may be some required options that are missing (used to |
| // verify options that get folded into command aliases). |
| bool VerifyPartialOptions(CommandReturnObject &result); |
| |
| void OutputFormattedUsageText(Stream &strm, |
| const OptionDefinition &option_def, |
| uint32_t output_max_columns); |
| |
| void GenerateOptionUsage(Stream &strm, CommandObject *cmd, |
| uint32_t screen_width); |
| |
| bool SupportsLongOption(const char *long_option); |
| |
| // The following two pure virtual functions must be defined by every class |
| // that inherits from this class. |
| |
| virtual llvm::ArrayRef<OptionDefinition> GetDefinitions() { |
| return llvm::ArrayRef<OptionDefinition>(); |
| } |
| |
| // Call this prior to parsing any options. This call will call the subclass |
| // OptionParsingStarting() and will avoid the need for all |
| // OptionParsingStarting() function instances from having to call the |
| // Option::OptionParsingStarting() like they did before. This was error prone |
| // and subclasses shouldn't have to do it. |
| void NotifyOptionParsingStarting(ExecutionContext *execution_context); |
| |
| /// Parse the provided arguments. |
| /// |
| /// The parsed options are set via calls to SetOptionValue. In case of a |
| /// successful parse, the function returns a copy of the input arguments |
| /// with the parsed options removed. Otherwise, it returns an error. |
| /// |
| /// param[in] platform_sp |
| /// The platform used for option validation. This is necessary |
| /// because an empty execution_context is not enough to get us |
| /// to a reasonable platform. If the platform isn't given, |
| /// we'll try to get it from the execution context. If we can't |
| /// get it from the execution context, we'll skip validation. |
| /// |
| /// param[in] require_validation |
| /// When true, it will fail option parsing if validation could |
| /// not occur due to not having a platform. |
| llvm::Expected<Args> Parse(const Args &args, |
| ExecutionContext *execution_context, |
| lldb::PlatformSP platform_sp, |
| bool require_validation); |
| |
| llvm::Expected<Args> ParseAlias(const Args &args, |
| OptionArgVector *option_arg_vector, |
| std::string &input_line); |
| |
| OptionElementVector ParseForCompletion(const Args &args, |
| uint32_t cursor_index); |
| |
| Status NotifyOptionParsingFinished(ExecutionContext *execution_context); |
| |
| /// Set the value of an option. |
| /// |
| /// \param[in] option_idx |
| /// The index into the "struct option" array that was returned |
| /// by Options::GetLongOptions(). |
| /// |
| /// \param[in] option_arg |
| /// The argument value for the option that the user entered, or |
| /// nullptr if there is no argument for the current option. |
| /// |
| /// \param[in] execution_context |
| /// The execution context to use for evaluating the option. |
| /// May be nullptr if the option is to be evaluated outside any |
| /// particular context. |
| /// |
| /// \see Args::ParseOptions (Options&) |
| /// \see man getopt_long_only |
| virtual Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, |
| ExecutionContext *execution_context) = 0; |
| |
| /// Handles the generic bits of figuring out whether we are in an option, |
| /// and if so completing it. |
| /// |
| /// \param[in/out] request |
| /// The completion request that we need to act upon. |
| /// |
| /// \param[in] interpreter |
| /// The interpreter that's doing the completing. |
| /// |
| /// FIXME: This is the wrong return value, since we also need to |
| /// make a distinction between total number of matches, and the window the |
| /// user wants returned. |
| /// |
| /// \return |
| /// \btrue if we were in an option, \bfalse otherwise. |
| bool HandleOptionCompletion(lldb_private::CompletionRequest &request, |
| OptionElementVector &option_map, |
| CommandInterpreter &interpreter); |
| |
| /// Handles the generic bits of figuring out whether we are in an option, |
| /// and if so completing it. |
| /// |
| /// \param[in/out] request |
| /// The completion request that we need to act upon. |
| /// |
| /// \param[in] interpreter |
| /// The command interpreter doing the completion. |
| /// |
| /// FIXME: This is the wrong return value, since we also need to |
| /// make a distinction between total number of matches, and the window the |
| /// user wants returned. |
| /// |
| /// \return |
| /// \btrue if we were in an option, \bfalse otherwise. |
| virtual bool |
| HandleOptionArgumentCompletion(lldb_private::CompletionRequest &request, |
| OptionElementVector &opt_element_vector, |
| int opt_element_index, |
| CommandInterpreter &interpreter); |
| |
| protected: |
| // This is a set of options expressed as indexes into the options table for |
| // this Option. |
| typedef std::set<int> OptionSet; |
| typedef std::vector<OptionSet> OptionSetVector; |
| |
| std::vector<Option> m_getopt_table; |
| OptionSet m_seen_options; |
| OptionSetVector m_required_options; |
| OptionSetVector m_optional_options; |
| |
| OptionSetVector &GetRequiredOptions() { |
| BuildValidOptionSets(); |
| return m_required_options; |
| } |
| |
| OptionSetVector &GetOptionalOptions() { |
| BuildValidOptionSets(); |
| return m_optional_options; |
| } |
| |
| bool IsASubset(const OptionSet &set_a, const OptionSet &set_b); |
| |
| size_t OptionsSetDiff(const OptionSet &set_a, const OptionSet &set_b, |
| OptionSet &diffs); |
| |
| void OptionsSetUnion(const OptionSet &set_a, const OptionSet &set_b, |
| OptionSet &union_set); |
| |
| // Subclasses must reset their option values prior to starting a new option |
| // parse. Each subclass must override this function and revert all option |
| // settings to default values. |
| virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0; |
| |
| virtual Status OptionParsingFinished(ExecutionContext *execution_context) { |
| // If subclasses need to know when the options are done being parsed they |
| // can implement this function to do extra checking |
| Status error; |
| return error; |
| } |
| }; |
| |
| class OptionGroup { |
| public: |
| OptionGroup() = default; |
| |
| virtual ~OptionGroup() = default; |
| |
| virtual llvm::ArrayRef<OptionDefinition> GetDefinitions() = 0; |
| |
| virtual Status SetOptionValue(uint32_t option_idx, |
| llvm::StringRef option_value, |
| ExecutionContext *execution_context) = 0; |
| |
| virtual void OptionParsingStarting(ExecutionContext *execution_context) = 0; |
| |
| virtual Status OptionParsingFinished(ExecutionContext *execution_context) { |
| // If subclasses need to know when the options are done being parsed they |
| // can implement this function to do extra checking |
| Status error; |
| return error; |
| } |
| }; |
| |
| class OptionGroupOptions : public Options { |
| public: |
| OptionGroupOptions() |
| : Options(), m_option_defs(), m_option_infos(), m_did_finalize(false) {} |
| |
| ~OptionGroupOptions() override = default; |
| |
| /// Append options from a OptionGroup class. |
| /// |
| /// Append all options from \a group using the exact same option groups that |
| /// each option is defined with. |
| /// |
| /// \param[in] group |
| /// A group of options to take option values from and copy their |
| /// definitions into this class. |
| void Append(OptionGroup *group); |
| |
| /// Append options from a OptionGroup class. |
| /// |
| /// Append options from \a group that have a usage mask that has any bits in |
| /// "src_mask" set. After the option definition is copied into the options |
| /// definitions in this class, set the usage_mask to "dst_mask". |
| /// |
| /// \param[in] group |
| /// A group of options to take option values from and copy their |
| /// definitions into this class. |
| /// |
| /// \param[in] src_mask |
| /// When copying options from \a group, you might only want some of |
| /// the options to be appended to this group. This mask allows you |
| /// to control which options from \a group get added. It also allows |
| /// you to specify the same options from \a group multiple times |
| /// for different option sets. |
| /// |
| /// \param[in] dst_mask |
| /// Set the usage mask for any copied options to \a dst_mask after |
| /// copying the option definition. |
| void Append(OptionGroup *group, uint32_t src_mask, uint32_t dst_mask); |
| |
| void Finalize(); |
| |
| bool DidFinalize() { return m_did_finalize; } |
| |
| Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, |
| ExecutionContext *execution_context) override; |
| |
| void OptionParsingStarting(ExecutionContext *execution_context) override; |
| |
| Status OptionParsingFinished(ExecutionContext *execution_context) override; |
| |
| llvm::ArrayRef<OptionDefinition> GetDefinitions() override { |
| assert(m_did_finalize); |
| return m_option_defs; |
| } |
| |
| const OptionGroup *GetGroupWithOption(char short_opt); |
| |
| struct OptionInfo { |
| OptionInfo(OptionGroup *g, uint32_t i) : option_group(g), option_index(i) {} |
| OptionGroup *option_group; // The group that this option came from |
| uint32_t option_index; // The original option index from the OptionGroup |
| }; |
| typedef std::vector<OptionInfo> OptionInfos; |
| |
| std::vector<OptionDefinition> m_option_defs; |
| OptionInfos m_option_infos; |
| bool m_did_finalize; |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // liblldb_Options_h_ |