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