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