diff options
Diffstat (limited to 'include/lldb/Interpreter/Options.h')
-rw-r--r-- | include/lldb/Interpreter/Options.h | 487 |
1 files changed, 487 insertions, 0 deletions
diff --git a/include/lldb/Interpreter/Options.h b/include/lldb/Interpreter/Options.h new file mode 100644 index 000000000000..ac4daa8f579a --- /dev/null +++ b/include/lldb/Interpreter/Options.h @@ -0,0 +1,487 @@ +//===-- Options.h -----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Options_h_ +#define liblldb_Options_h_ + +// C Includes +#include <getopt.h> + +// C++ Includes +#include <set> +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" +#include "lldb/lldb-defines.h" +#include "lldb/Interpreter/Args.h" + +namespace lldb_private { + + static inline bool + isprint8 (int ch) + { + if (ch & 0xffffff00u) + return false; + return isprint(ch); + } + + +//---------------------------------------------------------------------- +/// @class Options Options.h "lldb/Interpreter/Options.h" +/// @brief 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: +/// \code +/// Error Args::ParseOptions (Options &); +/// \endcode +/// +/// 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 +/// +/// Example code: +/// \code +/// #include <getopt.h> +/// #include <string> +/// +/// class CommandOptions : public Options +/// { +/// public: +/// virtual struct option * +/// GetLongOptions() { +/// return g_options; +/// } +/// +/// virtual Error +/// SetOptionValue (uint32_t option_idx, int option_val, const char *option_arg) +/// { +/// Error error; +/// switch (option_val) +/// { +/// case 'g': debug = true; break; +/// case 'v': verbose = true; break; +/// case 'l': log_file = option_arg; break; +/// case 'f': log_flags = strtoull(option_arg, NULL, 0); break; +/// default: +/// error.SetErrorStringWithFormat("unrecognized short option %c", option_val); +/// break; +/// } +/// +/// return error; +/// } +/// +/// CommandOptions (CommandInterpreter &interpreter) : debug (true), verbose (false), log_file (), log_flags (0) +/// {} +/// +/// bool debug; +/// bool verbose; +/// std::string log_file; +/// uint32_t log_flags; +/// +/// static struct option g_options[]; +/// +/// }; +/// +/// struct option CommandOptions::g_options[] = +/// { +/// { "debug", no_argument, NULL, 'g' }, +/// { "log-file", required_argument, NULL, 'l' }, +/// { "log-flags", required_argument, NULL, 'f' }, +/// { "verbose", no_argument, NULL, 'v' }, +/// { NULL, 0, NULL, 0 } +/// }; +/// +/// int main (int argc, const char **argv, const char **envp) +/// { +/// CommandOptions options; +/// Args main_command; +/// main_command.SetArguments(argc, argv, false); +/// main_command.ParseOptions(options); +/// +/// if (options.verbose) +/// { +/// std::cout << "verbose is on" << std::endl; +/// } +/// } +/// \endcode +//---------------------------------------------------------------------- +class Options +{ +public: + + Options (CommandInterpreter &interpreter); + + 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 + //------------------------------------------------------------------ + struct 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 char *text, + uint32_t output_max_columns); + + void + GenerateOptionUsage (Stream &strm, + CommandObject *cmd); + + bool + SupportsLongOption (const char *long_option); + + // The following two pure virtual functions must be defined by every + // class that inherits from this class. + + virtual const OptionDefinition* + GetDefinitions () { return NULL; } + + // 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 (); + + Error + NotifyOptionParsingFinished (); + + //------------------------------------------------------------------ + /// 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 + /// NULL if there is no argument for the current option. + /// + /// + /// @see Args::ParseOptions (Options&) + /// @see man getopt_long_only + //------------------------------------------------------------------ + virtual Error + SetOptionValue (uint32_t option_idx, const char *option_arg) = 0; + + //------------------------------------------------------------------ + /// Handles the generic bits of figuring out whether we are in an + /// option, and if so completing it. + /// + /// @param[in] input + /// The command line parsed into words + /// + /// @param[in] cursor_index + /// The index in \ainput of the word in which the cursor lies. + /// + /// @param[in] char_pos + /// The character position of the cursor in its argument word. + /// + /// @param[in] match_start_point + /// @param[in] match_return_elements + /// See CommandObject::HandleCompletions for a description of + /// how these work. + /// + /// @param[in] interpreter + /// The interpreter that's doing the completing. + /// + /// @param[out] word_complete + /// \btrue if this is a complete option value (a space will be + /// inserted after the completion.) \b false otherwise. + /// + /// @param[out] matches + /// The array of matches returned. + /// + /// 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 (Args &input, + OptionElementVector &option_map, + int cursor_index, + int char_pos, + int match_start_point, + int max_return_elements, + bool &word_complete, + lldb_private::StringList &matches); + + //------------------------------------------------------------------ + /// Handles the generic bits of figuring out whether we are in an + /// option, and if so completing it. + /// + /// @param[in] interpreter + /// The command interpreter doing the completion. + /// + /// @param[in] input + /// The command line parsed into words + /// + /// @param[in] cursor_index + /// The index in \ainput of the word in which the cursor lies. + /// + /// @param[in] char_pos + /// The character position of the cursor in its argument word. + /// + /// @param[in] opt_element_vector + /// The results of the options parse of \a input. + /// + /// @param[in] opt_element_index + /// The position in \a opt_element_vector of the word in \a + /// input containing the cursor. + /// + /// @param[in] match_start_point + /// @param[in] match_return_elements + /// See CommandObject::HandleCompletions for a description of + /// how these work. + /// + /// @param[out] word_complete + /// \btrue if this is a complete option value (a space will + /// be inserted after the completion.) \bfalse otherwise. + /// + /// @param[out] matches + /// The array of matches returned. + /// + /// 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 (Args &input, + int cursor_index, + int char_pos, + OptionElementVector &opt_element_vector, + int opt_element_index, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches); + +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; + + CommandInterpreter &m_interpreter; + std::vector<struct 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 () = 0; + + virtual Error + OptionParsingFinished () + { + // If subclasses need to know when the options are done being parsed + // they can implement this function to do extra checking + Error error; + return error; + } +}; + + class OptionGroup + { + public: + OptionGroup () + { + } + + virtual + ~OptionGroup () + { + } + + virtual uint32_t + GetNumDefinitions () = 0; + + virtual const OptionDefinition* + GetDefinitions () = 0; + + virtual Error + SetOptionValue (CommandInterpreter &interpreter, + uint32_t option_idx, + const char *option_value) = 0; + + virtual void + OptionParsingStarting (CommandInterpreter &interpreter) = 0; + + virtual Error + OptionParsingFinished (CommandInterpreter &interpreter) + { + // If subclasses need to know when the options are done being parsed + // they can implement this function to do extra checking + Error error; + return error; + } + }; + + class OptionGroupOptions : public Options + { + public: + + OptionGroupOptions (CommandInterpreter &interpreter) : + Options (interpreter), + m_option_defs (), + m_option_infos (), + m_did_finalize (false) + { + } + + virtual + ~OptionGroupOptions () + { + } + + + //---------------------------------------------------------------------- + /// 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 (); + + virtual Error + SetOptionValue (uint32_t option_idx, + const char *option_arg); + + virtual void + OptionParsingStarting (); + + virtual Error + OptionParsingFinished (); + + const OptionDefinition* + GetDefinitions () + { + assert (m_did_finalize); + return &m_option_defs[0]; + } + 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_ |