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