Home | History | Annotate | Download | only in Option
      1 //===- Option.h - Abstract Driver Options -----------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #ifndef LLVM_OPTION_OPTION_H
     11 #define LLVM_OPTION_OPTION_H
     12 
     13 #include "llvm/ADT/SmallVector.h"
     14 #include "llvm/ADT/StringRef.h"
     15 #include "llvm/Option/OptSpecifier.h"
     16 #include "llvm/Option/OptTable.h"
     17 #include "llvm/Support/ErrorHandling.h"
     18 #include <cassert>
     19 #include <string>
     20 
     21 namespace llvm {
     22 
     23 class raw_ostream;
     24 
     25 namespace opt {
     26 
     27 class Arg;
     28 class ArgList;
     29 
     30 /// ArgStringList - Type used for constructing argv lists for subprocesses.
     31 using ArgStringList = SmallVector<const char *, 16>;
     32 
     33 /// Base flags for all options. Custom flags may be added after.
     34 enum DriverFlag {
     35   HelpHidden       = (1 << 0),
     36   RenderAsInput    = (1 << 1),
     37   RenderJoined     = (1 << 2),
     38   RenderSeparate   = (1 << 3)
     39 };
     40 
     41 /// Option - Abstract representation for a single form of driver
     42 /// argument.
     43 ///
     44 /// An Option class represents a form of option that the driver
     45 /// takes, for example how many arguments the option has and how
     46 /// they can be provided. Individual option instances store
     47 /// additional information about what group the option is a member
     48 /// of (if any), if the option is an alias, and a number of
     49 /// flags. At runtime the driver parses the command line into
     50 /// concrete Arg instances, each of which corresponds to a
     51 /// particular Option instance.
     52 class Option {
     53 public:
     54   enum OptionClass {
     55     GroupClass = 0,
     56     InputClass,
     57     UnknownClass,
     58     FlagClass,
     59     JoinedClass,
     60     ValuesClass,
     61     SeparateClass,
     62     RemainingArgsClass,
     63     RemainingArgsJoinedClass,
     64     CommaJoinedClass,
     65     MultiArgClass,
     66     JoinedOrSeparateClass,
     67     JoinedAndSeparateClass
     68   };
     69 
     70   enum RenderStyleKind {
     71     RenderCommaJoinedStyle,
     72     RenderJoinedStyle,
     73     RenderSeparateStyle,
     74     RenderValuesStyle
     75   };
     76 
     77 protected:
     78   const OptTable::Info *Info;
     79   const OptTable *Owner;
     80 
     81 public:
     82   Option(const OptTable::Info *Info, const OptTable *Owner);
     83 
     84   bool isValid() const {
     85     return Info != nullptr;
     86   }
     87 
     88   unsigned getID() const {
     89     assert(Info && "Must have a valid info!");
     90     return Info->ID;
     91   }
     92 
     93   OptionClass getKind() const {
     94     assert(Info && "Must have a valid info!");
     95     return OptionClass(Info->Kind);
     96   }
     97 
     98   /// \brief Get the name of this option without any prefix.
     99   StringRef getName() const {
    100     assert(Info && "Must have a valid info!");
    101     return Info->Name;
    102   }
    103 
    104   const Option getGroup() const {
    105     assert(Info && "Must have a valid info!");
    106     assert(Owner && "Must have a valid owner!");
    107     return Owner->getOption(Info->GroupID);
    108   }
    109 
    110   const Option getAlias() const {
    111     assert(Info && "Must have a valid info!");
    112     assert(Owner && "Must have a valid owner!");
    113     return Owner->getOption(Info->AliasID);
    114   }
    115 
    116   /// \brief Get the alias arguments as a \0 separated list.
    117   /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0".
    118   const char *getAliasArgs() const {
    119     assert(Info && "Must have a valid info!");
    120     assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) &&
    121            "AliasArgs should be either 0 or non-empty.");
    122 
    123     return Info->AliasArgs;
    124   }
    125 
    126   /// \brief Get the default prefix for this option.
    127   StringRef getPrefix() const {
    128     const char *Prefix = *Info->Prefixes;
    129     return Prefix ? Prefix : StringRef();
    130   }
    131 
    132   /// \brief Get the name of this option with the default prefix.
    133   std::string getPrefixedName() const {
    134     std::string Ret = getPrefix();
    135     Ret += getName();
    136     return Ret;
    137   }
    138 
    139   unsigned getNumArgs() const { return Info->Param; }
    140 
    141   bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;}
    142 
    143   RenderStyleKind getRenderStyle() const {
    144     if (Info->Flags & RenderJoined)
    145       return RenderJoinedStyle;
    146     if (Info->Flags & RenderSeparate)
    147       return RenderSeparateStyle;
    148     switch (getKind()) {
    149     case GroupClass:
    150     case InputClass:
    151     case UnknownClass:
    152       return RenderValuesStyle;
    153     case JoinedClass:
    154     case JoinedAndSeparateClass:
    155       return RenderJoinedStyle;
    156     case CommaJoinedClass:
    157       return RenderCommaJoinedStyle;
    158     case FlagClass:
    159     case ValuesClass:
    160     case SeparateClass:
    161     case MultiArgClass:
    162     case JoinedOrSeparateClass:
    163     case RemainingArgsClass:
    164     case RemainingArgsJoinedClass:
    165       return RenderSeparateStyle;
    166     }
    167     llvm_unreachable("Unexpected kind!");
    168   }
    169 
    170   /// Test if this option has the flag \a Val.
    171   bool hasFlag(unsigned Val) const {
    172     return Info->Flags & Val;
    173   }
    174 
    175   /// getUnaliasedOption - Return the final option this option
    176   /// aliases (itself, if the option has no alias).
    177   const Option getUnaliasedOption() const {
    178     const Option Alias = getAlias();
    179     if (Alias.isValid()) return Alias.getUnaliasedOption();
    180     return *this;
    181   }
    182 
    183   /// getRenderName - Return the name to use when rendering this
    184   /// option.
    185   StringRef getRenderName() const {
    186     return getUnaliasedOption().getName();
    187   }
    188 
    189   /// matches - Predicate for whether this option is part of the
    190   /// given option (which may be a group).
    191   ///
    192   /// Note that matches against options which are an alias should never be
    193   /// done -- aliases do not participate in matching and so such a query will
    194   /// always be false.
    195   bool matches(OptSpecifier ID) const;
    196 
    197   /// accept - Potentially accept the current argument, returning a
    198   /// new Arg instance, or 0 if the option does not accept this
    199   /// argument (or the argument is missing values).
    200   ///
    201   /// If the option accepts the current argument, accept() sets
    202   /// Index to the position where argument parsing should resume
    203   /// (even if the argument is missing values).
    204   ///
    205   /// \param ArgSize The number of bytes taken up by the matched Option prefix
    206   ///                and name. This is used to determine where joined values
    207   ///                start.
    208   Arg *accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const;
    209 
    210   void print(raw_ostream &O) const;
    211   void dump() const;
    212 };
    213 
    214 } // end namespace opt
    215 
    216 } // end namespace llvm
    217 
    218 #endif // LLVM_OPTION_OPTION_H
    219