blob: 6ecf08d28e750fa856c15cabe8f5853d3398a168 [file] [log] [blame]
//===-- 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
// 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
//------------------------------------------------------------------
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);
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);
CommandInterpreter&
GetInterpreter()
{
return m_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;
CommandInterpreter &m_interpreter;
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 () = 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 ();
bool
DidFinalize ()
{
return m_did_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];
}
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_