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