aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/include/lldb/Interpreter/Options.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/include/lldb/Interpreter/Options.h')
-rw-r--r--contrib/llvm-project/lldb/include/lldb/Interpreter/Options.h376
1 files changed, 376 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/include/lldb/Interpreter/Options.h b/contrib/llvm-project/lldb/include/lldb/Interpreter/Options.h
new file mode 100644
index 000000000000..9a6a17c2793f
--- /dev/null
+++ b/contrib/llvm-project/lldb/include/lldb/Interpreter/Options.h
@@ -0,0 +1,376 @@
+//===-- 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 LLDB_INTERPRETER_OPTIONS_H
+#define LLDB_INTERPRETER_OPTIONS_H
+
+#include <set>
+#include <vector>
+
+#include "lldb/Utility/Args.h"
+#include "lldb/Utility/CompletionRequest.h"
+#include "lldb/Utility/OptionDefinition.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-private.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.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;
+
+/// \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
+ /// \b true if we were in an option, \b false 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.
+ virtual void
+ 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() = default;
+
+ ~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);
+
+ /// Append selected options from a OptionGroup class.
+ ///
+ /// Append the subset of options from \a group, where the "long_option" value
+ /// is _not_ in \a exclude_long_options.
+ ///
+ /// \param[in] group
+ /// A group of options to take option values from and copy their
+ /// definitions into this class.
+ ///
+ /// \param[in] exclude_long_options
+ /// A set of long option strings which indicate which option values values
+ /// to limit from \a group.
+ void Append(OptionGroup *group,
+ llvm::ArrayRef<llvm::StringRef> exclude_long_options);
+
+ 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 = false;
+};
+
+/// Creates an error that represents the failure to parse an command line option
+/// argument. This creates an error containing all information needed to show
+/// the developer what went wrong when parsing their command. It is recommended
+/// to use this instead of writing an error by hand.
+///
+/// \param[in] option_arg
+/// The argument that was attempted to be parsed.
+///
+/// \param[in] short_option
+/// The short form of the option. For example, if the flag is -f, the short
+/// option is "f".
+///
+/// \param[in] long_option
+/// The long form of the option. This field is optional. If the flag is
+/// --force, then the long option is "force".
+///
+/// \param[in] additional_context
+/// This is extra context that will get included in the error. This field is
+/// optional.
+///
+/// \return
+/// An llvm::Error that contains a standardized format for what went wrong
+/// when parsing and why.
+llvm::Error CreateOptionParsingError(llvm::StringRef option_arg,
+ const char short_option,
+ llvm::StringRef long_option = {},
+ llvm::StringRef additional_context = {});
+
+static constexpr llvm::StringLiteral g_bool_parsing_error_message =
+ "Failed to parse as boolean";
+static constexpr llvm::StringLiteral g_int_parsing_error_message =
+ "Failed to parse as integer";
+static constexpr llvm::StringLiteral g_language_parsing_error_message =
+ "Unknown language";
+
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_OPTIONS_H