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