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 isValid()83 bool isValid() const { 84 return Info != nullptr; 85 } 86 getID()87 unsigned getID() const { 88 assert(Info && "Must have a valid info!"); 89 return Info->ID; 90 } 91 getKind()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. getName()98 StringRef getName() const { 99 assert(Info && "Must have a valid info!"); 100 return Info->Name; 101 } 102 getGroup()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 getAlias()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". getAliasArgs()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. getPrefix()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. getPrefixedName()132 std::string getPrefixedName() const { 133 std::string Ret(getPrefix()); 134 Ret += getName(); 135 return Ret; 136 } 137 138 /// Get the help text for this option. getHelpText()139 StringRef getHelpText() const { 140 assert(Info && "Must have a valid info!"); 141 return Info->HelpText; 142 } 143 144 /// Get the meta-variable list for this option. getMetaVar()145 StringRef getMetaVar() const { 146 assert(Info && "Must have a valid info!"); 147 return Info->MetaVar; 148 } 149 getNumArgs()150 unsigned getNumArgs() const { return Info->Param; } 151 hasNoOptAsInput()152 bool hasNoOptAsInput() const { return Info->Flags & RenderAsInput;} 153 getRenderStyle()154 RenderStyleKind getRenderStyle() const { 155 if (Info->Flags & RenderJoined) 156 return RenderJoinedStyle; 157 if (Info->Flags & RenderSeparate) 158 return RenderSeparateStyle; 159 switch (getKind()) { 160 case GroupClass: 161 case InputClass: 162 case UnknownClass: 163 return RenderValuesStyle; 164 case JoinedClass: 165 case JoinedAndSeparateClass: 166 return RenderJoinedStyle; 167 case CommaJoinedClass: 168 return RenderCommaJoinedStyle; 169 case FlagClass: 170 case ValuesClass: 171 case SeparateClass: 172 case MultiArgClass: 173 case JoinedOrSeparateClass: 174 case RemainingArgsClass: 175 case RemainingArgsJoinedClass: 176 return RenderSeparateStyle; 177 } 178 llvm_unreachable("Unexpected kind!"); 179 } 180 181 /// Test if this option has the flag \a Val. hasFlag(unsigned Val)182 bool hasFlag(unsigned Val) const { 183 return Info->Flags & Val; 184 } 185 186 /// getUnaliasedOption - Return the final option this option 187 /// aliases (itself, if the option has no alias). getUnaliasedOption()188 const Option getUnaliasedOption() const { 189 const Option Alias = getAlias(); 190 if (Alias.isValid()) return Alias.getUnaliasedOption(); 191 return *this; 192 } 193 194 /// getRenderName - Return the name to use when rendering this 195 /// option. getRenderName()196 StringRef getRenderName() const { 197 return getUnaliasedOption().getName(); 198 } 199 200 /// matches - Predicate for whether this option is part of the 201 /// given option (which may be a group). 202 /// 203 /// Note that matches against options which are an alias should never be 204 /// done -- aliases do not participate in matching and so such a query will 205 /// always be false. 206 bool matches(OptSpecifier ID) const; 207 208 /// accept - Potentially accept the current argument, returning a 209 /// new Arg instance, or 0 if the option does not accept this 210 /// argument (or the argument is missing values). 211 /// 212 /// If the option accepts the current argument, accept() sets 213 /// Index to the position where argument parsing should resume 214 /// (even if the argument is missing values). 215 /// 216 /// \p CurArg The argument to be matched. It may be shorter than the 217 /// underlying storage to represent a Joined argument. 218 /// \p GroupedShortOption If true, we are handling the fallback case of 219 /// parsing a prefix of the current argument as a short option. 220 Arg *accept(const ArgList &Args, StringRef CurArg, bool GroupedShortOption, 221 unsigned &Index) const; 222 223 private: 224 Arg *acceptInternal(const ArgList &Args, StringRef CurArg, 225 unsigned &Index) const; 226 227 public: 228 void print(raw_ostream &O) const; 229 void dump() const; 230 }; 231 232 } // end namespace opt 233 234 } // end namespace llvm 235 236 #endif // LLVM_OPTION_OPTION_H 237